001/* 002 * Renderer 4. The MIT License. 003 * Copyright (c) 2022 rlkraft@pnw.edu 004 * See LICENSE for details. 005*/ 006 007package renderer.scene; 008 009import renderer.scene.primitives.*; 010 011import java.util.List; 012import java.util.ArrayList; 013import java.awt.Color; 014 015/** 016 A {@code Model} object represents a distinct geometric object in a 017 {@link Scene}. A {@code Model} data structure is mainly a {@link List} 018 of {@link Vertex} objects, a {@link List} of {@link Primitive} objects, 019 and a list of {@link Color} objects. 020<p> 021 Each {@link Vertex} object contains the xyz-coordinates, in the 022 {@code Model}'s own coordinate system, for one point from the 023 {@code Model}. 024<p> 025 Each {@link Color} object represents a color associated to one 026 (or more) {@link Vertex} objects. 027<p> 028 The {@link Vertex} objects represents points from the geometric object 029 that we are modeling. In the real world, a geometric object has an infinite 030 number of points. In 3D graphics, we "approximate" a geometric object by 031 listing just enough points to adequately describe the object. For example, 032 in the real world, a rectangle contains an infinite number of points, but 033 it can be adequately modeled by just its four corner points. (Think about 034 a circle. How many points does it take to adequately model a circle? Look 035 at the {@link renderer.models_L.Circle} model.) 036<p> 037 Each {@link Primitive} object is either a {@link LineSegment} or a 038 {@link Point}. 039<p> 040 Each {@link LineSegment} object contains four integers, two integers that 041 are the indices of two {@link Vertex} objects from the {@code Model}'s 042 vertex list, and two integers that are indices of two {@link Color} 043 objects from the {@link Model}'s color list. The two vertices are the 044 line segment's two endpoints, and each of the two colors is associated 045 with one of the two endpoints. 046<p> 047 Each {@link Point} object contains two integers, one integer index of 048 a {@link Vertex} from the {@code Model}'s vertex list, and one integer 049 index of a {@link Color} from the {@code Model}'s color list. 050<p> 051 We use {@link LineSegment} objects to represent the space between the 052 model's vertices. For example, while a rectangle can be approximated by 053 its four corner points, those same four points could also represent two 054 parallel line segments, or they could represent two lines that cross each 055 other. By using four line segments that connect around the four points, 056 we get a good, unambiguous representation of a rectangle. 057<p> 058 If we modeled a circle using just points, we would probably need to use 059 hundreds of points. But if we connect every two adjacent points with a 060 short line segment, we can get a good model of a circle with just a few 061 dozen points. 062<p> 063 Our {@code Model}'s represent geometric objects as a "wire-frame" of line 064 segments, that is, a geometric object is drawn as a collection of "edges". 065 This is a fairly simplistic way of doing 3D graphics and we will improve 066 this in later renderers. 067<p> 068 See 069<br> <a href="https://en.wikipedia.org/wiki/Wire-frame_model" target="_top"> 070 https://en.wikipedia.org/wiki/Wire-frame_model</a> 071<br>or 072<br> <a href="https://www.google.com/search?q=computer+graphics+wireframe&tbm=isch" target="_top"> 073 https://www.google.com/search?q=computer+graphics+wireframe&tbm=isch</a> 074*/ 075public class Model 076{ 077 public final List<Vertex> vertexList; 078 public final List<Primitive> primitiveList; 079 public final List<Color> colorList; 080 public final String name; 081 082 public boolean visible; 083 084 /** 085 Construct an empty {@code Model} object. 086 */ 087 public Model() 088 { 089 this(new ArrayList<>(), // vertexList 090 new ArrayList<>(), // primitiveList 091 new ArrayList<>(), // colorList 092 "", // name 093 true); // visible 094 } 095 096 097 /** 098 Construct an empty {@code Model} object with the given 099 {link String} name. 100 101 @param name a {link String} that is a name for this {@code Model} 102 @throws NullPointerException if {@code name} is {@code null} 103 */ 104 public Model(final String name) 105 { 106 this(new ArrayList<>(), // vertexList 107 new ArrayList<>(), // primitiveList 108 new ArrayList<>(), // colorList 109 name, // name 110 true); // visible 111 } 112 113 114 /** 115 Construct a {@code Model} object with all the given data. 116 117 @param vertexList a {@link Vertex} {link List} for this {@code Model} 118 @param primitiveList a {@link Primitive} {link List} for this {@code Model} 119 @param colorList a {@link Color} {link List} for this {@code Model} 120 @param name a {link String} that is a name for this {@code Model} 121 @param visible a {@code boolean} that determines this {@code Model}'s visibility 122 @throws NullPointerException if {@code vertexList} is {@code null} 123 @throws NullPointerException if {@code primitiveList} is {@code null} 124 @throws NullPointerException if {@code colorList} is {@code null} 125 @throws NullPointerException if {@code name} is {@code null} 126 */ 127 public Model(final List<Vertex> vertexList, 128 final List<Primitive> primitiveList, 129 final List<Color> colorList, 130 final String name, 131 final boolean visible) 132 { 133 if (null == vertexList) 134 throw new NullPointerException("vertexList must not be null"); 135 if (null == primitiveList) 136 throw new NullPointerException("primitiveList must not be null"); 137 if (null == colorList) 138 throw new NullPointerException("colorList must not be null"); 139 if (null == name) 140 throw new NullPointerException("name must not be null"); 141 142 this.vertexList = vertexList; 143 this.primitiveList = primitiveList; 144 this.colorList = colorList; 145 this.name = name; 146 this.visible = visible; 147 } 148 149 150 /** 151 Add a {@link Vertex} (or vertices) to this {@code Model}'s 152 {@link List} of vertices. 153 154 @param vArray array of {@link Vertex} objects to add to this {@code Model} 155 @throws NullPointerException if any {@link Vertex} is {@code null} 156 */ 157 public final void addVertex(final Vertex... vArray) 158 { 159 for (final Vertex v : vArray) 160 { 161 if (null == v) 162 throw new NullPointerException("Vertex must not be null"); 163 164 vertexList.add( v ); 165 } 166 } 167 168 169 /** 170 Get a {@link Primitive} from this {@code Model}'s 171 {@link List} of primitives. 172 173 @param index integer index of a {@link Primitive} from this {@code Model} 174 @return the {@link Primitive} object at the given index 175 */ 176 public final Primitive getPrimitive(final int index) 177 { 178 return primitiveList.get(index); 179 } 180 181 182 /** 183 Add a {@link Primitive} (or Primitives) to this {@code Model}'s 184 {@link List} of primitives. 185 <p> 186 NOTE: This method does not add any vertices to the {@code Model}'s 187 {@link Vertex} list. This method assumes that the appropriate vertices 188 have been added to the {@code Model}'s {@link Vertex} list. 189 190 @param pArray array of {@link Primitive} objects to add to this {@code Model} 191 @throws NullPointerException if any {@link Primitive} is {@code null} 192 */ 193 public final void addPrimitive(final Primitive... pArray) 194 { 195 for (final Primitive p : pArray) 196 { 197 if (null == p) 198 throw new NullPointerException("Primitive must not be null"); 199 200 primitiveList.add(p); 201 } 202 } 203 204 205 /** 206 Add a {@link Color} (or colors) to this {@code Model}'s 207 {@link List} of colors. 208 209 @param cArray array of {@link Color} objects to add to this {@code Model} 210 @throws NullPointerException if any {@link Color} is {@code null} 211 */ 212 public final void addColor(final Color... cArray) 213 { 214 for (final Color c : cArray) 215 { 216 if (null == c) 217 throw new NullPointerException("Color must not be null"); 218 219 this.colorList.add(c); 220 } 221 } 222 223 224 /** 225 For debugging. 226 227 @return {@link String} representation of this {@code Model} object 228 */ 229 @Override 230 public String toString() 231 { 232 String result = ""; 233 result += "Model: " + name + "\n"; 234 result += "This Model's visibility is: " + visible + "\n"; 235 result += "Model has " + vertexList.size() + " vertices.\n"; 236 result += "Model has " + colorList.size() + " colors.\n"; 237 result += "Model has " + primitiveList.size() + " primitives.\n"; 238 int i = 0; 239 for (final Vertex v : this.vertexList) 240 { 241 result += i + ": " + v.toString() + "\n"; 242 ++i; 243 } 244 i = 0; 245 for (final Color c : this.colorList) 246 { 247 result += i + ": " + c.toString() + "\n"; 248 ++i; 249 } 250 i = 0; 251 for (final Primitive p : this.primitiveList) 252 { 253 result += i + ": " + p.toString() + "\n"; 254 ++i; 255 } 256 return result; 257 } 258}