001/*
002 * Renderer 9. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.scene;
008
009/**
010   We use two steps to transform the camera's configurable orthographic
011   view volume into the standard orthographic view volume. The first step
012   translates the camera's view volume so that its center line is the z-axis.
013   The second step scales the translated view volume so that it intersects
014   the image plane, {@code z = -1}, with corners {@code (-1, -1, -1)}
015   and {@code (+1, +1, -1)}.
016<p>
017   This matrix translates the camera's view volume so that the translated
018   view volume will be centered on the z-axis.
019   <pre>{@code
020     [ 1  0  0  -(r+l)/2 ]
021     [ 0  1  0  -(t+b)/2 ]
022     [ 0  0  1      0    ]
023     [ 0  0  0      1    ]
024   }</pre>
025   This matrix scales the translated view volume so that it will be
026   2 units wide and 2 units tall at the image plane {@code z = -1}.
027   <pre>{@code
028     [ 2/(r-l)    0     0  0 ]
029     [   0     2/(t-b)  0  0 ]
030     [   0        0     1  0 ]
031     [   0        0     0  1 ]
032   }</pre>
033   The matrix product looks like this.
034   <pre>{@code
035     [ 1  0  0  -(r+l)/2 ]   [ 2/(r-l)    0     0  0 ]
036     [ 0  1  0  -(t+b)/2 ] = [   0     2/(t-b)  0  0 ]
037     [ 0  0  1      0    ]   [   0        0     1  0 ]
038     [ 0  0  0      1    ]   [   0        0     0  1 ]
039
040          [ 2/(r-l)    0    0  -(r+l)/2 ]
041        = [   0     2/(t-b) 0  -(t+b)/2 ]
042          [   0        0    1      0    ]
043          [   0        0    0      1    ]
044   }</pre>
045   This product matrix transforms the camera's configurable orthographic
046   view volume into the standard normalized orthographic view volume
047   whose intersection with the image plane, {@code z = -1}, has
048   {@code left = -1}, {@code right = +1}, {@code bottom = -1},
049   and {@code top = +1}.
050*/
051public final class OrthographicNormalizeMatrix
052{
053   /**
054      This is a static factory method.
055      <p>
056      Construct the {@link Matrix} that transforms from the
057      {@link Camera}'s orthographic view coordinate system to
058      the normalized orthographic camera coordinate system.
059
060      @param l  left edge of view rectangle
061      @param r  right edge of view rectangle
062      @param b  bottom edge of view rectangle
063      @param t  top edge of view rectangle
064      @return a new {@code Matrix} object containing the orthographic normalization matrix
065   */
066   public static Matrix build(final double l, final double r,
067                              final double b, final double t)
068   {
069      final Matrix m1, m2;
070
071      m1 = Matrix.buildFromColumns(
072               new Vector(  1.0,      0.0,    0.0, 0.0),
073               new Vector(  0.0,      1.0,    0.0, 0.0),
074               new Vector(  0.0,      0.0,    1.0, 0.0),
075               new Vector(-(r+l)/2, -(t+b)/2, 0.0, 1.0));
076
077      m2 = Matrix.buildFromColumns(
078               new Vector(2/(r-l),   0.0,   0.0, 0.0),
079               new Vector(   0.0,  2/(t-b), 0.0, 0.0),
080               new Vector(   0.0,    0.0,   1.0, 0.0),
081               new Vector(   0.0,    0.0,   0.0, 1.0));
082
083      return m2.times(m1);
084   }
085}