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}