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