rigidShape.cpp

Engine/source/T3D/rigidShape.cpp

More...

Public Variables

Public Functions

ConsoleDocClass(RigidShape , "@brief The <a href="/coding/class/classrigidshape/">RigidShape</a> class implements rigid-body physics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> DTS objects in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">world.\n\n</a>" "\"Rigid body physics\" refers <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> a system whereby objects are assumed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have a finite size, \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "equally distributed masses, and where deformations of the objects themselves are not accounted <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "Uses the <a href="/coding/class/classrigidshape/">RigidShape</a> class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">physics.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" " datablock <a href="/coding/class/classrigidshapedata/">RigidShapeData</a>(BouncingBoulder)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " category=\"RigidShape\";\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" "	   emap = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   // <a href="/coding/class/classrigid/">Rigid</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Body\n</a>" "	   mass = 500;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   massCenter = \"0 0 0\";    // Center of mass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rigid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">body\n</a>" "	   massBox = \"0 0 0\";         // Size of box used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> moment of inertia,\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "								  // <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> zero it defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> object bounding <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">box\n</a>" "	   drag = 0.2;                // Drag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coefficient\n</a>" "	   bodyFriction = 0.2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   bodyRestitution = 0.1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minImpactSpeed = 5;        // Impacts over this invoke the script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback\n</a>" "	   softImpactSpeed = 5;       // Play SoftImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   hardImpactSpeed = 15;      // Play HardImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   integration = 4;           // Physics integration: <a href="/coding/file/processlist_8h/#processlist_8h_1a6dfddc4b6033c4de60ed37c4fe30f650">TickSec</a>/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rate\n</a>" "	   collisionTol = 0.1;        // <a href="/coding/class/structcollision/">Collision</a> distance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "	   contactTol = 0.1;          // Contact velocity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minRollSpeed = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   maxDrag = 0.5;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minDrag = 0.01;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dustHeight = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dragForce = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   vertFactor = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classrigidshape/">RigidShape</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "		dataBlock = \"BouncingBoulder\";\n" "		parentGroup = EWCreatorWindow.objectGroup;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RigidShapeData\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )
ConsoleDocClass(RigidShapeData , "@brief Defines the physics properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an individual <a href="/coding/class/classrigidshapedata/">RigidShapeData</a> physics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" " datablock <a href="/coding/class/classrigidshapedata/">RigidShapeData</a>( BouncingBoulder )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   category = \"RigidShape\";\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" "	   emap = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   // <a href="/coding/class/classrigid/">Rigid</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Body\n</a>" "	   mass = 500;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   massCenter = \"0 0 0\";    // Center of mass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rigid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">body\n</a>" "	   massBox = \"0 0 0\";         // Size of box used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> moment of inertia,\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "								  // <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> zero it defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> object bounding <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">box\n</a>" "	   drag = 0.2;                // Drag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coefficient\n</a>" "	   bodyFriction = 0.2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   bodyRestitution = 0.1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minImpactSpeed = 5;        // Impacts over this invoke the script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback\n</a>" "	   softImpactSpeed = 5;       // Play SoftImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   hardImpactSpeed = 15;      // Play HardImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   integration = 4;           // Physics integration: <a href="/coding/file/processlist_8h/#processlist_8h_1a6dfddc4b6033c4de60ed37c4fe30f650">TickSec</a>/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rate\n</a>" "	   collisionTol = 0.1;        // <a href="/coding/class/structcollision/">Collision</a> distance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "	   contactTol = 0.1;          // Contact velocity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minRollSpeed = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   maxDrag = 0.5;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minDrag = 0.01;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dustHeight = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dragForce = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   vertFactor = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RigidShape\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )
DefineEngineMethod(RigidShape , forceClientTransform , void , () , "@brief Forces the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> jump <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/class/classrigidshape/">RigidShape</a>'s transform rather then warp <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" )
DefineEngineMethod(RigidShape , freezeSim , void , (bool isFrozen) , "@brief Enables or disables the physics simulation on the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param isFrozen Boolean frozen state <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Define the frozen <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state.\n</a>" "% isFrozen)
DefineEngineMethod(RigidShape , reset , void , () , "@brief Clears physic forces from the shape and sets it at <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rest.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Inform the <a href="/coding/class/classrigidshape/">RigidShape</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reset.\n</a>" "%thisRigidShape.reset();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/class/structshapebasedata/">ShapeBaseData</a>" )
IMPLEMENT_CALLBACK(RigidShape , onEnterLiquid , void , (const char *objId, F32 waterCoverage, const char *liquidType) , (objId, waterCoverage, liquidType) , "@brief Called whenever this <a href="/coding/class/classrigidshape/">RigidShape</a> object enters <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">liquid.\n\n</a>" "@param objId The ID of the rigidShape <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param waterCoverage Amount of water coverage the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">has.\n</a>" "@param liquidType Type of liquid that was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">entered.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// The <a href="/coding/class/classrigidshape/">RigidShape</a> object falls in a body of liquid, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "RigidShape::onEnterLiquid(%this,%objId,%waterCoverage,%liquidType)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run whenever this callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs.\n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" )
IMPLEMENT_CALLBACK(RigidShape , onLeaveLiquid , void , (const char *objId, const char *liquidType) , (objId, liquidType) , "@brief Called whenever the <a href="/coding/class/classrigidshape/">RigidShape</a> object exits <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">liquid.\n\n</a>" "@param objId The ID of the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param liquidType Type <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> liquid that was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exited.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// The <a href="/coding/class/classrigidshape/">RigidShape</a> object exits in a body of liquid, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "RigidShape::onLeaveLiquid(%this,%objId,%liquidType)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run whenever this callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs.\n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" )

Detailed Description

Public Variables

U32 sTriggerMask 

Public Functions

ConsoleDocClass(RigidShape , "@brief The <a href="/coding/class/classrigidshape/">RigidShape</a> class implements rigid-body physics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> DTS objects in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">world.\n\n</a>" "\"Rigid body physics\" refers <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> a system whereby objects are assumed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have a finite size, \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "equally distributed masses, and where deformations of the objects themselves are not accounted <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "Uses the <a href="/coding/class/classrigidshape/">RigidShape</a> class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">physics.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" " datablock <a href="/coding/class/classrigidshapedata/">RigidShapeData</a>(BouncingBoulder)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " category=\"RigidShape\";\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" "	   emap = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   // <a href="/coding/class/classrigid/">Rigid</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Body\n</a>" "	   mass = 500;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   massCenter = \"0 0 0\";    // Center of mass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rigid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">body\n</a>" "	   massBox = \"0 0 0\";         // Size of box used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> moment of inertia,\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "								  // <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> zero it defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> object bounding <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">box\n</a>" "	   drag = 0.2;                // Drag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coefficient\n</a>" "	   bodyFriction = 0.2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   bodyRestitution = 0.1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minImpactSpeed = 5;        // Impacts over this invoke the script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback\n</a>" "	   softImpactSpeed = 5;       // Play SoftImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   hardImpactSpeed = 15;      // Play HardImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   integration = 4;           // Physics integration: <a href="/coding/file/processlist_8h/#processlist_8h_1a6dfddc4b6033c4de60ed37c4fe30f650">TickSec</a>/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rate\n</a>" "	   collisionTol = 0.1;        // <a href="/coding/class/structcollision/">Collision</a> distance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "	   contactTol = 0.1;          // Contact velocity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minRollSpeed = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   maxDrag = 0.5;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minDrag = 0.01;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dustHeight = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dragForce = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   vertFactor = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classrigidshape/">RigidShape</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "		dataBlock = \"BouncingBoulder\";\n" "		parentGroup = EWCreatorWindow.objectGroup;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RigidShapeData\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )

ConsoleDocClass(RigidShapeData , "@brief Defines the physics properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an individual <a href="/coding/class/classrigidshapedata/">RigidShapeData</a> physics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" " datablock <a href="/coding/class/classrigidshapedata/">RigidShapeData</a>( BouncingBoulder )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   category = \"RigidShape\";\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" "	   emap = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   // <a href="/coding/class/classrigid/">Rigid</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Body\n</a>" "	   mass = 500;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   massCenter = \"0 0 0\";    // Center of mass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rigid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">body\n</a>" "	   massBox = \"0 0 0\";         // Size of box used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> moment of inertia,\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "								  // <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> zero it defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> object bounding <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">box\n</a>" "	   drag = 0.2;                // Drag <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">coefficient\n</a>" "	   bodyFriction = 0.2;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   bodyRestitution = 0.1;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minImpactSpeed = 5;        // Impacts over this invoke the script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback\n</a>" "	   softImpactSpeed = 5;       // Play SoftImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   hardImpactSpeed = 15;      // Play HardImpact <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Sound\n</a>" "	   integration = 4;           // Physics integration: <a href="/coding/file/processlist_8h/#processlist_8h_1a6dfddc4b6033c4de60ed37c4fe30f650">TickSec</a>/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rate\n</a>" "	   collisionTol = 0.1;        // <a href="/coding/class/structcollision/">Collision</a> distance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "	   contactTol = 0.1;          // Contact velocity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tolerance\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minRollSpeed = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   maxDrag = 0.5;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   minDrag = 0.01;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dustHeight = 10;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   dragForce = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	   vertFactor = 0.05;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "	};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RigidShape\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Physics\n</a>" )

DefineEngineMethod(RigidShape , forceClientTransform , void , () , "@brief Forces the client <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> jump <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/class/classrigidshape/">RigidShape</a>'s transform rather then warp <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" )

DefineEngineMethod(RigidShape , freezeSim , void , (bool isFrozen) , "@brief Enables or disables the physics simulation on the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param isFrozen Boolean frozen state <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Define the frozen <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state.\n</a>" "% isFrozen)

DefineEngineMethod(RigidShape , reset , void , () , "@brief Clears physic forces from the shape and sets it at <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rest.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Inform the <a href="/coding/class/classrigidshape/">RigidShape</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reset.\n</a>" "%thisRigidShape.reset();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/class/structshapebasedata/">ShapeBaseData</a>" )

IMPLEMENT_CALLBACK(RigidShape , onEnterLiquid , void , (const char *objId, F32 waterCoverage, const char *liquidType) , (objId, waterCoverage, liquidType) , "@brief Called whenever this <a href="/coding/class/classrigidshape/">RigidShape</a> object enters <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">liquid.\n\n</a>" "@param objId The ID of the rigidShape <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param waterCoverage Amount of water coverage the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">has.\n</a>" "@param liquidType Type of liquid that was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">entered.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// The <a href="/coding/class/classrigidshape/">RigidShape</a> object falls in a body of liquid, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "RigidShape::onEnterLiquid(%this,%objId,%waterCoverage,%liquidType)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run whenever this callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs.\n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" )

IMPLEMENT_CALLBACK(RigidShape , onLeaveLiquid , void , (const char *objId, const char *liquidType) , (objId, liquidType) , "@brief Called whenever the <a href="/coding/class/classrigidshape/">RigidShape</a> object exits <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">liquid.\n\n</a>" "@param objId The ID of the <a href="/coding/class/classrigidshape/">RigidShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param liquidType Type <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> liquid that was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exited.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// The <a href="/coding/class/classrigidshape/">RigidShape</a> object exits in a body of liquid, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "RigidShape::onLeaveLiquid(%this,%objId,%liquidType)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run whenever this callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs.\n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ShapeBase\n\n</a>" )

IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData )

IMPLEMENT_CO_NETOBJECT_V1(RigidShape )

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platform.h"
  25#include "T3D/rigidShape.h"
  26
  27#include "app/game.h"
  28#include "math/mMath.h"
  29#include "console/simBase.h"
  30#include "console/console.h"
  31#include "console/consoleTypes.h"
  32#include "collision/clippedPolyList.h"
  33#include "collision/planeExtractor.h"
  34#include "T3D/gameBase/moveManager.h"
  35#include "core/stream/bitStream.h"
  36#include "core/dnet.h"
  37#include "T3D/gameBase/gameConnection.h"
  38#include "ts/tsShapeInstance.h"
  39#include "math/mathIO.h"
  40#include "scene/sceneRenderState.h"
  41#include "scene/sceneManager.h"
  42#include "T3D/fx/cameraFXMgr.h"
  43#include "T3D/trigger.h"
  44#include "T3D/item.h"
  45#include "gfx/primBuilder.h"
  46#include "gfx/gfxDrawUtil.h"
  47#include "sfx/sfxTypes.h"
  48#include "sfx/sfxSystem.h"
  49#include "T3D/fx/particleEmitter.h"
  50#include "console/engineAPI.h"
  51
  52
  53IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
  54
  55ConsoleDocClass( RigidShapeData,
  56   "@brief Defines the physics properties for an individual RigidShapeData physics object.\n\n"
  57
  58   "@tsexample\n"
  59   "  datablock RigidShapeData( BouncingBoulder )\n"
  60   "  {\n"  
  61   "     category = \"RigidShape\";\n"
  62   "\n"     
  63   "     shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n"
  64   "     emap = true;\n"
  65   "\n"
  66   "     // Rigid Body\n"
  67   "     mass = 500;\n"
  68   "     massCenter = \"0 0 0\";    // Center of mass for rigid body\n"
  69   "     massBox = \"0 0 0\";         // Size of box used for moment of inertia,\n"
  70   "                         // if zero it defaults to object bounding box\n"
  71   "     drag = 0.2;                // Drag coefficient\n"
  72   "     bodyFriction = 0.2;\n"
  73   "     bodyRestitution = 0.1;\n"
  74   "     minImpactSpeed = 5;        // Impacts over this invoke the script callback\n"
  75   "     softImpactSpeed = 5;       // Play SoftImpact Sound\n"
  76   "     hardImpactSpeed = 15;      // Play HardImpact Sound\n"
  77   "     integration = 4;           // Physics integration: TickSec/Rate\n"
  78   "     collisionTol = 0.1;        // Collision distance tolerance\n"
  79   "     contactTol = 0.1;          // Contact velocity tolerance\n"
  80   "\n"     
  81   "     minRollSpeed = 10;\n"
  82   "\n"     
  83   "     maxDrag = 0.5;\n"
  84   "     minDrag = 0.01;\n"
  85   "\n"
  86   "     dustHeight = 10;\n"
  87   "\n"
  88   "     dragForce = 0.05;\n"
  89   "     vertFactor = 0.05;\n"
  90   "  };\n"
  91   "@endtsexample\n\n"
  92
  93   "@see RigidShape\n"
  94   "@see ShapeBase\n\n"
  95
  96   "@ingroup Physics\n"
  97);
  98
  99
 100IMPLEMENT_CO_NETOBJECT_V1(RigidShape);
 101
 102ConsoleDocClass( RigidShape,
 103   "@brief The RigidShape class implements rigid-body physics for DTS objects in the world.\n\n"
 104
 105   "\"Rigid body physics\" refers to a system whereby objects are assumed to have a finite size,\n"
 106   "equally distributed masses, and where deformations of the objects themselves are not accounted for.\n"
 107   "Uses the RigidShape class to control its physics.\n\n"
 108
 109   "@tsexample\n"
 110   "  datablock RigidShapeData( BouncingBoulder )\n"
 111   "  {\n"  
 112   "     category = \"RigidShape\";\n"
 113   "\n"     
 114   "     shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n"
 115   "     emap = true;\n"
 116   "\n"
 117   "     // Rigid Body\n"
 118   "     mass = 500;\n"
 119   "     massCenter = \"0 0 0\";    // Center of mass for rigid body\n"
 120   "     massBox = \"0 0 0\";         // Size of box used for moment of inertia,\n"
 121   "                         // if zero it defaults to object bounding box\n"
 122   "     drag = 0.2;                // Drag coefficient\n"
 123   "     bodyFriction = 0.2;\n"
 124   "     bodyRestitution = 0.1;\n"
 125   "     minImpactSpeed = 5;        // Impacts over this invoke the script callback\n"
 126   "     softImpactSpeed = 5;       // Play SoftImpact Sound\n"
 127   "     hardImpactSpeed = 15;      // Play HardImpact Sound\n"
 128   "     integration = 4;           // Physics integration: TickSec/Rate\n"
 129   "     collisionTol = 0.1;        // Collision distance tolerance\n"
 130   "     contactTol = 0.1;          // Contact velocity tolerance\n"
 131   "\n"     
 132   "     minRollSpeed = 10;\n"
 133   "\n"     
 134   "     maxDrag = 0.5;\n"
 135   "     minDrag = 0.01;\n"
 136   "\n"
 137   "     dustHeight = 10;\n"
 138   "\n"
 139   "     dragForce = 0.05;\n"
 140   "     vertFactor = 0.05;\n"
 141   "  };\n"
 142   "\n"
 143   " new RigidShape()\n"
 144   "  {\n"
 145    "    dataBlock = \"BouncingBoulder\";\n"
 146    "    parentGroup = EWCreatorWindow.objectGroup;\n"
 147    " };\n"
 148   "@endtsexample\n\n"
 149
 150   "@see RigidShapeData\n"
 151   "@see ShapeBase\n\n"
 152   
 153   "@ingroup Physics\n"
 154);
 155
 156
 157IMPLEMENT_CALLBACK( RigidShape, onEnterLiquid, void, ( const char* objId, F32 waterCoverage, const char* liquidType ),
 158                                        ( objId, waterCoverage, liquidType ),
 159   "@brief Called whenever this RigidShape object enters liquid.\n\n"
 160   "@param objId The ID of the rigidShape object.\n"
 161   "@param waterCoverage Amount of water coverage the RigidShape has.\n"
 162   "@param liquidType Type of liquid that was entered.\n\n"
 163   "@tsexample\n"
 164   "// The RigidShape object falls in a body of liquid, causing the callback to occur.\n"
 165   "RigidShape::onEnterLiquid(%this,%objId,%waterCoverage,%liquidType)\n"
 166   "  {\n"
 167   "     // Code to run whenever this callback occurs.\n"
 168   "  }\n"
 169   "@endtsexample\n\n"
 170   "@see ShapeBase\n\n"
 171);
 172
 173IMPLEMENT_CALLBACK( RigidShape, onLeaveLiquid, void, ( const char* objId, const char* liquidType ),( objId, liquidType ),
 174   "@brief Called whenever the RigidShape object exits liquid.\n\n"
 175   "@param objId The ID of the RigidShape object.\n"
 176   "@param liquidType Type if liquid that was exited.\n\n"
 177   "@tsexample\n"
 178   "// The RigidShape object exits in a body of liquid, causing the callback to occur.\n"
 179   "RigidShape::onLeaveLiquid(%this,%objId,%liquidType)\n"
 180   "  {\n"
 181   "     // Code to run whenever this callback occurs.\n"
 182   "  }\n"
 183   "@endtsexample\n\n"
 184   "@see ShapeBase\n\n"
 185);
 186
 187//----------------------------------------------------------------------------
 188
 189namespace {
 190
 191   // Client prediction
 192   const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 193   const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
 194   const F32 sRigidShapeGravity = -20;
 195
 196   // Physics and collision constants
 197   static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
 198   static S32 sRestCount = 10;            // Consecutive ticks before comming to rest
 199
 200   const U32 sCollisionMoveMask = ( TerrainObjectType     | PlayerObjectType  | 
 201                                    StaticShapeObjectType | VehicleObjectType |
 202                                    VehicleBlockerObjectType );
 203
 204   const U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
 205   const U32 sClientCollisionMask = sCollisionMoveMask;
 206
 207   void nonFilter(SceneObject* object,void *key)
 208   {
 209      SceneContainer::CallbackInfo* info = reinterpret_cast<SceneContainer::CallbackInfo*>(key);
 210      object->buildPolyList(info->context,info->polyList,info->boundingBox,info->boundingSphere);
 211   }
 212
 213} // namespace {}
 214
 215
 216// Trigger objects that are not normally collided with.
 217static U32 sTriggerMask = ItemObjectType     |
 218TriggerObjectType  |
 219CorpseObjectType;
 220
 221
 222//----------------------------------------------------------------------------
 223
 224RigidShapeData::RigidShapeData()
 225{
 226   shadowEnable = true;
 227
 228   body.friction = 0;
 229   body.restitution = 1;
 230
 231   minImpactSpeed = 25;
 232   softImpactSpeed = 25;
 233   hardImpactSpeed = 50;
 234   minRollSpeed = 0;
 235
 236   cameraRoll = true;
 237   cameraLag = 0;
 238   cameraDecay = 0;
 239   cameraOffset = 0;
 240
 241   minDrag = 0;
 242   maxDrag = 0;
 243   integration = 1;
 244   collisionTol = 0.1f;
 245   contactTol = 0.1f;
 246   massCenter.set(0,0,0);
 247   massBox.set(0,0,0);
 248
 249   drag = 0.7f;
 250   density = 4;
 251
 252   for (S32 i = 0; i < Body::MaxSounds; i++)
 253      body.sound[i] = 0;
 254
 255   dustEmitter = NULL;
 256   dustID = 0;
 257   dustHeight = 1.0;
 258
 259   dMemset( splashEmitterList, 0, sizeof( splashEmitterList ) );
 260   dMemset( splashEmitterIDList, 0, sizeof( splashEmitterIDList ) );
 261
 262   splashFreqMod = 300.0;
 263   splashVelEpsilon = 0.50;
 264   exitSplashSoundVel = 2.0;
 265   softSplashSoundVel = 1.0;
 266   medSplashSoundVel = 2.0;
 267   hardSplashSoundVel = 3.0;
 268
 269   dMemset(waterSound, 0, sizeof(waterSound));
 270
 271   dragForce            = 0;
 272   vertFactor           = 0.25;
 273
 274   dustTrailEmitter = NULL;
 275   dustTrailID = 0;
 276}
 277
 278RigidShapeData::~RigidShapeData()
 279{
 280
 281}
 282
 283//----------------------------------------------------------------------------
 284
 285
 286bool RigidShapeData::onAdd()
 287{
 288   if(!Parent::onAdd())
 289      return false;
 290
 291   return true;
 292}
 293
 294
 295bool RigidShapeData::preload(bool server, String &errorStr)
 296{
 297   if (!Parent::preload(server, errorStr))
 298      return false;
 299
 300   // RigidShape objects must define a collision detail
 301   if (!collisionDetails.size() || collisionDetails[0] == -1)
 302   {
 303      Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail");
 304      errorStr = String::ToString("RigidShapeData: Couldn't load shape \"%s\"",shapeName);
 305      return false;
 306   }
 307
 308   // Resolve objects transmitted from server
 309   if (!server) {
 310      for (S32 i = 0; i < Body::MaxSounds; i++)
 311         sfxResolve( &body.sound[ i ], errorStr );
 312   }
 313
 314   if( !dustEmitter && dustID != 0 )
 315   {
 316      if( !Sim::findObject( dustID, dustEmitter ) )
 317      {
 318         Con::errorf( ConsoleLogEntry::General, "RigidShapeData::preload Invalid packet, bad datablockId(dustEmitter): 0x%x", dustID );
 319      }
 320   }
 321
 322   U32 i;
 323   for( i=0; i<VC_NUM_SPLASH_EMITTERS; i++ )
 324   {
 325      if( !splashEmitterList[i] && splashEmitterIDList[i] != 0 )
 326      {
 327         if( !Sim::findObject( splashEmitterIDList[i], splashEmitterList[i] ) )
 328         {
 329            Con::errorf( ConsoleLogEntry::General, "RigidShapeData::preload Invalid packet, bad datablockId(splashEmitter): 0x%x", splashEmitterIDList[i] );
 330         }
 331      }
 332   }
 333
 334   if (dragForce <= 0.01f) 
 335   {
 336      Con::warnf("RigidShapeData::preload: dragForce must be at least 0.01");
 337      dragForce = 0.01f;
 338   }
 339
 340   if (vertFactor < 0.0f || vertFactor > 1.0f) 
 341   {
 342      Con::warnf("RigidShapeData::preload: vert factor must be [0, 1]");
 343      vertFactor = vertFactor < 0.0f ? 0.0f : 1.0f;
 344   }
 345
 346   if( !dustTrailEmitter && dustTrailID != 0 )
 347   {
 348      if( !Sim::findObject( dustTrailID, dustTrailEmitter ) )
 349      {
 350         Con::errorf( ConsoleLogEntry::General, "RigidShapeData::preload Invalid packet, bad datablockId(dustTrailEmitter): 0x%x", dustTrailID );
 351      }
 352   }
 353
 354   return true;
 355}   
 356
 357
 358//----------------------------------------------------------------------------
 359
 360void RigidShapeData::packData(BitStream* stream)
 361{
 362   Parent::packData(stream);
 363
 364   stream->write(body.restitution);
 365   stream->write(body.friction);
 366   for( U32 i = 0; i < Body::MaxSounds; ++ i )
 367      sfxWrite( stream, body.sound[ i ] );
 368
 369   stream->write(minImpactSpeed);
 370   stream->write(softImpactSpeed);
 371   stream->write(hardImpactSpeed);
 372   stream->write(minRollSpeed);
 373
 374   stream->write(maxDrag);
 375   stream->write(minDrag);
 376   stream->write(integration);
 377   stream->write(collisionTol);
 378   stream->write(contactTol);
 379   mathWrite(*stream,massCenter);
 380   mathWrite(*stream,massBox);
 381
 382   stream->writeFlag(cameraRoll);
 383   stream->write(cameraLag);
 384   stream->write(cameraDecay);
 385   stream->write(cameraOffset);
 386
 387   stream->write( dustHeight );
 388
 389   stream->write(exitSplashSoundVel);
 390   stream->write(softSplashSoundVel);
 391   stream->write(medSplashSoundVel);
 392   stream->write(hardSplashSoundVel);
 393
 394   // write the water sound profiles
 395   for( U32 i = 0; i < MaxSounds; ++ i )
 396      sfxWrite( stream, waterSound[ i ] );
 397
 398   if (stream->writeFlag( dustEmitter ))
 399      stream->writeRangedU32( dustEmitter->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast );
 400
 401   for( U32 i = 0; i < VC_NUM_SPLASH_EMITTERS; ++ i )
 402   {
 403      if( stream->writeFlag( splashEmitterList[i] != NULL ) )
 404         stream->writeRangedU32( splashEmitterList[i]->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast );
 405   }
 406
 407   stream->write(splashFreqMod);
 408   stream->write(splashVelEpsilon);
 409
 410   stream->write(dragForce);
 411   stream->write(vertFactor);
 412
 413   if (stream->writeFlag( dustTrailEmitter ))
 414      stream->writeRangedU32( dustTrailEmitter->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast );
 415}   
 416
 417void RigidShapeData::unpackData(BitStream* stream)
 418{
 419   Parent::unpackData(stream);
 420
 421   stream->read(&body.restitution);
 422   stream->read(&body.friction);
 423
 424   for( U32 i = 0; i < Body::MaxSounds; i++)
 425      sfxRead( stream, &body.sound[ i ] );
 426
 427   stream->read(&minImpactSpeed);
 428   stream->read(&softImpactSpeed);
 429   stream->read(&hardImpactSpeed);
 430   stream->read(&minRollSpeed);
 431
 432   stream->read(&maxDrag);
 433   stream->read(&minDrag);
 434   stream->read(&integration);
 435   stream->read(&collisionTol);
 436   stream->read(&contactTol);
 437   mathRead(*stream,&massCenter);
 438   mathRead(*stream,&massBox);
 439
 440   cameraRoll = stream->readFlag();
 441   stream->read(&cameraLag);
 442   stream->read(&cameraDecay);
 443   stream->read(&cameraOffset);
 444
 445   stream->read( &dustHeight );
 446
 447   stream->read(&exitSplashSoundVel);
 448   stream->read(&softSplashSoundVel);
 449   stream->read(&medSplashSoundVel);
 450   stream->read(&hardSplashSoundVel);
 451
 452   // write the water sound profiles
 453   for( U32 i = 0; i < MaxSounds; ++ i )
 454      sfxRead( stream, &waterSound[ i ] );
 455
 456   if( stream->readFlag() )
 457      dustID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
 458
 459   for( U32 i = 0; i < VC_NUM_SPLASH_EMITTERS; ++ i )
 460   {
 461      if( stream->readFlag() )
 462         splashEmitterIDList[i] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
 463   }
 464
 465   stream->read(&splashFreqMod);
 466   stream->read(&splashVelEpsilon);
 467
 468   stream->read(&dragForce);
 469   stream->read(&vertFactor);
 470
 471   if( stream->readFlag() )
 472      dustTrailID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
 473}   
 474
 475
 476//----------------------------------------------------------------------------
 477
 478void RigidShapeData::initPersistFields()
 479{
 480   addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
 481   addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
 482   addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
 483   addField("bodyFriction", TypeF32, Offset(body.friction, RigidShapeData), "How much friction this object has. Lower values will cause the object to appear to be more slippery.");
 484
 485   addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, RigidShapeData),
 486      "Minimum collision speed to classify collision as impact (triggers onImpact on server object)." );
 487   addField("softImpactSpeed", TypeF32, Offset(softImpactSpeed, RigidShapeData), "Minimum speed at which this object must be travelling for the soft impact sound to be played.");
 488   addField("hardImpactSpeed", TypeF32, Offset(hardImpactSpeed, RigidShapeData), "Minimum speed at which the object must be travelling for the hard impact sound to be played.");
 489   addField("minRollSpeed", TypeF32, Offset(minRollSpeed, RigidShapeData));
 490
 491   addField("maxDrag", TypeF32, Offset(maxDrag, RigidShapeData), "Maximum drag available to this object.");
 492   addField("minDrag", TypeF32, Offset(minDrag, RigidShapeData), "Minimum drag available to this object.");
 493   addField("integration", TypeS32, Offset(integration, RigidShapeData), "Number of physics steps to process per tick.");
 494   addField("collisionTol", TypeF32, Offset(collisionTol, RigidShapeData), "Collision distance tolerance.");
 495   addField("contactTol", TypeF32, Offset(contactTol, RigidShapeData), "Contact velocity tolerance.");
 496   
 497   addGroup( "Forces" );
 498
 499      addField("dragForce",            TypeF32, Offset(dragForce,            RigidShapeData), "Used to simulate the constant drag acting on the object");
 500      addField("vertFactor",           TypeF32, Offset(vertFactor,           RigidShapeData), "The scalar applied to the vertical portion of the velocity drag acting on a object.");
 501   
 502   endGroup( "Forces" );
 503   
 504   addGroup( "Particle Effects" );
 505
 506      addField("dustEmitter",       TYPEID< ParticleEmitterData >(),   Offset(dustEmitter,        RigidShapeData), "Array of pointers to ParticleEmitterData datablocks which will be used to emit particles at object/terrain contact point.\n");
 507      addField("triggerDustHeight", TypeF32,                      Offset(triggerDustHeight,  RigidShapeData), "Maximum height from the ground at which the object will generate dust.\n");
 508      addField("dustHeight",        TypeF32,                      Offset(dustHeight,         RigidShapeData), "Height of dust effects.\n");
 509
 510      addField("dustTrailEmitter",     TYPEID< ParticleEmitterData >(),   Offset(dustTrailEmitter,   RigidShapeData), "Particle emitter used to create a dust trail for the moving object.\n");
 511
 512      addField("splashEmitter",        TYPEID< ParticleEmitterData >(),   Offset(splashEmitterList,     RigidShapeData), VC_NUM_SPLASH_EMITTERS, "Array of pointers to ParticleEmitterData datablocks which will generate splash effects.\n");
 513
 514      addField("splashFreqMod",  TypeF32,                Offset(splashFreqMod,   RigidShapeData), "The simulated frequency modulation of a splash generated by this object. Multiplied along with speed and time elapsed when determining splash emition rate.\n");
 515      addField("splashVelEpsilon", TypeF32,              Offset(splashVelEpsilon, RigidShapeData), "The threshold speed at which we consider the object's movement to have stopped when updating splash effects.\n");
 516      
 517   endGroup( "Particle Effects" );
 518   
 519   addGroup( "Sounds" );
 520
 521      addField("softImpactSound", TypeSFXTrackName, Offset(body.sound[Body::SoftImpactSound], RigidShapeData),
 522         "Sound to play when body impacts with at least softImageSpeed but less than hardImpactSpeed." );
 523      addField("hardImpactSound", TypeSFXTrackName, Offset(body.sound[Body::HardImpactSound], RigidShapeData),
 524         "Sound to play when body impacts with at least hardImpactSpeed." );
 525
 526      addField("exitSplashSoundVelocity", TypeF32,       Offset(exitSplashSoundVel, RigidShapeData), "The minimum velocity at which the exit splash sound will be played when emerging from water.\n");
 527      addField("softSplashSoundVelocity", TypeF32,       Offset(softSplashSoundVel, RigidShapeData),"The minimum velocity at which the soft splash sound will be played when impacting water.\n");
 528      addField("mediumSplashSoundVelocity", TypeF32,     Offset(medSplashSoundVel, RigidShapeData), "The minimum velocity at which the medium splash sound will be played when impacting water.\n");
 529      addField("hardSplashSoundVelocity", TypeF32,       Offset(hardSplashSoundVel, RigidShapeData), "The minimum velocity at which the hard splash sound will be played when impacting water.\n");
 530      addField("exitingWater",      TypeSFXTrackName,   Offset(waterSound[ExitWater],   RigidShapeData), "The AudioProfile will be used to produce sounds when emerging from water.\n");
 531      addField("impactWaterEasy",   TypeSFXTrackName,   Offset(waterSound[ImpactSoft],   RigidShapeData), "The AudioProfile will be used to produce sounds when a soft impact with water occurs.\n");
 532      addField("impactWaterMedium", TypeSFXTrackName,   Offset(waterSound[ImpactMedium],   RigidShapeData), "The AudioProfile will be used to produce sounds when a medium impact with water occurs.\n");
 533      addField("impactWaterHard",   TypeSFXTrackName,   Offset(waterSound[ImpactHard],   RigidShapeData), "The AudioProfile will be used to produce sounds when a hard impact with water occurs.\n");
 534      addField("waterWakeSound",    TypeSFXTrackName,   Offset(waterSound[Wake],   RigidShapeData), "The AudioProfile will be used to produce sounds when a water wake is displayed.\n");
 535      
 536   endGroup( "Sounds" );
 537   
 538   addGroup( "Camera" );
 539
 540      addField("cameraRoll",     TypeBool,       Offset(cameraRoll,     RigidShapeData), "Specifies whether the camera's rotation matrix, and the render eye transform are multiplied during camera updates.\n");
 541      addField("cameraLag",      TypeF32,        Offset(cameraLag,      RigidShapeData), "Scalar amount by which the third person camera lags the object, relative to the object's linear velocity.\n");
 542      addField("cameraDecay",  TypeF32,        Offset(cameraDecay,  RigidShapeData), "Scalar rate at which the third person camera offset decays, per tick.\n");
 543      addField("cameraOffset",   TypeF32,        Offset(cameraOffset,   RigidShapeData), "The vertical offset of the object's camera.\n");
 544      
 545   endGroup( "Camera" );
 546
 547   Parent::initPersistFields();
 548}   
 549
 550
 551//----------------------------------------------------------------------------
 552//----------------------------------------------------------------------------
 553
 554//----------------------------------------------------------------------------
 555
 556RigidShape::RigidShape()
 557{
 558
 559   mNetFlags.set(Ghostable);
 560
 561   mDustTrailEmitter = NULL;
 562
 563   mDataBlock = 0;
 564   // [rene, 27-Apr-11] WTH is a RigidShape a vehicle???
 565   mTypeMask |= VehicleObjectType | DynamicShapeObjectType;
 566
 567   mDelta.pos = Point3F(0,0,0);
 568   mDelta.posVec = Point3F(0,0,0);
 569   mDelta.warpTicks = mDelta.warpCount = 0;
 570   mDelta.dt = 1;
 571   mDelta.move = NullMove;
 572   mPredictionCount = 0;
 573   mDelta.cameraOffset.set(0,0,0);
 574   mDelta.cameraVec.set(0,0,0);
 575   mDelta.cameraRot.set(0,0,0);
 576   mDelta.cameraRotVec.set(0,0,0);
 577
 578   mRigid.linPosition.set(0, 0, 0);
 579   mRigid.linVelocity.set(0, 0, 0);
 580   mRigid.angPosition.identity();
 581   mRigid.angVelocity.set(0, 0, 0);
 582   mRigid.linMomentum.set(0, 0, 0);
 583   mRigid.angMomentum.set(0, 0, 0);
 584   mContacts.clear();
 585
 586   mCameraOffset.set(0,0,0);
 587
 588   dMemset( mDustEmitterList, 0, sizeof( mDustEmitterList ) );
 589   dMemset( mSplashEmitterList, 0, sizeof( mSplashEmitterList ) );
 590
 591   mDisableMove = false; // start frozen by default
 592   restCount = 0;
 593
 594   inLiquid = false;
 595}   
 596
 597RigidShape::~RigidShape()
 598{
 599   //
 600}
 601
 602U32 RigidShape::getCollisionMask()
 603{
 604   if (isServerObject())
 605      return sServerCollisionMask;
 606   else
 607      return sClientCollisionMask;
 608}
 609
 610Point3F RigidShape::getVelocity() const
 611{
 612   return mRigid.linVelocity;
 613}
 614
 615//----------------------------------------------------------------------------
 616
 617bool RigidShape::onAdd()
 618{
 619   if (!Parent::onAdd())
 620      return false;
 621
 622   // When loading from a mission script, the base SceneObject's transform
 623   // will have been set and needs to be transfered to the rigid body.
 624   mRigid.setTransform(mObjToWorld);
 625
 626   // Initialize interpolation vars.      
 627   mDelta.rot[1] = mDelta.rot[0] = mRigid.angPosition;
 628   mDelta.pos = mRigid.linPosition;
 629   mDelta.posVec = Point3F(0,0,0);
 630
 631   // Create Emitters on the client
 632   if( isClientObject() )
 633   {
 634      if( mDataBlock->dustEmitter )
 635      {
 636         for( U32 i=0; i<RigidShapeData::VC_NUM_DUST_EMITTERS; i++ )
 637         {
 638            mDustEmitterList[i] = new ParticleEmitter;
 639            mDustEmitterList[i]->onNewDataBlock( mDataBlock->dustEmitter, false );
 640            if( !mDustEmitterList[i]->registerObject() )
 641            {
 642               Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
 643               delete mDustEmitterList[i];
 644               mDustEmitterList[i] = NULL;
 645            }
 646         }
 647      }
 648
 649      for( U32 j=0; j<RigidShapeData::VC_NUM_SPLASH_EMITTERS; j++ )
 650      {
 651         if( mDataBlock->splashEmitterList[j] )
 652         {
 653            mSplashEmitterList[j] = new ParticleEmitter;
 654            mSplashEmitterList[j]->onNewDataBlock( mDataBlock->splashEmitterList[j], false );
 655            if( !mSplashEmitterList[j]->registerObject() )
 656            {
 657               Con::warnf( ConsoleLogEntry::General, "Could not register splash emitter for class: %s", mDataBlock->getName() );
 658               delete mSplashEmitterList[j];
 659               mSplashEmitterList[j] = NULL;
 660            }
 661
 662         }
 663      }
 664   }
 665
 666   // Create a new convex.
 667   AssertFatal(mDataBlock->collisionDetails[0] != -1, "Error, a rigid shape must have a collision-1 detail!");
 668   mConvex.mObject    = this;
 669   mConvex.pShapeBase = this;
 670   mConvex.hullId     = 0;
 671   mConvex.box        = mObjBox;
 672   mConvex.box.minExtents.convolve(mObjScale);
 673   mConvex.box.maxExtents.convolve(mObjScale);
 674   mConvex.findNodeTransform();
 675
 676   addToScene();
 677
 678
 679   if( !isServerObject() )
 680   {
 681      if( mDataBlock->dustTrailEmitter )
 682      {
 683         mDustTrailEmitter = new ParticleEmitter;
 684         mDustTrailEmitter->onNewDataBlock( mDataBlock->dustTrailEmitter, false );
 685         if( !mDustTrailEmitter->registerObject() )
 686         {
 687            Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
 688            delete mDustTrailEmitter;
 689            mDustTrailEmitter = NULL;
 690         }
 691      }
 692   }
 693
 694
 695   if (isServerObject())
 696      scriptOnAdd();
 697
 698   return true;
 699}
 700
 701void RigidShape::onRemove()
 702{
 703   scriptOnRemove();
 704   removeFromScene();
 705
 706   U32 i=0;
 707   for( i=0; i<RigidShapeData::VC_NUM_DUST_EMITTERS; i++ )
 708   {
 709      if( mDustEmitterList[i] )
 710      {
 711         mDustEmitterList[i]->deleteWhenEmpty();
 712         mDustEmitterList[i] = NULL;
 713      }
 714   }
 715
 716   for( i=0; i<RigidShapeData::VC_NUM_SPLASH_EMITTERS; i++ )
 717   {
 718      if( mSplashEmitterList[i] )
 719      {
 720         mSplashEmitterList[i]->deleteWhenEmpty();
 721         mSplashEmitterList[i] = NULL;
 722      }
 723   }
 724
 725   Parent::onRemove();
 726}
 727
 728
 729//----------------------------------------------------------------------------
 730
 731void RigidShape::processTick(const Move* move)
 732{     
 733   Parent::processTick(move);
 734   if ( isMounted() )
 735      return;
 736
 737   // Warp to catch up to server
 738   if (mDelta.warpCount < mDelta.warpTicks) 
 739   {
 740      mDelta.warpCount++;
 741
 742      // Set new pos.
 743      mObjToWorld.getColumn(3,&mDelta.pos);
 744      mDelta.pos += mDelta.warpOffset;
 745      mDelta.rot[0] = mDelta.rot[1];
 746      mDelta.rot[1].interpolate(mDelta.warpRot[0],mDelta.warpRot[1],F32(mDelta.warpCount)/<a href="/coding/class/classrigidshape/#classrigidshape_1a4a7d0e60ba7dff122314e6ac9034e3bb">mDelta</a>.warpTicks);
 747      setPosition(mDelta.pos,mDelta.rot[1]);
 748
 749      // Pos backstepping
 750      mDelta.posVec.x = -mDelta.warpOffset.x;
 751      mDelta.posVec.y = -mDelta.warpOffset.y;
 752      mDelta.posVec.z = -mDelta.warpOffset.z;
 753   }
 754   else 
 755   {
 756      if (!move) 
 757      {
 758         if (isGhost()) 
 759         {
 760            // If we haven't run out of prediction time,
 761            // predict using the last known move.
 762            if (mPredictionCount-- <= 0)
 763               return;
 764            move = &mDelta.move;
 765         }
 766         else
 767            move = &NullMove;
 768      }
 769
 770      // Process input move
 771      updateMove(move);
 772
 773      // Save current rigid state interpolation
 774      mDelta.posVec = mRigid.linPosition;
 775      mDelta.rot[0] = mRigid.angPosition;
 776
 777      // Update the physics based on the integration rate
 778      S32 count = mDataBlock->integration;
 779      if (!mDisableMove)
 780         updateWorkingCollisionSet(getCollisionMask());
 781      for (U32 i = 0; i < count; i++)
 782         updatePos(TickSec / count);
 783
 784      // Wrap up interpolation info
 785      mDelta.pos     = mRigid.linPosition;
 786      mDelta.posVec -= mRigid.linPosition;
 787      mDelta.rot[1]  = mRigid.angPosition;
 788
 789      // Update container database
 790      setPosition(mRigid.linPosition, mRigid.angPosition);
 791      setMaskBits(PositionMask);
 792      updateContainer();
 793   }
 794}
 795
 796void RigidShape::interpolateTick(F32 dt)
 797{     
 798   Parent::interpolateTick(dt);
 799   if ( isMounted() )
 800      return;
 801
 802   if(dt == 0.0f)
 803      setRenderPosition(mDelta.pos, mDelta.rot[1]);
 804   else
 805   {
 806      QuatF rot;
 807      rot.interpolate(mDelta.rot[1], mDelta.rot[0], dt);
 808      Point3F pos = mDelta.pos + mDelta.posVec * dt;
 809      setRenderPosition(pos,rot);
 810   }
 811   mDelta.dt = dt;
 812}
 813
 814void RigidShape::advanceTime(F32 dt)
 815{     
 816   Parent::advanceTime(dt);
 817
 818   updateFroth(dt);
 819
 820   if ( isMounted() )
 821      return;
 822
 823   // Update 3rd person camera offset.  Camera update is done
 824   // here as it's a client side only animation.
 825   mCameraOffset -=
 826      (mCameraOffset * mDataBlock->cameraDecay +
 827      mRigid.linVelocity * mDataBlock->cameraLag) * dt;
 828}
 829
 830
 831//----------------------------------------------------------------------------
 832
 833bool RigidShape::onNewDataBlock(GameBaseData* dptr, bool reload)
 834{
 835   mDataBlock = dynamic_cast<RigidShapeData*>(dptr);
 836   if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
 837      return false;
 838
 839   // Update Rigid Info
 840   mRigid.mass = mDataBlock->mass;
 841   mRigid.oneOverMass = 1 / mRigid.mass;
 842   mRigid.friction = mDataBlock->body.friction;
 843   mRigid.restitution = mDataBlock->body.restitution;
 844   mRigid.setCenterOfMass(mDataBlock->massCenter);
 845
 846   // Ignores massBox, just set sphere for now. Derived objects
 847   // can set what they want.
 848   mRigid.setObjectInertia();
 849
 850   scriptOnNewDataBlock();
 851
 852   return true;
 853}
 854
 855
 856//----------------------------------------------------------------------------
 857
 858void RigidShape::getCameraParameters(F32 *min,F32* max,Point3F* off,MatrixF* rot)
 859{
 860   *min = mDataBlock->cameraMinDist;
 861   *max = mDataBlock->cameraMaxDist;
 862
 863   off->set(0,0,mDataBlock->cameraOffset);
 864   rot->identity();
 865}
 866
 867
 868//----------------------------------------------------------------------------
 869
 870void RigidShape::getCameraTransform(F32* pos,MatrixF* mat)
 871{
 872   // Returns camera to world space transform
 873   // Handles first person / third person camera position
 874   if (isServerObject() && mShapeInstance)
 875      mShapeInstance->animateNodeSubtrees(true);
 876
 877   if (*pos == 0) 
 878   {
 879      getRenderEyeTransform(mat);
 880      return;
 881   }
 882
 883   // Get the shape's camera parameters.
 884   F32 min,max;
 885   MatrixF rot;
 886   Point3F offset;
 887   getCameraParameters(&min,&max,&offset,&rot);
 888
 889   // Start with the current eye position
 890   MatrixF eye;
 891   getRenderEyeTransform(&eye);
 892
 893   // Build a transform that points along the eye axis
 894   // but where the Z axis is always up.
 895   if (mDataBlock->cameraRoll)
 896      mat->mul(eye,rot);
 897   else 
 898   {
 899      MatrixF cam(1);
 900      VectorF x,y,z(0,0,1);
 901      eye.getColumn(1, &y);
 902      
 903      mCross(y, z, &x);
 904      x.normalize();
 905      mCross(x, y, &z);
 906      z.normalize();
 907
 908      cam.setColumn(0,x);
 909      cam.setColumn(1,y);
 910      cam.setColumn(2,z);
 911      mat->mul(cam,rot);
 912   }
 913
 914   // Camera is positioned straight back along the eye's -Y axis.
 915   // A ray is cast to make sure the camera doesn't go through
 916   // anything solid.
 917   VectorF vp,vec;
 918   vp.x = vp.z = 0;
 919   vp.y = -(max - min) * *pos;
 920   eye.mulV(vp,&vec);
 921
 922   // Use the camera node as the starting position if it exists.
 923   Point3F osp,sp;
 924   if (mDataBlock->cameraNode != -1) 
 925   {
 926      mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp);
 927      getRenderTransform().mulP(osp,&sp);
 928   }
 929   else
 930      eye.getColumn(3,&sp);
 931
 932   // Make sure we don't hit ourself...
 933   disableCollision();
 934   if (isMounted())
 935      getObjectMount()->disableCollision();
 936
 937   // Cast the ray into the container database to see if we're going
 938   // to hit anything.
 939   RayInfo collision;
 940   Point3F ep = sp + vec + offset + mCameraOffset;
 941   if (mContainer->castRay(sp, ep,
 942      ~(WaterObjectType | GameBaseObjectType | DefaultObjectType),
 943      &collision) == true) 
 944   {
 945
 946         // Shift the collision point back a little to try and
 947         // avoid clipping against the front camera plane.
 948         F32 t = collision.t - (-mDot(vec, collision.normal) / vec.len()) * 0.1;
 949         if (t > 0.0f)
 950            ep = sp + offset + mCameraOffset + (vec * t);
 951         else
 952            eye.getColumn(3,&ep);
 953      }
 954      mat->setColumn(3,ep);
 955
 956      // Re-enable our collision.
 957      if (isMounted())
 958         getObjectMount()->enableCollision();
 959      enableCollision();
 960
 961   // Apply Camera FX.
 962   mat->mul( gCamFXMgr.getTrans() );
 963}
 964
 965
 966//----------------------------------------------------------------------------
 967
 968void RigidShape::getVelocity(const Point3F& r, Point3F* v)
 969{
 970   mRigid.getVelocity(r, v);
 971}
 972
 973void RigidShape::applyImpulse(const Point3F &pos, const Point3F &impulse)
 974{
 975   Point3F r;
 976   mRigid.getOriginVector(pos,&r);
 977   mRigid.applyImpulse(r, impulse);
 978}
 979
 980
 981//----------------------------------------------------------------------------
 982
 983void RigidShape::updateMove(const Move* move)
 984{
 985   mDelta.move = *move;
 986}
 987
 988//----------------------------------------------------------------------------
 989
 990void RigidShape::setPosition(const Point3F& pos,const QuatF& rot)
 991{
 992   MatrixF mat;
 993   rot.setMatrix(&mat);
 994   mat.setColumn(3,pos);
 995   Parent::setTransform(mat);
 996}
 997
 998void RigidShape::setRenderPosition(const Point3F& pos, const QuatF& rot)
 999{
1000   MatrixF mat;
1001   rot.setMatrix(&mat);
1002   mat.setColumn(3,pos);
1003   Parent::setRenderTransform(mat);
1004}
1005
1006void RigidShape::setTransform(const MatrixF& newMat)
1007{
1008   mRigid.setTransform(newMat);
1009   Parent::setTransform(newMat);
1010   mRigid.atRest = false;
1011   mContacts.clear();
1012}
1013
1014void RigidShape::forceClientTransform()
1015{
1016   setMaskBits(ForceMoveMask);
1017}
1018
1019
1020//-----------------------------------------------------------------------------
1021
1022void RigidShape::disableCollision()
1023{
1024   Parent::disableCollision();
1025}
1026
1027void RigidShape::enableCollision()
1028{
1029   Parent::enableCollision();
1030}   
1031
1032
1033//----------------------------------------------------------------------------
1034/** Update the physics
1035*/
1036
1037void RigidShape::updatePos(F32 dt)
1038{
1039   Point3F origVelocity = mRigid.linVelocity;
1040
1041   // Update internal forces acting on the body.
1042   mRigid.clearForces();
1043   updateForces(dt);
1044
1045   // Update collision information based on our current pos.
1046   bool collided = false;
1047   if (!mRigid.atRest && !mDisableMove) 
1048   {
1049      collided = updateCollision(dt);
1050
1051      // Now that all the forces have been processed, lets       
1052      // see if we're at rest.  Basically, if the kinetic energy of
1053      // the shape is less than some percentage of the energy added
1054      // by gravity for a short period, we're considered at rest.
1055      // This should really be part of the rigid class...
1056      if (mCollisionList.getCount()) 
1057      {
1058         F32 k = mRigid.getKineticEnergy();
1059         F32 G = sRigidShapeGravity * dt;
1060         F32 Kg = 0.5 * mRigid.mass * G * G;
1061         if (k < sRestTol * Kg && ++restCount > sRestCount)
1062            mRigid.setAtRest();
1063      }
1064      else
1065         restCount = 0;
1066   }
1067
1068   // Integrate forward
1069   if (!mRigid.atRest && !mDisableMove)
1070      mRigid.integrate(dt);
1071
1072   // Deal with client and server scripting, sounds, etc.
1073   if (isServerObject()) 
1074   {
1075
1076      // Check triggers and other objects that we normally don't
1077      // collide with.  This function must be called before notifyCollision
1078      // as it will queue collision.
1079      checkTriggers();
1080
1081      // Invoke the onCollision notify callback for all the objects
1082      // we've just hit.
1083      notifyCollision();
1084
1085      // Server side impact script callback
1086      if (collided) 
1087      {
1088         VectorF collVec = mRigid.linVelocity - origVelocity;
1089         F32 collSpeed = collVec.len();
1090         if (collSpeed > mDataBlock->minImpactSpeed)
1091            onImpact(collVec);
1092      }
1093
1094      // Water script callbacks      
1095      if (!inLiquid && mWaterCoverage != 0.0f) 
1096      {
1097         onEnterLiquid_callback(getIdString(), mWaterCoverage, mLiquidType.c_str() );
1098         inLiquid = true;
1099      }
1100      else if (inLiquid && mWaterCoverage == 0.0f) 
1101      {
1102       onLeaveLiquid_callback(getIdString(), mLiquidType.c_str() );
1103         inLiquid = false;
1104      }
1105
1106   }
1107   else {
1108
1109      // Play impact sounds on the client.
1110      if (collided) {
1111         F32 collSpeed = (mRigid.linVelocity - origVelocity).len();
1112         S32 impactSound = -1;
1113         if (collSpeed >= mDataBlock->hardImpactSpeed)
1114            impactSound = RigidShapeData::Body::HardImpactSound;
1115         else
1116            if (collSpeed >= mDataBlock->softImpactSpeed)
1117               impactSound = RigidShapeData::Body::SoftImpactSound;
1118
1119         if (impactSound != -1 && mDataBlock->body.sound[impactSound] != NULL)
1120            SFX->playOnce(mDataBlock->body.sound[impactSound], &getTransform());
1121      }
1122
1123      // Water volume sounds
1124      F32 vSpeed = getVelocity().len();
1125      if (!inLiquid && mWaterCoverage >= 0.8f) {
1126         if (vSpeed >= mDataBlock->hardSplashSoundVel) 
1127            SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
1128         else
1129            if (vSpeed >= mDataBlock->medSplashSoundVel)
1130               SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactMedium], &getTransform());
1131            else
1132               if (vSpeed >= mDataBlock->softSplashSoundVel)
1133                  SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
1134         inLiquid = true;
1135      }   
1136      else
1137         if(inLiquid && mWaterCoverage < 0.8f) {
1138            if (vSpeed >= mDataBlock->exitSplashSoundVel)
1139               SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
1140            inLiquid = false;
1141         }
1142   }
1143}
1144
1145
1146//----------------------------------------------------------------------------
1147
1148void RigidShape::updateForces(F32 /*dt*/)
1149{
1150   if (mDisableMove) return;
1151   Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod);
1152
1153   MatrixF currTransform;
1154   mRigid.getTransform(&currTransform);
1155
1156   Point3F torque(0, 0, 0);
1157   Point3F force(0, 0, 0);
1158
1159   Point3F vel = mRigid.linVelocity;
1160
1161   // Gravity
1162   force += gravForce;
1163
1164   // Apply drag
1165   Point3F vDrag = mRigid.linVelocity;
1166   vDrag.convolve(Point3F(1, 1, mDataBlock->vertFactor));
1167   force -= vDrag * mDataBlock->dragForce;
1168
1169   // Add in physical zone force
1170   force += mAppliedForce;
1171
1172   // Container buoyancy & drag
1173   force  += Point3F(0, 0,-mBuoyancy * sRigidShapeGravity * mRigid.mass * mGravityMod);
1174   force  -= mRigid.linVelocity * mDrag;
1175   torque -= mRigid.angMomentum * mDrag;
1176
1177   mRigid.force  = force;
1178   mRigid.torque = torque;
1179}
1180
1181
1182//-----------------------------------------------------------------------------
1183/** Update collision information
1184Update the convex state and check for collisions. If the object is in
1185collision, impact and contact forces are generated.
1186*/
1187
1188bool RigidShape::updateCollision(F32 dt)
1189{
1190   // Update collision information
1191   MatrixF mat,cmat;
1192   mConvex.transform = &mat;
1193   mRigid.getTransform(&mat);
1194   cmat = mConvex.getTransform();
1195
1196   mCollisionList.clear();
1197   CollisionState *state = mConvex.findClosestState(cmat, getScale(), mDataBlock->collisionTol);
1198   if (state && state->dist <= mDataBlock->collisionTol) 
1199   {
1200      //resolveDisplacement(ns,state,dt);
1201      mConvex.getCollisionInfo(cmat, getScale(), &mCollisionList, mDataBlock->collisionTol);
1202   }
1203
1204   // Resolve collisions
1205   bool collided = resolveCollision(mRigid,mCollisionList);
1206   resolveContacts(mRigid,mCollisionList,dt);
1207   return collided;
1208}
1209
1210
1211//----------------------------------------------------------------------------
1212/** Resolve collision impacts
1213Handle collision impacts, as opposed to contacts. Impulses are calculated based
1214on standard collision resolution formulas.
1215*/
1216bool RigidShape::resolveCollision(Rigid&  ns,CollisionList& cList)
1217{
1218   // Apply impulses to resolve collision
1219   bool colliding, collided = false;
1220
1221   do 
1222   {
1223      colliding = false;
1224      for (S32 i = 0; i < cList.getCount(); i++) 
1225      {
1226         Collision& c = cList[i];
1227         if (c.distance < mDataBlock->collisionTol) 
1228         {
1229            // Velocity into surface
1230            Point3F v,r;
1231            ns.getOriginVector(c.point,&r);
1232            ns.getVelocity(r,&v);
1233            F32 vn = mDot(v,c.normal);
1234
1235            // Only interested in velocities greater than sContactTol,
1236            // velocities less than that will be dealt with as contacts
1237            // "constraints".
1238            if (vn < -mDataBlock->contactTol) 
1239            {
1240
1241               // Apply impulses to the rigid body to keep it from
1242               // penetrating the surface.
1243               ns.resolveCollision(cList[i].point,
1244                  cList[i].normal);
1245               colliding = collided  = true;
1246
1247               // Keep track of objects we collide with
1248               if (!isGhost() && c.object->getTypeMask() & ShapeBaseObjectType) 
1249               {
1250                  ShapeBase* col = static_cast<ShapeBase*>(c.object);
1251                  queueCollision(col,v - col->getVelocity());
1252               }
1253            }
1254         }
1255      }
1256   } while (colliding);
1257
1258   return collided;
1259}
1260
1261//----------------------------------------------------------------------------
1262/** Resolve contact forces
1263Resolve contact forces using the "penalty" method. Forces are generated based
1264on the depth of penetration and the moment of inertia at the point of contact.
1265*/
1266bool RigidShape::resolveContacts(Rigid& ns,CollisionList& cList,F32 dt)
1267{
1268   // Use spring forces to manage contact constraints.
1269   bool collided = false;
1270   Point3F t,p(0,0,0),l(0,0,0);
1271   for (S32 i = 0; i < cList.getCount(); i++) 
1272   {
1273      Collision& c = cList[i];
1274      if (c.distance < mDataBlock->collisionTol) 
1275      {
1276
1277         // Velocity into the surface
1278         Point3F v,r;
1279         ns.getOriginVector(c.point,&r);
1280         ns.getVelocity(r,&v);
1281         F32 vn = mDot(v,c.normal);
1282
1283         // Only interested in velocities less than mDataBlock->contactTol,
1284         // velocities greater than that are dealt with as collisions.
1285         if (mFabs(vn) < mDataBlock->contactTol) 
1286         {
1287            collided = true;
1288
1289            // Penetration force. This is actually a spring which
1290            // will seperate the body from the collision surface.
1291            F32 zi = 2 * mFabs(mRigid.getZeroImpulse(r,c.normal));
1292            F32 s = (mDataBlock->collisionTol - c.distance) * zi - ((vn / mDataBlock->contactTol) * zi);
1293            Point3F f = c.normal * s;
1294
1295            // Friction impulse, calculated as a function of the
1296            // amount of force it would take to stop the motion
1297            // perpendicular to the normal.
1298            Point3F uv = v - (c.normal * vn);
1299            F32 ul = uv.len();
1300            if (s > 0 && ul) 
1301            {
1302               uv /= -ul;
1303               F32 u = ul * ns.getZeroImpulse(r,uv);
1304               s *= mRigid.friction;
1305               if (u > s)
1306                  u = s;
1307               f += uv * u;
1308            }
1309
1310            // Accumulate forces
1311            p += f;
1312            mCross(r,f,&t);
1313            l += t;
1314         }
1315      }
1316   }
1317
1318   // Contact constraint forces act over time...
1319   ns.linMomentum += p * dt;
1320   ns.angMomentum += l * dt;
1321   ns.updateVelocity();
1322   return true;
1323}
1324
1325
1326//----------------------------------------------------------------------------
1327
1328bool RigidShape::resolveDisplacement(Rigid& ns,CollisionState *state, F32 dt)
1329{
1330   SceneObject* obj = (state->a->getObject() == this)?
1331      state->b->getObject(): state->a->getObject();
1332
1333   if (obj->isDisplacable() && ((obj->getTypeMask() & ShapeBaseObjectType) != 0))
1334   {
1335      // Try to displace the object by the amount we're trying to move
1336      Point3F objNewMom = ns.linVelocity * obj->getMass() * 1.1f;
1337      Point3F objOldMom = obj->getMomentum();
1338      Point3F objNewVel = objNewMom / obj->getMass();
1339
1340      Point3F myCenter;
1341      Point3F theirCenter;
1342      getWorldBox().getCenter(&myCenter);
1343      obj->getWorldBox().getCenter(&theirCenter);
1344      if (mDot(myCenter - theirCenter, objNewMom) >= 0.0f || objNewVel.len() < 0.01)
1345      {
1346         objNewMom = (theirCenter - myCenter);
1347         objNewMom.normalize();
1348         objNewMom *= 1.0f * obj->getMass();
1349         objNewVel = objNewMom / obj->getMass();
1350      }
1351
1352      obj->setMomentum(objNewMom);
1353      if (obj->displaceObject(objNewVel * 1.1f * dt) == true)
1354      {
1355         // Queue collision and change in velocity
1356         VectorF dv = (objOldMom - objNewMom) / obj->getMass();
1357         queueCollision(static_cast<ShapeBase*>(obj), dv);
1358         return true;
1359      }
1360   }
1361
1362   return false;
1363}   
1364
1365
1366//----------------------------------------------------------------------------
1367
1368void RigidShape::updateWorkingCollisionSet(const U32 mask)
1369{
1370   Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
1371   F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
1372   F32 l = (len * 1.1) + 0.1;  // fudge factor
1373   convexBox.minExtents -= Point3F(l, l, l);
1374   convexBox.maxExtents += Point3F(l, l, l);
1375
1376   disableCollision();
1377   mConvex.updateWorkingList(convexBox, mask);
1378   enableCollision();
1379}
1380
1381
1382//----------------------------------------------------------------------------
1383/** Check collisions with trigger and items
1384Perform a container search using the current bounding box
1385of the main body, wheels are not included.  This method should
1386only be called on the server.
1387*/
1388void RigidShape::checkTriggers()
1389{
1390   Box3F bbox = mConvex.getBoundingBox(getTransform(), getScale());
1391   gServerContainer.findObjects(bbox,sTriggerMask,findCallback,this);
1392}
1393
1394/** The callback used in by the checkTriggers() method.
1395The checkTriggers method uses a container search which will
1396invoke this callback on each obj that matches.
1397*/
1398void RigidShape::findCallback(SceneObject* obj,void *key)
1399{
1400   RigidShape* shape = reinterpret_cast<RigidShape*>(key);
1401   U32 objectMask = obj->getTypeMask();
1402
1403   // Check: triggers, corpses and items, basically the same things
1404   // that the player class checks for
1405   if (objectMask & TriggerObjectType) {
1406      Trigger* pTrigger = static_cast<Trigger*>(obj);
1407      pTrigger->potentialEnterObject(shape);
1408   }
1409   else if (objectMask & CorpseObjectType) {
1410      ShapeBase* col = static_cast<ShapeBase*>(obj);
1411      shape->queueCollision(col,shape->getVelocity() - col->getVelocity());
1412   }
1413   else if (objectMask & ItemObjectType) {
1414      Item* item = static_cast<Item*>(obj);
1415      if (shape != item->getCollisionObject())
1416         shape->queueCollision(item,shape->getVelocity() - item->getVelocity());
1417   }
1418}
1419
1420
1421//----------------------------------------------------------------------------
1422
1423void RigidShape::writePacketData(GameConnection *connection, BitStream *stream)
1424{
1425   Parent::writePacketData(connection, stream);
1426
1427   mathWrite(*stream, mRigid.linPosition);
1428   mathWrite(*stream, mRigid.angPosition);
1429   mathWrite(*stream, mRigid.linMomentum);
1430   mathWrite(*stream, mRigid.angMomentum);
1431   stream->writeFlag(mRigid.atRest);
1432   stream->writeFlag(mContacts.getCount() == 0);
1433
1434   stream->writeFlag(mDisableMove);
1435   stream->setCompressionPoint(mRigid.linPosition);
1436}
1437
1438void RigidShape::readPacketData(GameConnection *connection, BitStream *stream)
1439{
1440   Parent::readPacketData(connection, stream);
1441
1442   mathRead(*stream, &mRigid.linPosition);
1443   mathRead(*stream, &mRigid.angPosition);
1444   mathRead(*stream, &mRigid.linMomentum);
1445   mathRead(*stream, &mRigid.angMomentum);
1446   mRigid.atRest = stream->readFlag();
1447   if (stream->readFlag())
1448      mContacts.clear();
1449   mRigid.updateInertialTensor();
1450   mRigid.updateVelocity();
1451
1452   mDisableMove = stream->readFlag();
1453   stream->setCompressionPoint(mRigid.linPosition);
1454}   
1455
1456
1457//----------------------------------------------------------------------------
1458
1459U32 RigidShape::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
1460{
1461   U32 retMask = Parent::packUpdate(con, mask, stream);
1462
1463   // The rest of the data is part of the control object packet update.
1464   // If we're controlled by this client, we don't need to send it.
1465   if (stream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
1466      return retMask;
1467
1468   mDelta.move.pack(stream);
1469
1470   if (stream->writeFlag(mask & PositionMask))
1471   {
1472      stream->writeFlag(mask & ForceMoveMask);
1473
1474      stream->writeCompressedPoint(mRigid.linPosition);
1475      mathWrite(*stream, mRigid.angPosition);
1476      mathWrite(*stream, mRigid.linMomentum);
1477      mathWrite(*stream, mRigid.angMomentum);
1478      stream->writeFlag(mRigid.atRest);
1479   }
1480   
1481   if(stream->writeFlag(mask & FreezeMask))
1482      stream->writeFlag(mDisableMove);
1483
1484   return retMask;
1485}   
1486
1487void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream)
1488{
1489   Parent::unpackUpdate(con,stream);
1490
1491   if (stream->readFlag())
1492      return;
1493
1494   mDelta.move.unpack(stream);
1495
1496   if (stream->readFlag()) 
1497   {
1498      // Check if we need to jump to the given transform
1499      // rather than interpolate to it.
1500      bool forceUpdate = stream->readFlag();
1501
1502      mPredictionCount = sMaxPredictionTicks;
1503      F32 speed = mRigid.linVelocity.len();
1504      mDelta.warpRot[0] = mRigid.angPosition;
1505
1506      // Read in new position and momentum values
1507      stream->readCompressedPoint(&mRigid.linPosition);
1508      mathRead(*stream, &mRigid.angPosition);
1509      mathRead(*stream, &mRigid.linMomentum);
1510      mathRead(*stream, &mRigid.angMomentum);
1511      mRigid.atRest = stream->readFlag();
1512      mRigid.updateVelocity();
1513
1514      if (!forceUpdate && isProperlyAdded()) 
1515      {
1516         // Determine number of ticks to warp based on the average
1517         // of the client and server velocities.
1518         Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
1519         mDelta.warpOffset = mRigid.linPosition - cp;
1520
1521         // Calc the distance covered in one tick as the average of
1522         // the old speed and the new speed from the server.
1523         F32 dt,as = (speed + mRigid.linVelocity.len()) * 0.5 * TickSec;
1524
1525         // Cal how many ticks it will take to cover the warp offset.
1526         // If it's less than what's left in the current tick, we'll just
1527         // warp in the remaining time.
1528         if (!as || (dt = mDelta.warpOffset.len() / as) > sMaxWarpTicks)
1529            dt = mDelta.dt + sMaxWarpTicks;
1530         else
1531            dt = (dt <= mDelta.dt)? mDelta.dt : mCeil(dt - mDelta.dt) + mDelta.dt;
1532
1533         // Adjust current frame interpolation
1534         if (mDelta.dt) 
1535         {
1536            mDelta.pos = cp + (mDelta.warpOffset * (mDelta.dt / dt));
1537            mDelta.posVec = (cp - mDelta.pos) / mDelta.dt;
1538            QuatF cr;
1539            cr.interpolate(mDelta.rot[1],mDelta.rot[0],mDelta.dt);
1540            mDelta.rot[1].interpolate(cr,mRigid.angPosition,mDelta.dt / dt);
1541            mDelta.rot[0].extrapolate(mDelta.rot[1],cr,mDelta.dt);
1542         }
1543
1544         // Calculated multi-tick warp
1545         mDelta.warpCount = 0;
1546         mDelta.warpTicks = (S32)(mFloor(dt));
1547         if (mDelta.warpTicks) 
1548         {
1549            mDelta.warpOffset = mRigid.linPosition - mDelta.pos;
1550            mDelta.warpOffset /= mDelta.warpTicks;
1551            mDelta.warpRot[0] = mDelta.rot[1];
1552            mDelta.warpRot[1] = mRigid.angPosition;
1553         }
1554      }
1555      else 
1556      {
1557         // Set the shape to the server position
1558         mDelta.dt  = 0;
1559         mDelta.pos = mRigid.linPosition;
1560         mDelta.posVec.set(0,0,0);
1561         mDelta.rot[1] = mDelta.rot[0] = mRigid.angPosition;
1562         mDelta.warpCount = mDelta.warpTicks = 0;
1563         setPosition(mRigid.linPosition, mRigid.angPosition);
1564      }
1565   }
1566   
1567   if(stream->readFlag())
1568      mDisableMove = stream->readFlag();
1569}
1570
1571
1572//----------------------------------------------------------------------------
1573
1574void RigidShape::initPersistFields()
1575{
1576   Parent::initPersistFields();
1577}
1578
1579//----------------------------------------------------------------------------
1580
1581void RigidShape::updateLiftoffDust( F32 dt )
1582{
1583   Point3F offset( 0.0, 0.0, mDataBlock->dustHeight );
1584   emitDust( mDustEmitterList[ 0 ], mDataBlock->triggerDustHeight, offset,
1585             ( U32 )( dt * 1000 ) );
1586}
1587
1588//--------------------------------------------------------------------------
1589void RigidShape::updateFroth( F32 dt )
1590{
1591   // update bubbles
1592   Point3F moveDir = getVelocity();
1593
1594   Point3F contactPoint;
1595
1596   F32 speed = moveDir.len();
1597   if( speed < mDataBlock->splashVelEpsilon ) speed = 0.0;
1598
1599   U32 emitRate = (U32)(speed * mDataBlock->splashFreqMod * dt);
1600
1601   U32 i;
1602   for( i=0; i<RigidShapeData::VC_NUM_SPLASH_EMITTERS; i++ )
1603   {
1604      if( mSplashEmitterList[i] )
1605      {
1606         mSplashEmitterList[i]->emitParticles( contactPoint, contactPoint, Point3F( 0.0, 0.0, 1.0 ), 
1607            moveDir, emitRate );
1608      }
1609   }
1610
1611}
1612
1613//--------------------------------------------------------------------------
1614// Returns true if shape is intersecting a water surface (roughly)
1615//--------------------------------------------------------------------------
1616bool RigidShape::collidingWithWater( Point3F &waterHeight )
1617{
1618   Point3F curPos = getPosition();
1619
1620   F32 height = mFabs( mObjBox.maxExtents.z - mObjBox.minExtents.z );
1621
1622   RayInfo rInfo;
1623   if( gClientContainer.castRay( curPos + Point3F(0.0, 0.0, height), curPos, WaterObjectType, &rInfo) )
1624   {
1625      waterHeight = rInfo.point;
1626      return true;
1627   }
1628
1629   return false;
1630}
1631
1632void RigidShape::setEnergyLevel(F32 energy)
1633{
1634   Parent::setEnergyLevel(energy);
1635   setMaskBits(EnergyMask);
1636}
1637
1638void RigidShape::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
1639{
1640   Parent::prepBatchRender( state, mountedImageIndex );
1641
1642   if ( !gShowBoundingBox )
1643      return;
1644
1645   ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
1646   ri->renderDelegate.bind( this, &RigidShape::_renderMassAndContacts );
1647   ri->type = RenderPassManager::RIT_Editor;
1648   state->getRenderPass()->addInst( ri );
1649}
1650
1651void RigidShape::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
1652{
1653   // Box for the center of Mass
1654   GFXStateBlockDesc desc;
1655   desc.setBlend(false, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
1656   desc.setZReadWrite(false);
1657   desc.fillMode = GFXFillWireframe;
1658
1659   GFX->getDrawUtil()->drawCube( desc, Point3F(0.1f,0.1f,0.1f), mDataBlock->massCenter, ColorI(255, 255, 255), &mRenderObjToWorld );
1660
1661   // Collision points...
1662   for (S32 i = 0; i < mCollisionList.getCount(); i++)
1663   {
1664      const Collision& collision = mCollisionList[i];
1665      GFX->getDrawUtil()->drawCube( desc, Point3F(0.05f,0.05f,0.05f), collision.point, ColorI(0, 0, 255) );
1666   }
1667
1668   // Render the normals as one big batch... 
1669   PrimBuild::begin(GFXLineList, mCollisionList.getCount() * 2);
1670   for (S32 i = 0; i < mCollisionList.getCount(); i++)
1671   {
1672
1673      const Collision& collision = mCollisionList[i];
1674      PrimBuild::color3f(1, 1, 1);
1675      PrimBuild::vertex3fv(collision.point);
1676      PrimBuild::vertex3fv(collision.point + collision.normal * 0.05f);
1677   }
1678   PrimBuild::end();
1679
1680   // Build and render the collision polylist which is returned
1681   // in the server's world space.
1682   ClippedPolyList polyList;
1683   polyList.mPlaneList.setSize(6);
1684   polyList.mPlaneList[0].set(getWorldBox().minExtents,VectorF(-1,0,0));
1685   polyList.mPlaneList[1].set(getWorldBox().minExtents,VectorF(0,-1,0));
1686   polyList.mPlaneList[2].set(getWorldBox().minExtents,VectorF(0,0,-1));
1687   polyList.mPlaneList[3].set(getWorldBox().maxExtents,VectorF(1,0,0));
1688   polyList.mPlaneList[4].set(getWorldBox().maxExtents,VectorF(0,1,0));
1689   polyList.mPlaneList[5].set(getWorldBox().maxExtents,VectorF(0,0,1));
1690   Box3F dummyBox;
1691   SphereF dummySphere;
1692   buildPolyList(PLC_Collision, &polyList, dummyBox, dummySphere);
1693   //polyList.render();
1694}
1695
1696void RigidShape::reset()
1697{
1698   mRigid.clearForces();
1699   mRigid.setAtRest();
1700}
1701
1702void RigidShape::freezeSim(bool frozen)
1703{
1704   mDisableMove = frozen;
1705   setMaskBits(FreezeMask);
1706}
1707
1708DefineEngineMethod( RigidShape, reset, void, (),,
1709   "@brief Clears physic forces from the shape and sets it at rest.\n\n"
1710   "@tsexample\n"
1711   "// Inform the RigidShape object to reset.\n"
1712   "%thisRigidShape.reset();\n"
1713   "@endtsexample\n\n"
1714   "@see ShapeBaseData")
1715{
1716   object->reset();
1717}
1718
1719DefineEngineMethod( RigidShape, freezeSim, void, (bool isFrozen),,
1720   "@brief Enables or disables the physics simulation on the RigidShape object.\n\n"
1721   "@param isFrozen Boolean frozen state to set the object.\n"
1722   "@tsexample\n"
1723   "// Define the frozen state.\n"
1724   "%isFrozen = \"true\";\n\n"
1725   "// Inform the object of the defined frozen state\n"
1726   "%thisRigidShape.freezeSim(%isFrozen);\n"
1727   "@endtsexample\n\n"
1728   "@see ShapeBaseData")
1729{
1730   object->freezeSim(isFrozen);
1731}
1732
1733DefineEngineMethod( RigidShape, forceClientTransform, void, (),,
1734   "@brief Forces the client to jump to the RigidShape's transform rather then warp to it.\n\n")
1735{
1736   if(object->isServerObject())
1737   {
1738      object->forceClientTransform();
1739   }
1740}
1741