001/* 002 003*/ 004 005package renderer.pipeline; 006import renderer.scene.*; 007 008/** 009 Project each {@link Vertex} of a {@link LineSegment} from camera 010 coordinates to the {@link Camera}'s image plane {@code z = -1}. 011<p> 012 Let us derive the formulas for the perspective projection 013 transformation (the formulas for the parallel projection 014 transformation are pretty obvious). We will derive the 015 x-coordinate formula; the y-coordinate formula is similar. 016<p> 017 Let {@code (x_c, y_c, z_c)} denote a point in the 3-dimensional 018 camera coordinate system. Let {@code (x_p, y_p, -1)} denote the 019 point's perspective projection into the image plane, {@code z = -1}. 020 Here is a "picture" of just the xz-plane from camera space. This 021 picture shows the point {@code (x_c, z_c)} and its projection to 022 the point {@code (x_p, -1)} in the image plane. 023<pre>{@code 024 x 025 | / 026 | / 027 x_c + + (x_c, z_c) 028 | / | 029 | / | 030 | / | 031 | / | 032 | / | 033 | / | 034 x_p + + | 035 | / | | 036 | / | | 037 | / | | 038 | / | | 039 | / | | 040 +-----------+-------------+------------> -z 041 (0,0) -1 z_c 042}</pre> 043<p> 044 We are looking for a formula that computes {@code x_p} in terms of 045 {@code x_c} and {@code z_c}. There are two similar triangles in this 046 picture that share a vertex at the origin. Using the properties of 047 similar triangles we have the following ratios. (Remember that these 048 are ratios of positive lengths, so we write {@code -z_c}, since 049 {@code z_c} is on the negative z-axis). 050<pre>{@code 051 x_p x_c 052 ----- = ----- 053 1 -z_c 054}</pre> 055<p> 056 If we solve this ratio for the unknown, {@code x_p}, we get the 057 projection formula, 058<pre>{@code 059 x_p = -x_c / z_c. 060}</pre> 061<p> 062 The equivalent formula for the y-coordinate is 063<pre>{@code 064 y_p = -y_c / z_c. 065}</pre> 066*/ 067public class Projection 068{ 069 /** 070 Project each {@link Vertex} from a {@link LineSegment} to 071 the {@link Camera}'s image plane {@code z = -1}. 072 073 @param ls {@code LineSegment} to project onto the image plane 074 @param camera a reference to the {@link Scene}'s {@code Camera} object 075 */ 076 public static void project(LineSegment ls, Camera camera) 077 { 078 // For each vertex in the line segment, 079 // compute its projected (x,y) coordinates. 080 if ( camera.perspective ) 081 { 082 // calculate the perspective projection 083 ls.v[0].x = ls.v[0].x / -ls.v[0].z; // xp = xc / -zc 084 ls.v[0].y = ls.v[0].y / -ls.v[0].z; // yp = yc / -zc 085 ls.v[0].z = -1; // zp = -1 086 ls.v[1].x = ls.v[1].x / -ls.v[1].z; 087 ls.v[1].y = ls.v[1].y / -ls.v[1].z; 088 ls.v[1].z = -1; 089 } 090 else 091 { 092 // calculate the parallel projection 093 // xp = xc 094 // yp = yc 095 ls.v[0].z = 0; // zp = 0 096 ls.v[1].z = 0; 097 } 098 } 099}