001/*
002 * Renderer 4. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.scene.primitives;
008
009import java.util.List;
010import java.util.ArrayList;
011
012/**
013   A {@code Primitive} is something that we can build
014   geometric shapes out of (a "graphics primitive").
015<p>
016   See <a href="https://en.wikipedia.org/wiki/Geometric_primitive" target="_top">
017                https://en.wikipedia.org/wiki/Geometric_primitive</a>
018<p>
019   We have two geometric primitives,
020   <ul>
021   <li>{@link LineSegment},
022   <li>{@link Point}.
023   </ul>
024<p>
025   Each {@code Primitive} holds two lists of integer indices.
026<p>
027   One list is of indices into its {@link renderer.scene.Model}'s
028   {@link List} of {@link renderer.scene.Vertex} objects. These
029   are the vertices that determine the primitive's geometry.
030<p>
031   The other list is of indices into its {@link renderer.scene.Model}'s
032   {@link List} of {@link java.awt.Color} objects.
033<p>
034   The two lists of integer indices must always have the same
035   length. For every {@link renderer.scene.Vertex} index in a
036   {@code Primitive} there must be a {@link java.awt.Color} index.
037*/
038/*
039   NOTE: The Primitive class could be an inner class of
040         the Model class. Then each Primitive object would
041         automatically have access to the actual Vertex and
042         Color lists that the Primitive is indexing into.
043*/
044public abstract class Primitive
045{
046   // A Primitive object is made up of indices to vertices and colors in a Model.
047   public final List<Integer> vIndexList; // indices for this primitive's vertices
048   public final List<Integer> cIndexList; // indices for this primitive's colors
049
050   /**
051      Construct an empty {@code Primitive}.
052   */
053   protected Primitive()
054   {
055      this.vIndexList = new ArrayList<>();
056      this.cIndexList = new ArrayList<>();
057   }
058
059
060   /**
061      Construct a {@code Primitive} with the given array of indices for the
062      {@link renderer.scene.Vertex} and {@link java.awt.Color} index lists.
063      <p>
064      NOTE: This constructor does not put any {@link renderer.scene.Vertex}
065      or {@link java.awt.Color} objects into this {@link Primitive}'s
066      {@link renderer.scene.Model} object. This constructor assumes that
067      the given indices are valid (or will be valid by the time this
068      {@link Primitive} gets rendered).
069
070      @param indices  array of {@link renderer.scene.Vertex} and {@link java.awt.Color} indices to place in this {@code Primitive}
071   */
072   protected Primitive(final int... indices)
073   {
074      this();
075
076      for (final int i : indices)
077      {
078         addIndices(i, i);
079      }
080   }
081
082
083   /**
084      Construct a {@code Primitive} object using the two given
085      {@link List}s of integer indices.
086      <p>
087      NOTE: This constructor does not put any {@link renderer.scene.Vertex}
088      or {@link java.awt.Color} objects into this {@link Primitive}'s
089      {@link renderer.scene.Model} object. This constructor assumes that
090      the given indices are valid (or will be valid by the time this
091      {@link Primitive} gets rendered).
092
093      @param vIndexList  {@link List} of integer indices into a {@link renderer.scene.Vertex} list
094      @param cIndexList  {@link List} of integer indices into a {@link java.awt.Color} list
095      @throws NullPointerException if {@code vIndexList} is {@code null}
096      @throws NullPointerException if {@code cIndexList} is {@code null}
097      @throws IllegalArgumentException if {@code vIndexList} and {@code cIndexList} are not the same size
098   */
099   protected Primitive(final List<Integer> vIndexList,
100                       final List<Integer> cIndexList)
101   {
102      if (null == vIndexList)
103         throw new NullPointerException("vIndexList must not be null");
104      if (null == cIndexList)
105         throw new NullPointerException("cIndexList must not be null");
106      if (vIndexList.size() != cIndexList.size() )
107         throw new IllegalArgumentException("vIndexList and cIndexList must be the same size");
108
109      this.vIndexList = vIndexList;
110      this.cIndexList = cIndexList;
111   }
112
113
114   /**
115      Add the given array of indices to the {@link renderer.scene.Vertex}
116      and {@link java.awt.Color} index lists.
117      <p>
118      NOTE: This method does not put any {@link renderer.scene.Vertex}
119      or {@link java.awt.Color} objects into this {@link Primitive}'s
120      {@link renderer.scene.Model} object. This method assumes that
121      the given indices are valid (or will be valid by the time this
122      {@link Primitive} gets rendered).
123
124      @param indices  array of {@link renderer.scene.Vertex} and {@link java.awt.Color} indices to add to this {@code Primitive}
125   */
126   public void addIndex(final int... indices)
127   {
128      for (final int i : indices)
129      {
130         addIndices(i, i);
131      }
132   }
133
134
135   /**
136      Add the given indices to the {@link renderer.scene.Vertex} and
137      {@link java.awt.Color} index lists.
138      <p>
139      NOTE: This method does not put any {@link renderer.scene.Vertex}
140      or {@link java.awt.Color} objects into this {@link Primitive}'s
141      {@link renderer.scene.Model} object. This method assumes that
142      the given indices are valid (or will be valid by the time this
143      {@link Primitive} gets rendered).
144
145      @param vIndex  integer {@link renderer.scene.Vertex} index to add to this {@code Primitive}
146      @param cIndex  integer {@link java.awt.Color} index to add to this {@code Primitive}
147   */
148   public void addIndices(final int vIndex, final int cIndex)
149   {
150      vIndexList.add(vIndex);
151      cIndexList.add(cIndex);
152   }
153
154
155   /**
156      Set the {@link java.awt.Color} index list to the given array of indices.
157      <p>
158      NOTE: This method does not put any {@link java.awt.Color} objects
159      into this {@link Primitive}'s {@link renderer.scene.Model} object.
160      This method assumes that the given indices are valid (or will be
161      valid by the time this {@link Primitive} gets rendered).
162
163      @param cIndices  array of {@link java.awt.Color} indices for this {@code Primitive}
164      @throws IllegalArgumentException if {@code cIndices} does not have the correct length for this {@code Primitive}
165   */
166   public void setColorIndices(final int... cIndices)
167   {
168      if (vIndexList.size() != cIndices.length )
169         throw new IllegalArgumentException("wrong number of color indices for this primitive");
170
171      cIndexList.clear();
172      for (int i = 0; i < cIndices.length; ++i)
173      {
174         cIndexList.add( cIndices[i] );
175      }
176   }
177
178
179   /**
180      Give this {@code Primitive} the uniform {@link java.awt.Color} indexed
181      by the given color index.
182      <p>
183      NOTE: This method does not put a {@link java.awt.Color} object
184      into this {@link Primitive}'s {@link renderer.scene.Model} object.
185      This method assumes that the given index is valid (or will be valid
186      by the time this {@link Primitive} gets rendered).
187
188      @param cIndex  integer color index to use for this {@code Primitive}'s {@link java.awt.Color}
189   */
190   public void setColorIndex(final int cIndex)
191   {
192      for (int i = 0; i < cIndexList.size(); ++i)
193      {
194         cIndexList.set(i, cIndex);
195      }
196   }
197
198
199   /**
200      For debugging.
201
202      @return {@link String} representation of this {@code Primitive} object
203   */
204   @Override
205   public abstract String toString();
206}