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 }