001 package physics3d;
002
003
004 import java.util.ArrayList;
005 import java.util.Collections;
006 import java.util.List;
007
008 /**
009 * Shape is a immutable class that describes the bounding area, and 3d shape of a GameObject
010 *
011 *@specfield bound : PhysicsShape // the bounds of the shape, centered at the origin
012 *@specified parts : set // the parts that make up the Shape, centered at the origin
013 */
014
015 /*
016 * Abstraction Function
017 * AF(r) = a Shape, s, such that
018 * s.bound = r. bound
019 * s.parts = r.parts
020 */
021
022 /*
023 * Rep Invariant
024 * bound, parts != null
025 * bound bounds parts
026 */
027
028 public class Shape {
029 //fields
030 private final PhysicsShape bound;
031 private final List<PhysicsShape> parts;
032
033 //static shapes
034 private static Shape ball;
035 private static Shape cirBumper;
036 private static Shape squBumper;
037 private static Shape triBumper;
038 private static Shape flipper;
039
040 //constructors
041 private Shape(PhysicsShape bound, PhysicsShape part) {
042 this.bound = bound;
043 parts = new ArrayList<PhysicsShape>();
044 parts.add(part);
045 //checkRep();
046 }
047
048 private Shape(PhysicsShape bound, List<PhysicsShape> parts) {
049 this.bound = bound;
050 this.parts = parts;
051 //checkRep();
052 }
053
054 //factory methods
055 /**
056 * @return the standard Ball's shape
057 */
058 public static Shape getBallShape() {
059 if (ball == null) {
060 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, 0.25);
061 PhysicsShape sphere = new Sphere(Vect3.ZERO, 0.25);
062 ball = new Shape(boundSphere, sphere);
063 }
064 return ball;
065 }
066
067 /**
068 * @return the standard SquareBumper's shape
069 */
070 public static Shape getSqBumperShape() {
071 if (squBumper == null) {
072 Double s = 0.5;
073
074 //bounding sphere
075 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, Math.sqrt(3) * s);
076
077 //parts
078 //vertices of cube
079 Vect3 a = new Vect3(-s, -s, -s);
080 Vect3 b = new Vect3(s, -s, -s);
081 Vect3 c = new Vect3(s, -s, s);
082 Vect3 d = new Vect3(-s, -s, s);
083 Vect3 e = new Vect3(-s, s, -s);
084 Vect3 f = new Vect3(-s, s, s);
085 Vect3 g = new Vect3(s, s, s);
086 Vect3 h = new Vect3(s, s, -s);
087
088 //points at the vertices
089 PhysicsShape pa = new Sphere(a, 0);
090 PhysicsShape pb = new Sphere(b, 0);
091 PhysicsShape pc = new Sphere(c, 0);
092 PhysicsShape pd = new Sphere(d, 0);
093 PhysicsShape pe = new Sphere(e, 0);
094 PhysicsShape pf = new Sphere(f, 0);
095 PhysicsShape pg = new Sphere(g, 0);
096 PhysicsShape ph = new Sphere(h, 0);
097
098 //edges
099 PhysicsShape e1 = new LateralCylinder(0, a, b);
100 PhysicsShape e2 = new LateralCylinder(0, b, c);
101 PhysicsShape e3 = new LateralCylinder(0, c, d);
102 PhysicsShape e4 = new LateralCylinder(0, d, a);
103
104 PhysicsShape e5 = new LateralCylinder(0, e, f);
105 PhysicsShape e6 = new LateralCylinder(0, f, g);
106 PhysicsShape e7 = new LateralCylinder(0, g, h);
107 PhysicsShape e8 = new LateralCylinder(0, h, e);
108
109 PhysicsShape e9 = new LateralCylinder(0, a, e);
110 PhysicsShape e10 = new LateralCylinder(0, b, h);
111 PhysicsShape e11 = new LateralCylinder(0, c, g);
112 PhysicsShape e12 = new LateralCylinder(0, d, f);
113
114 //faces of cube
115 //top faces
116 PhysicsShape top = new PlanePolygon(makeList(a, b, c, d));
117
118 //bottom faces
119 PhysicsShape bottom = new PlanePolygon(makeList(e, f, g, h));
120
121 //front faces
122 PhysicsShape front = new PlanePolygon(makeList(a, e, h, b));
123
124 //back faces
125 PhysicsShape back = new PlanePolygon(makeList(d, c, g, f));
126
127 //left faces
128 PhysicsShape left = new PlanePolygon(makeList(a, d, f, e));
129
130 //right faces
131 PhysicsShape right = new PlanePolygon(makeList(c, b, h, g));
132
133 //put parts in list
134 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
135
136 //vertices
137 partsList.add(pa);
138 partsList.add(pb);
139 partsList.add(pc);
140 partsList.add(pd);
141 partsList.add(pe);
142 partsList.add(pf);
143 partsList.add(pg);
144 partsList.add(ph);
145
146 //edges
147 partsList.add(e1);
148 partsList.add(e2);
149 partsList.add(e3);
150 partsList.add(e4);
151 partsList.add(e5);
152 partsList.add(e6);
153 partsList.add(e7);
154 partsList.add(e8);
155 partsList.add(e9);
156 partsList.add(e10);
157 partsList.add(e11);
158 partsList.add(e12);
159
160 //faces
161 partsList.add(top);
162 partsList.add(bottom);
163 partsList.add(front);
164 partsList.add(back);
165 partsList.add(left);
166 partsList.add(right);
167
168 //creates the Shape
169 squBumper = new Shape(boundSphere, partsList);
170 }
171 return squBumper;
172 }
173
174 /**
175 * @return the standard TriangleBumper's shape
176 */
177 public static Shape getTriBumperShape() {
178 if (triBumper == null) {
179 Double s = 0.5;
180
181 //bounding sphere
182 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, Math.sqrt(3) * s);
183
184 //parts
185 //vertices
186 Vect3 a = new Vect3(-s, -s, -s);
187 Vect3 b = new Vect3(s, -s, -s);
188 Vect3 c = new Vect3(s, -s, s);
189 Vect3 d = new Vect3(-s, -s, s);
190 Vect3 e = new Vect3(-s, s, -s);
191 Vect3 f = new Vect3(-s, s, s);
192
193 //corner points
194 PhysicsShape pa = new Sphere(a, 0);
195 PhysicsShape pb = new Sphere(b, 0);
196 PhysicsShape pc = new Sphere(c, 0);
197 PhysicsShape pd = new Sphere(d, 0);
198 PhysicsShape pe = new Sphere(e, 0);
199 PhysicsShape pf = new Sphere(f, 0);
200
201 //edges
202 PhysicsShape e1 = new LateralCylinder(0, a, b);
203 PhysicsShape e2 = new LateralCylinder(0, b, c);
204 PhysicsShape e3 = new LateralCylinder(0, c, d);
205 PhysicsShape e4 = new LateralCylinder(0, d, a);
206
207 PhysicsShape e5 = new LateralCylinder(0, e, b);
208 PhysicsShape e6 = new LateralCylinder(0, c, f);
209
210 PhysicsShape e7 = new LateralCylinder(0, a, e);
211 PhysicsShape e8 = new LateralCylinder(0, d, f);
212 PhysicsShape e9 = new LateralCylinder(0, e, f);
213
214 //faces
215 //front and back triangles
216 PhysicsShape front = new PlanePolygon(makeList(a, e, b));
217 PhysicsShape back = new PlanePolygon(makeList(f, c, d));
218
219 //bottom quad
220 PhysicsShape top = new PlanePolygon(makeList(a, b, c, d));
221
222 //side quad
223 PhysicsShape side = new PlanePolygon(makeList(e, a, d, f));
224
225 //slanted quad
226 PhysicsShape bottom = new PlanePolygon(makeList(e, f, c, b));
227
228 //put parts in list
229 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
230
231 //adding vertices
232 partsList.add(pa);
233 partsList.add(pb);
234 partsList.add(pc);
235 partsList.add(pd);
236 partsList.add(pe);
237 partsList.add(pf);
238
239 //adding edges
240 partsList.add(e1);
241 partsList.add(e2);
242 partsList.add(e3);
243 partsList.add(e4);
244 partsList.add(e5);
245 partsList.add(e6);
246 partsList.add(e7);
247 partsList.add(e8);
248 partsList.add(e9);
249
250 //adding faces
251 partsList.add(front);
252 partsList.add(back);
253 partsList.add(bottom);
254 partsList.add(side);
255 partsList.add(top);
256
257 //creates the Shape
258 triBumper = new Shape(boundSphere, partsList);
259 }
260 return triBumper;
261 }
262
263 /**
264 * @return the CircleBumper's standard shape
265 */
266 public static Shape getCirBumperShape() {
267 if (cirBumper == null) {
268 Double s = 0.5;
269
270 //bounding sphere
271 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, Math.sqrt(3) * s);
272
273 //parts
274 //front circle
275 Vect3 fv = new Vect3(0, 0, -s);
276 PhysicsShape frontCircle = new PlaneCircle(fv, Vect3.Z_HAT.neg(), s);
277 //back circle
278 Vect3 bv = new Vect3(0, 0, s);
279 PhysicsShape backCircle = new PlaneCircle(bv, Vect3.Z_HAT, s);
280 //cylinder
281 PhysicsShape cylinder = new LateralCylinder(s, bv, fv);
282
283 //toruses
284 PhysicsShape frontTorus = new Torus(fv, Vect3.Z_HAT, s, 0);
285 PhysicsShape backTorus = new Torus(bv, Vect3.Z_HAT.neg(), s, 0);
286
287 //put parts in list
288 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
289 partsList.add(frontCircle);
290 partsList.add(backCircle);
291 partsList.add(cylinder);
292 partsList.add(frontTorus);
293 partsList.add(backTorus);
294
295 //creates the Shape
296 cirBumper = new Shape(boundSphere, partsList);
297 }
298 return cirBumper;
299 }
300
301 /**
302 * @return the Shape of an Absorber
303 */
304 public static Shape getAbsorberShape(int height, int width, int depth) {
305 double w2 = width/2.0;
306 double h2 = height/2.0;
307 double d2 = depth/2.0;
308
309 //bounding sphere
310 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, Math.sqrt(w2*w2 + h2*h2 + d2*d2));
311
312 Vect3 a = new Vect3(-w2, -h2, -d2);
313 Vect3 b = new Vect3(w2, -h2, -d2);
314 Vect3 c = new Vect3(w2, -h2, d2);
315 Vect3 d = new Vect3(-w2, -h2, d2);
316 Vect3 e = new Vect3(-w2, h2, -d2);
317 Vect3 f = new Vect3(-w2, h2, d2);
318 Vect3 g = new Vect3(w2, h2, d2);
319 Vect3 h = new Vect3(w2, h2, -d2);
320
321 //points at the vertices
322 PhysicsShape pa = new Sphere(a, 0);
323 PhysicsShape pb = new Sphere(b, 0);
324 PhysicsShape pc = new Sphere(c, 0);
325 PhysicsShape pd = new Sphere(d, 0);
326 PhysicsShape pe = new Sphere(e, 0);
327 PhysicsShape pf = new Sphere(f, 0);
328 PhysicsShape pg = new Sphere(g, 0);
329 PhysicsShape ph = new Sphere(h, 0);
330
331 //edges
332 PhysicsShape e1 = new LateralCylinder(0, a, b);
333 PhysicsShape e2 = new LateralCylinder(0, b, c);
334 PhysicsShape e3 = new LateralCylinder(0, c, d);
335 PhysicsShape e4 = new LateralCylinder(0, d, a);
336
337 PhysicsShape e5 = new LateralCylinder(0, e, f);
338 PhysicsShape e6 = new LateralCylinder(0, f, g);
339 PhysicsShape e7 = new LateralCylinder(0, g, h);
340 PhysicsShape e8 = new LateralCylinder(0, h, e);
341
342 PhysicsShape e9 = new LateralCylinder(0, a, e);
343 PhysicsShape e10 = new LateralCylinder(0, b, h);
344 PhysicsShape e11 = new LateralCylinder(0, c, g);
345 PhysicsShape e12 = new LateralCylinder(0, d, f);
346
347 //faces of cube
348 //top faces
349 PhysicsShape top = new PlanePolygon(makeList(a, b, c, d));
350
351 //bottom faces
352 PhysicsShape bottom = new PlanePolygon(makeList(e, f, g, h));
353
354 //front faces
355 PhysicsShape front = new PlanePolygon(makeList(a, e, h, b));
356
357 //back faces
358 PhysicsShape back = new PlanePolygon(makeList(d, c, g, f));
359
360 //left faces
361 PhysicsShape left = new PlanePolygon(makeList(a, d, f, e));
362
363 //right faces
364 PhysicsShape right = new PlanePolygon(makeList(c, b, h, g));
365
366 //put parts in list
367 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
368 //adding vertices
369 partsList.add(pa);
370 partsList.add(pb);
371 partsList.add(pc);
372 partsList.add(pd);
373 partsList.add(pe);
374 partsList.add(pf);
375 partsList.add(pg);
376 partsList.add(ph);
377
378 //adding edges
379 partsList.add(e1);
380 partsList.add(e2);
381 partsList.add(e3);
382 partsList.add(e4);
383 partsList.add(e5);
384 partsList.add(e6);
385 partsList.add(e7);
386 partsList.add(e8);
387 partsList.add(e9);
388 partsList.add(e10);
389 partsList.add(e11);
390 partsList.add(e12);
391
392 //adding faces
393 partsList.add(top);
394 partsList.add(bottom);
395 partsList.add(front);
396 partsList.add(back);
397 partsList.add(left);
398 partsList.add(right);
399
400 return new Shape(boundSphere, partsList);
401 }
402
403
404
405 /**
406 * @return the Shape of a Flipper
407 */
408 public static Shape getFlipperShape() {
409 if (flipper == null) {
410 //radius of corner spheres
411 double r = GameConstants.FLIPPER_RADIUS_FRACTION;
412 double l = .5;
413
414 //bounding sphere... oversized for now.
415 PhysicsShape boundSphere = new Sphere(Vect3.ZERO, l * 3);
416
417 //parts
418 //four "corner" vertices
419 Vect3 a = new Vect3(0, 0, 1-.5);
420 Vect3 b = new Vect3(0, 0, .5-1);
421 Vect3 c = new Vect3(0, 2 * (1-r), 1-.5);
422 Vect3 d = new Vect3(0, 2 * (1-r), .5-1);
423
424 PhysicsShape topCyl = new LateralCylinder(r, a, b);
425 PhysicsShape botCyl = new LateralCylinder(r, c, d);
426
427 PhysicsShape aCir = new PlaneCircle(a, Vect3.Z_HAT, r);
428 PhysicsShape bCir = new PlaneCircle(b, Vect3.Z_HAT.neg(), r);
429 PhysicsShape cCir = new PlaneCircle(c, Vect3.Z_HAT, r);
430 PhysicsShape dCir = new PlaneCircle(d, Vect3.Z_HAT.neg(), r);
431
432 //side planes
433 //vertices
434 Vect3 ap1 = new Vect3(r, a.y(), a.z());
435 Vect3 bp1 = new Vect3(r, b.y(), b.z());
436 Vect3 cp1 = new Vect3(r, c.y(), c.z());
437 Vect3 dp1 = new Vect3(r, d.y(), d.z());
438
439 PhysicsShape plane1 = new PlanePolygon(makeList(ap1, bp1, dp1, cp1));
440
441 Vect3 ap2 = new Vect3(-r, a.y(), a.z());
442 Vect3 bp2 = new Vect3(-r, b.y(), b.z());
443 Vect3 cp2 = new Vect3(-r, c.y(), c.z());
444 Vect3 dp2 = new Vect3(-r, d.y(), d.z());
445
446 PhysicsShape plane2 = new PlanePolygon(makeList(ap2, cp2, dp2, bp2));
447
448 //front plane
449 PhysicsShape plane3 = new PlanePolygon(makeList(ap1, ap2, cp2, cp1));
450 PhysicsShape plane4 = new PlanePolygon(makeList(bp1, bp2, dp2, dp1));
451
452 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
453 partsList.add(aCir);
454 partsList.add(bCir);
455 partsList.add(cCir);
456 partsList.add(dCir);
457
458 partsList.add(topCyl);
459 partsList.add(botCyl);
460
461 partsList.add(plane1);
462 partsList.add(plane2);
463 partsList.add(plane3);
464 partsList.add(plane4);
465
466 /*
467 //four spheres
468 PhysicsShape s1 = new Sphere(a, r);
469 PhysicsShape s2 = new Sphere(b, r);
470 PhysicsShape s3 = new Sphere(c, r);
471 PhysicsShape s4 = new Sphere(d, r);
472
473 //4 cylinders
474 PhysicsShape aCyl = new LateralCylinder(r, a, b);
475 PhysicsShape bCyl = new LateralCylinder(r, b, d);
476 PhysicsShape cCyl = new LateralCylinder(r, d, c);
477 PhysicsShape dCyl = new LateralCylinder(r, c, a);
478
479 //side planes
480 //vertices
481 Vect3 ap1 = new Vect3(r, a.y(), a.z());
482 Vect3 bp1 = new Vect3(r, b.y(), b.z());
483 Vect3 cp1 = new Vect3(r, c.y(), c.z());
484 Vect3 dp1 = new Vect3(r, d.y(), d.z());
485
486 PhysicsShape plane1 = new PlanePolygon(makeList(ap1, bp1, cp1, dp1));
487
488 Vect3 ap2 = new Vect3(-r, a.y(), a.z());
489 Vect3 bp2 = new Vect3(-r, b.y(), b.z());
490 Vect3 cp2 = new Vect3(-r, c.y(), c.z());
491 Vect3 dp2 = new Vect3(-r, d.y(), d.z());
492
493 PhysicsShape plane2 = new PlanePolygon(makeList(cp2, ap2, bp2, dp2));
494 */
495 //put parts in List
496 // List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
497 /* partsList.add(s1);
498 partsList.add(s2);
499 partsList.add(s3);
500 partsList.add(s4);
501 partsList.add(aCyl);
502 partsList.add(bCyl);
503 partsList.add(cCyl);
504 partsList.add(dCyl);
505 partsList.add(plane1);
506 partsList.add(plane2);
507 */
508
509 flipper = new Shape(boundSphere, partsList);
510 }
511 return flipper;
512 }
513
514 /**
515 * @return the Shape for a wall given length and width
516 */
517 public static Shape getWallShape(int length, int width) {
518 // corners
519 Vect3 a = new Vect3(-width/2.0, -length/2.0, 0);
520 Vect3 b = new Vect3(width/2.0, -length/2.0, 0);
521 Vect3 c = new Vect3(width/2.0, length/2.0, 0);
522 Vect3 d = new Vect3(-width/2.0, length/2.0, 0);
523
524
525 //planes
526 PhysicsShape plane1 = new PlanePolygon(makeList(a, b, c, d));
527
528
529 //parts list
530 List<PhysicsShape> partsList = new ArrayList<PhysicsShape>();
531 partsList.add(plane1);
532
533 return new Shape(plane1, plane1);
534 }
535
536 //helper method that takes three Vect3s and puts them into a List
537 private static List<Vect3> makeList(Vect3 v1, Vect3 v2, Vect3 v3) {
538 List<Vect3> vList = new ArrayList<Vect3>();
539 vList.add(v1);
540 vList.add(v2);
541 vList.add(v3);
542 return Collections.unmodifiableList(vList);
543 }
544
545 private static List<Vect3> makeList(Vect3 v1, Vect3 v2, Vect3 v3, Vect3 v4) {
546 List<Vect3> vList = new ArrayList<Vect3>();
547 vList.add(v1);
548 vList.add(v2);
549 vList.add(v3);
550 vList.add(v4);
551 return Collections.unmodifiableList(vList);
552 }
553
554 /**
555 * @return the bound of this object
556 */
557 public PhysicsShape getBound() {
558 return this.bound;
559 }
560
561 /**
562 * @returns the parts of this object
563 */
564 public List<PhysicsShape> getParts() {
565 return Collections.unmodifiableList(parts);
566 }
567
568 private void checkRep() {}
569 }