001/*
002 * Renderer 9. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.pipeline;
008
009import renderer.scene.*;
010
011import java.util.List;
012import java.util.ArrayList;
013
014/**
015   Transform each {@link Vertex} of a {@link Model} from the
016   {@link Camera}'s (shared) view coordinates to normalized
017   camera coordinates.
018<p>
019   This stage transforms the {@link Camera}'s view volume
020   from a user defined shape (in the view coordinate system)
021   into the standard normalized view volume (in the camera
022   coordinate system) used by the {@link Clip} pipeline stage.
023<p>
024   There are two standard normalized view volumes, one for
025   perspective projection and one for orthographic projection.
026<p>
027   The standard normalized perspective view volume is the infinitely
028   long pyramid with its apex at the origin and intersecting the
029   image plane {@code z = -1} at the corners {@code (-1, -1, -1)}
030   and {@code (+1, +1, -1)}.
031<p>
032   The standard normalized orthographic view volume is the infinitely
033   long parallelepiped centered on the z-axis and intersecting the
034   image plane {@code z = -1} at the corners {@code (-1, -1, -1)}
035   and {@code (+1, +1, -1)}.
036<p>
037   The user defined view volume determined by the {@link Scene}'s
038   {@link Camera} object is either the infinitely long pyramid with its
039   apex at the origin and intersecting the image plane {@code z = -1} at
040   the corners {@code (left, bottom, -1)} and {@code (right, top, -1)},
041   or it is the infinitely long parallelepiped parallel to the z-axis
042   and intersecting the image plane {@code z = -1} at the corners
043   {@code (left, bottom, -1)} and {@code (right, top, -1)}.
044<p>
045   The view coordinate system is relative to the user defined view volume.
046<p>
047   The normalized camera coordinate system is relative to the normalized
048   view volume.
049<p>
050   The matrix that transforms the user defined view volume into the
051   normalized view volume also transform the view coordinate system
052   into the normalized camera coordinate system.
053<p>
054   The matrix that transforms view coordinates into normalized camera
055   coordinates is derived in the comments of
056   {@link PerspectiveNormalizeMatrix} and
057   {@link OrthographicNormalizeMatrix}.
058*/
059public final class View2Camera
060{
061   /**
062      Use the {@link Camera}'s normalizing {@link Matrix} to transform each
063      {@link Vertex} from the {@link Camera}'s view coordinate system to the
064      normalized camera coordinate system.
065
066      @param model  {@link Model} with {@link Vertex} objects in the camera's view coordinate system
067      @param camera  the {@link Scene}'s {@link Camera} with the normalizing {@link Matrix}
068      @return a new {@link Model} with {@link Vertex} objects in the normalized camera coordinate system
069   */
070   public static Model view2camera(final Model model, final Camera camera)
071   {
072      final Matrix normalizeMatrix = camera.getNormalizeMatrix();
073
074      // A new vertex list to hold the transformed vertices.
075      final List<Vertex> newVertexList =
076                            new ArrayList<>(model.vertexList.size());
077
078      // Replace each Vertex object with one that
079      // contains normalized camera coordinates.
080      for (final Vertex v : model.vertexList)
081      {
082         newVertexList.add( normalizeMatrix.times(v) );
083      }
084
085      return new Model(newVertexList,
086                       model.primitiveList,
087                       model.colorList,
088                       model.name,
089                       model.visible);
090   }
091
092
093
094   // Private default constructor to enforce noninstantiable class.
095   // See Item 4 in "Effective Java", 3rd Ed, Joshua Bloch.
096   private View2Camera() {
097      throw new AssertionError();
098   }
099}