1 /************************************************************************* 2 * * 3 * Tokamak Physics Engine, Copyright (C) 2002-2007 David Lam. * 4 * All rights reserved. Email: david@tokamakphysics.com * 5 * Web: www.tokamakphysics.com * 6 * * 7 * This library is distributed in the hope that it will be useful, * 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * 10 * LICENSE.TXT for more details. * 11 * * 12 *************************************************************************/ 13 14 #ifndef COLLISION_H 15 #define COLLISION_H 16 17 typedef enum 18 { 19 IMPULSE_IGNORE, 20 IMPULSE_NORMAL, 21 IMPULSE_CONTACT, 22 IMPULSE_CONSTRAINT, 23 IMPULSE_SLIDER, 24 IMPULSE_SLIDER_LIMIT_PRIMARY, 25 // IMPULSE_LIMIT, 26 IMPULSE_ANGULAR_LIMIT_PRIMARY, 27 IMPULSE_ANGULAR_LIMIT_SECONDARY, 28 IMPULSE_ANGULAR_MOTOR_PRIMARY, 29 IMPULSE_ANGULAR_MOTOR_SECONDARY, 30 IMPULSE_RELATIVE_LINEAR_VELOCITY, 31 }neImpulseType; 32 33 class neRigidBodyBase; 34 35 class neRigidBody_; 36 37 /////////////////////////////////////////////////////////////////// 38 // 39 // Collision Model 40 // 41 // 42 /////////////////////////////////////////////////////////////////// 43 44 typedef struct 45 { 46 neV3 point[2]; // closest point in world space, but relative to object centre 47 neV3 normal; // toward feature on body A 48 49 f32 distance; 50 bool penetrated; 51 52 int matIndex[2]; 53 }TCollisionResult; 54 55 /////////////////////////////////////////////////////////////////// 56 57 //typedef struct neBox neBox; 58 59 typedef struct _neBox 60 { 61 neV3 boxSize; //half of dimensions 62 //f32 boxSize[4]; 63 }neBox; 64 65 struct neTri 66 { 67 s32 indices[3]; 68 }; 69 70 struct neTriangleTerrain 71 { 72 neSimpleArray<s32> * triIndex; 73 neArray<neTriangle_> * triangles; 74 }; 75 76 struct neSphere 77 { 78 f32 radius; 79 f32 radiusSq; 80 }; 81 82 struct neCylinder 83 { 84 f32 radius; 85 f32 radiusSq; 86 f32 halfHeight; 87 }; 88 89 struct neConvexMesh 90 { 91 neV3 * vertices; 92 s32 * neighbours; 93 s32 vertexCount; 94 }; 95 96 struct neConvexDCD 97 { 98 neByte * convexData; 99 neV3 * vertices; 100 s32 numVerts; 101 }; 102 103 #ifdef USE_OPCODE 104 105 struct neOPCMesh 106 { 107 Opcode::OPCODE_Model * opmodel; 108 IceMaths::Point * vertices; 109 u32 vertCount; 110 IndexedTriangle * triIndices; 111 u32 triCount; 112 }; 113 114 #endif 115 116 typedef struct neBreakInfo neBreakInfo; 117 118 struct neBreakInfo 119 { 120 neV3 inertiaTensor; 121 neV3 breakPlane; 122 f32 mass; 123 f32 breakMagnitude; 124 f32 breakAbsorb; 125 f32 neighbourRadius; 126 neGeometry::neBreakFlag flag; //break all, 127 }; 128 129 typedef struct TConvex TConvex; 130 131 struct TConvex 132 { 133 enum 134 { 135 POINT, 136 LINE, 137 TRIANGLE, 138 BOX, 139 SPHERE, 140 CYLINDER, 141 TERRAIN, 142 CONVEXITY, 143 CONVEXDCD, 144 OPCODE_MESH, 145 }; 146 147 union 148 { 149 neBox box; 150 neTri tri; 151 neTriangleTerrain terrain; 152 neSphere sphere; 153 neCylinder cylinder; 154 neConvexMesh convexMesh; 155 neConvexDCD convexDCD; 156 #ifdef USE_OPCODE 157 neOPCMesh opcodeMesh; 158 #endif 159 }as; 160 161 neT3 c2p; // convex to physics object 162 f32 boundingRadius; 163 f32 envelope; 164 u32 type; 165 s32 matIndex; 166 u32 userData; 167 neBreakInfo breakInfo; 168 neV3 * vertices; 169 170 void SetBoxSize(f32 width, f32 height, f32 depth); 171 void SetSphere(f32 radius); 172 void SetTriangle(s32 a, s32 b, s32 c, neV3 * vertices); 173 void SetTerrain(neSimpleArray<s32> & triangleIndex, neArray<neTriangle_> & triangles, neV3 * vertices); 174 void SetConvexMesh(neByte * convexData); 175 176 #ifdef USE_OPCODE 177 178 void SetOpcodeMesh(IndexedTriangle * triIndex, u32 triCount, IceMaths::Point * vertArray, u32 vertCount); 179 180 #endif 181 182 void SetTransform(neT3 & t3); 183 neT3 GetTransform(); SetUserDataTConvex184 void SetUserData(u32 ud) 185 { 186 userData = ud; 187 } GetUserDataTConvex188 u32 GetUserData() 189 { 190 return userData; 191 } 192 void SetMaterialId(s32 id); 193 s32 GetMaterialId(); 194 f32 GetBoundRadius(); 195 u32 GetType(); 196 void Initialise(); 197 neM3 CalcInertiaTensor(f32 density, f32 & mass); 198 void GetExtend(neV3 & minExt, neV3 & maxEnt); 199 200 //quick access functions BoxSizeTConvex201 NEINLINE f32 BoxSize(s32 dir) 202 { 203 ASSERT(type == BOX); 204 205 return as.box.boxSize[dir]; 206 } RadiusTConvex207 NEINLINE f32 Radius() 208 { 209 ASSERT(type == SPHERE); 210 211 return as.sphere.radius; 212 } RadiusSqTConvex213 NEINLINE f32 RadiusSq() 214 { 215 ASSERT(type == SPHERE); 216 217 return as.sphere.radiusSq; 218 } CylinderRadiusTConvex219 NEINLINE f32 CylinderRadius() 220 { 221 ASSERT(type == CYLINDER); 222 223 return as.cylinder.radius; 224 } CylinderRadiusSqTConvex225 NEINLINE f32 CylinderRadiusSq() 226 { 227 ASSERT(type == CYLINDER); 228 229 return as.cylinder.radiusSq; 230 } CylinderHalfHeightTConvex231 NEINLINE f32 CylinderHalfHeight() 232 { 233 ASSERT(type == CYLINDER); 234 235 return as.cylinder.halfHeight; 236 } 237 }; 238 239 class neSensor_ 240 { 241 public: 242 neV3 pos; 243 244 neV3 dir; 245 246 neV3 dirNormal; 247 248 f32 length; 249 250 u32 cookies; 251 252 //results 253 254 neV3 normal; 255 256 neV3 contactPoint; 257 258 f32 depth; 259 260 s32 materialID; 261 262 neRigidBodyBase * body; 263 264 public: 265 neSensor_()266 neSensor_() 267 { 268 pos.SetZero(); 269 dir.SetZero(); 270 cookies = 0; 271 normal.SetZero(); 272 depth = 0; 273 materialID = 0; 274 body = NULL; 275 } 276 }; 277 /**************************************************************************** 278 * 279 * NE Physics Engine 280 * 281 * Class: neCollision 282 * 283 * Desc: 284 * 285 ****************************************************************************/ 286 287 typedef neFreeListItem<TConvex> TConvexItem; 288 289 class neCollision 290 { 291 public: neCollision()292 neCollision() 293 { 294 convex = NULL; 295 convexCount = 0; 296 boundingRadius = 0.0f; 297 obb.SetBoxSize(1.0f, 1.0f, 1.0f); 298 } 299 300 // void SeTConvex(TConvex * con, s32 count) 301 // { 302 // convex = con; 303 // convexCount = count+1; 304 // } 305 306 void CalcBB(); 307 308 public: 309 TConvex obb; 310 TConvex * convex; 311 s32 convexCount; 312 f32 boundingRadius; 313 }; 314 315 class neCollisionResult; 316 317 typedef neCollection<neCollisionResult>::itemType neCollisionResultHandle; 318 319 class neCollisionResult 320 { 321 PLACEMENT_MAGIC 322 public: 323 //neCollisionResultHandle bodyAHandle; 324 //neCollisionResultHandle bodyBHandle; 325 326 neV3 contactA; 327 neV3 contactB; 328 329 neV3 contactABody; // or relative tangential velocity 330 neV3 contactBBody; // or angular limit axis 331 332 neV3 contactAWorld; 333 neV3 contactBWorld; 334 335 neM3 collisionFrame; 336 337 neM3 w2c; 338 339 neV3 initRelVelWorld; 340 neV3 initRelVel; 341 neV3 finaltRelVel; 342 343 s32 materialIdA; 344 s32 materialIdB; 345 f32 depth; //+ve 346 neBool penetrate; 347 348 neRigidBodyBase * bodyA; 349 neRigidBodyBase * bodyB; 350 351 f32 relativeSpeed; 352 f32 finalRelativeSpeed; 353 354 TConvex * convexA; 355 TConvex * convexB; 356 357 neM3 k; 358 359 neM3 kInv; 360 361 f32 impulseScale; 362 363 neImpulseType impulseType; 364 365 neBool flag; 366 367 void UpdateConstraintRelativeSpeed(); 368 void StartStage2(); 369 void PrepareForSolver(neBool aIdle = false, neBool bIdle = false); 370 void CalcCollisionMatrix(neRigidBody_* ba, neRigidBody_ * bb, neBool isWorld); 371 void CalcCollisionMatrix2(neRigidBody_* ba, neRigidBody_ * bb); 372 void CalcCollisionMatrix3(neRigidBody_* ba, neRigidBody_ * bb); 373 374 f32 SolveContact(neFixedTimeStepSimulator * sim); 375 f32 SolveConstraint(neFixedTimeStepSimulator * sim); 376 f32 SolveSlider(neFixedTimeStepSimulator * sim); 377 f32 SolveSliderLimit(neFixedTimeStepSimulator * sim); 378 f32 SolveAngularPrimary(neFixedTimeStepSimulator * sim); 379 f32 SolveAngularSecondary(neFixedTimeStepSimulator * sim); 380 f32 SolveAngularMotorPrimary(neFixedTimeStepSimulator * sim); 381 f32 SolveRelativeLinear(neFixedTimeStepSimulator * sim); 382 383 f32 SolveAngular(f32 depth, const neV3 & axis, f32 relAV, neFixedTimeStepSimulator * sim); 384 f32 SolveAngular2(const neV3 & axisA, const neV3 & axisB, f32 relAV, f32 desireAV, f32 depth, neFixedTimeStepSimulator * sim); 385 f32 SolveAngular3(f32 depth, const neV3 & axis, f32 relAV, neFixedTimeStepSimulator * sim); 386 387 void CalcError(neFixedTimeStepSimulator * sim); 388 // void AddToBodies(); 389 Value()390 f32 Value(){ 391 return relativeSpeed;}; 392 393 neBool CheckIdle(); 394 Swap()395 void Swap() 396 { 397 collisionFrame[2] *= -1.0f; 398 399 neSwap(contactA, contactB); 400 401 neSwap(convexA, convexB); 402 } 403 }; 404 405 void CollisionTest(neCollisionResult & result, neCollision & colA, neT3 & transA, neCollision & colB, neT3 & transB, const neV3 & backupVector); 406 407 void CollisionTestSensor(TConvex * obbA, neSensor_ * sensorsA, neT3 & transA, neCollision & colB, neT3 & transB, neRigidBodyBase * body); 408 409 void ConvexCollisionTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector); 410 411 void Box2BoxTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector); 412 413 void Box2TriangleTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB); 414 415 void Box2TerrainTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB); 416 417 void Box2SphereTest(neCollisionResult & result, TConvex & boxA, neT3 & transA, TConvex & sphereB, neT3 & transB); 418 419 void Box2CylinderTest(neCollisionResult & result, TConvex & boxA, neT3 & transA, TConvex & sphereB, neT3 & transB); 420 421 void Sphere2TerrainTest(neCollisionResult & result, TConvex & sphereA, neT3 & transA, TConvex & terrainB); 422 423 void Sphere2SphereTest(neCollisionResult & result, TConvex & sphereA, neT3 & transA, TConvex & sphereB, neT3 & transB); 424 425 void Cylinder2CylinderTest(neCollisionResult & result, TConvex & cA, neT3 & transA, TConvex & cB, neT3 & transB); 426 427 void Cylinder2TerrainTest(neCollisionResult & result, TConvex & cylinderA, neT3 & transA, TConvex & terrainB); 428 429 void Cylinder2SphereTest(neCollisionResult & result, TConvex & cylinderA, neT3 & transA, TConvex & sphereB, neT3 & transB); 430 431 void Box2ConvexTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector); 432 433 void Convex2ConvexTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector); 434 435 void TranslateCOM(neM3 & I, neV3 &translate, f32 mass, f32 factor); 436 437 void DiagonalizeMassTensor(neM3 & I, neV3 & diagonal, neM3 & eigenVectors); 438 439 void SensorTest(neSensor_ & sensorA, TConvex & convexB, neT3 & transB); 440 441 #ifdef USE_OPCODE 442 443 void Box2OpcodeTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB); 444 445 void Sphere2OpcodeTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB); 446 447 void Cylinder2OpcodeTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB); 448 449 void Opcode2TerrainTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB); 450 451 void Opcode2OpcodeTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB); 452 453 #endif //USE_OPCODE 454 455 #endif 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476