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