001/*
002 * Renderer Models. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.models_L;
008
009import renderer.scene.*;
010import renderer.scene.primitives.*;
011
012/**
013   Create a wireframe model of a camera's perspective view frustum.
014   That is, create a frustum of a pyramid along the negative z-axis
015   with its apex at the origin.
016<p>
017   This class has two constructors that mimic the projPerspective()
018   methods from the {@link Camera} class.
019<p>
020   See <a href="https://en.wikipedia.org/wiki/Viewing_frustum" target="_top">
021                https://en.wikipedia.org/wiki/Viewing_frustum</a>
022*/
023public class ViewFrustumModel extends Model
024{
025   /**
026      Create a frustum of a pyramid along the negative z-axis with
027      a front face at {@code z = -0.25}, a back face at {@code z = -1},
028      and the front face bounded by {@code -0.25 <= x <= 0.25} and
029      {@code -0.25 <= y <= 0.25}.
030   */
031   public ViewFrustumModel( )
032   {
033      this(-0.25, 0.25, -0.25, 0.25, 0.25, 1);
034   }
035
036
037   /**
038      Create a frustum of a pyramid along the negative z-axis that
039      mimics a {@link Camera}'s perspective view volume.
040
041      @param left    left edge of the front face in the plane z = -near
042      @param right   right edge of the front face in the plane z = -near
043      @param bottom  bottom edge of the front face in the plane z = -near
044      @param top     top edge of the front face in the plane z = -near
045      @param near    distance from the origin to the front face
046      @param far     distance from the origin to the back face
047   */
048   public ViewFrustumModel(final double left,   final double right,
049                           final double bottom, final double top,
050                           final double near,   final double far)
051   {
052      super("View Frustum Model");
053
054      addVertex(new Vertex(left,  top,    -near),
055                new Vertex(right, top,    -near),
056                new Vertex(right, bottom, -near),
057                new Vertex(left,  bottom, -near),
058                new Vertex( (left/near)*far,    (top/near)*far, -far),
059                new Vertex((right/near)*far,    (top/near)*far, -far),
060                new Vertex((right/near)*far, (bottom/near)*far, -far),
061                new Vertex( (left/near)*far, (bottom/near)*far, -far));
062
063      // front (near) face
064      addPrimitive(new LineSegment(0, 1),
065                   new LineSegment(1, 2),
066                   new LineSegment(2, 3),
067                   new LineSegment(3, 0));
068      // back (far) face
069      addPrimitive(new LineSegment(4, 5),
070                   new LineSegment(5, 6),
071                   new LineSegment(6, 7),
072                   new LineSegment(7, 4));
073      // lines from front to back
074      addPrimitive(new LineSegment(0, 4),
075                   new LineSegment(1, 5),
076                   new LineSegment(2, 6),
077                   new LineSegment(3, 7));
078   }
079
080
081   /**
082      Here, the frustum is determined by a vertical "field of view"
083      angle and an aspect ratio for the front face.
084
085      @param fovy    angle in the y-direction subtended by the front face
086      @param aspect  aspect ratio of the front face
087      @param near    distance from the origin to the front face
088      @param far     distance from the origin to the back face
089   */
090   public ViewFrustumModel(final double fovy, final double aspect,
091                           final double near, final double far)
092   {
093      // top    =  near * Math.tan((Math.PI/180.0)*fovy/2.0)
094      // left   = -top * aspect
095      // right  =  top * aspect
096      // bottom = -top
097      this(-near * Math.tan((Math.PI/180.0)*fovy/2.0) * aspect,
098            near * Math.tan((Math.PI/180.0)*fovy/2.0) * aspect,
099           -near * Math.tan((Math.PI/180.0)*fovy/2.0),
100            near * Math.tan((Math.PI/180.0)*fovy/2.0),
101            near,
102            far);
103   }
104}//ViewFrustumModel