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 cube with its center
014   at the origin, having edge length 2, and with its
015   corners at {@code (±1, ±1, ±1)}.
016<p>
017   This version of the cube model has the top and bottom
018   faces of the cube cut up by a triangle fan and the
019   front, back, right, and left faces cut up by a grid
020   of perpendicular lines.
021<p>
022   Here is a picture showing how the cube's eight
023   corners are labeled.
024<pre>{@code
025                  v4=(-1,1,-1)
026                  +---------------------+ v5=(1,1,-1)
027                 /|                    /|
028                / |                   / |
029               /  |                  /  |
030              /   |                 /   |
031             /    |                /    |
032         v7 +---------------------+ v6  |
033            |     |               |     |
034            |     |               |     |
035            |     | v0=(-1,-1,-1) |     |
036            |     +---------------|-----+ v1=(1,-1,-1)
037            |    /                |    /
038            |   /                 |   /
039            |  /                  |  /
040            | /                   | /
041            |/                    |/
042            +---------------------+
043            v3=(-1,-1,1)          v2=(1,-1,1)
044}</pre>
045
046   @see Cube
047   @see Cube2
048   @see Cube3
049*/
050public class Cube4 extends Model
051{
052   /**
053      Create a cube with its center at the origin, having edge
054      length 2, with its corners at {@code (±1, ±1, ±1)}. with
055      a triangle fan of eight triangles in top and bottom faces,
056      and two perpendicular lines cutting each of the front,
057      back, right, and left faces.
058   */
059   public Cube4( )
060   {
061      this(2, 1, 2);
062   }
063
064
065   /**
066      Create a cube with its center at the origin, having edge
067      length 2, with its corners at {@code (±1, ±1, ±1)}, and
068      with the top and bottom faces containing a triangle fan
069      with the given number of triangles along each of the x,
070      and z directions.
071      <p>
072      There must be at least one triangle along the x and z directions.
073
074      @param xCount  number of triangles along the x-direction
075      @param yGrid   number of grid lines perpendicular to the y-axis
076      @param zCount  number of triangles along the z-direction
077      @throws IllegalArgumentException if {@code xCount} is less than 1
078      @throws IllegalArgumentException if {@code yGrid} is less than 0
079      @throws IllegalArgumentException if {@code zCount} is less than 1
080   */
081   public Cube4(final int xCount, final int yGrid, final int zCount)
082   {
083      super(String.format("Cube4(%d,%d,%d)", xCount, yGrid, zCount));
084
085      if (xCount < 1)
086         throw new IllegalArgumentException("xCount must be greater than or equal to 1");
087      if (yGrid < 0)
088         throw new IllegalArgumentException("yGrid must be greater than or equal to 0");
089      if (zCount < 1)
090         throw new IllegalArgumentException("zCount must be greater than or equal to 1");
091
092      final double xStep = 2.0 / xCount,
093                   yStep = 2.0 / (1 + yGrid),
094                   zStep = 2.0 / zCount;
095
096      // An array of vertices to be used to create primitives.
097      final Vertex[][] v = new Vertex[2 + yGrid][2*xCount + 2*zCount];
098
099      // Create all the vertices.
100      for (int i = 0; i < 2 + yGrid; ++i) // choose a height of latitude
101      {
102         for(int j = 0; j < xCount; ++j)
103         {
104            v[i][j] = new Vertex(-1 + j*xStep, // move right
105                                 -1 + i*yStep,
106                                 -1);
107         }
108         for(int j = 0; j < zCount; ++j)
109         {
110            v[i][xCount + j] = new Vertex( 1,
111                                          -1 + i*yStep,
112                                          -1 + j*zStep); // move forward
113         }
114         for(int j = 0; j < xCount; ++j)
115         {
116            v[i][xCount+zCount + j] = new Vertex( 1 - j*xStep, // move left
117                                                 -1 + i*yStep,
118                                                  1);
119         }
120         for(int j = 0; j < zCount; ++j)
121         {
122            v[i][2*xCount+zCount + j] = new Vertex(-1,
123                                                   -1 + i*yStep,
124                                                    1 - j*zStep); // backwards
125         }
126      }
127
128      // Add all of the vertices to this model.
129      for (int i = 0; i < 2 + yGrid; ++i)
130      {
131         for (int j = 0; j < 2*xCount + 2*zCount; ++j)
132         {
133            addVertex( v[i][j] );
134         }
135      }
136      addVertex(new Vertex(0, -1,  0),  // center bottom
137                new Vertex(0,  1,  0)); // center top
138      final int cBottom = (2 + yGrid) * (2*xCount + 2*zCount);
139      final int cTop = cBottom + 1;
140
141      // Create the line fans in the cube's bottom and top sides.
142      for (int j = 0; j < 2*xCount + 2*zCount; ++j)
143      {
144         addPrimitive(
145            new LineSegment(cBottom,
146                            j),                                // v[0][j]
147            new LineSegment(cTop,
148                            (yGrid+1)*(2*xCount+2*zCount)+j)); // v[2+yGrid-1][j]
149      }
150
151      // Create all the loops around the cube's vertical sides.
152      for (int i = 0; i < 2 + yGrid; ++i) // choose a height of latitude
153      {
154         for (int j = 0; j < 2*xCount + 2*zCount - 1; ++j)
155         {
156            addPrimitive(
157               new LineSegment(i*(2*xCount+2*zCount)+j,     // v[i][j]
158                               i*(2*xCount+2*zCount)+j+1)); // v[i][j+1]
159         }
160         addPrimitive(
161            new LineSegment((1+i)*(2*xCount+2*zCount) - 1, // v[i][2*xCount + 2*zCount-1]
162                               i *(2*xCount+2*zCount)));   // v[i][0]
163      }
164
165      // Create all the vertical lines in the cube's vertical sides.
166      for (int j = 0; j < 2*xCount + 2*zCount; ++j)
167      {
168         for (int i = 0; i < 2 + yGrid - 1; ++i) // choose a height of latitude
169         {
170            addPrimitive(
171               new LineSegment(   i *(2*xCount+2*zCount)+j,    // v[i  ][j]
172                               (i+1)*(2*xCount+2*zCount)+j));  // v[i+1][j]
173         }
174      }
175
176
177   }
178}//Cube4