physicsBehavior.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "T3D/components/physics/physicsBehavior.h"
  23. #include "platform/platform.h"
  24. #include "console/consoleTypes.h"
  25. #include "core/util/safeDelete.h"
  26. #include "core/resourceManager.h"
  27. #include "core/stream/fileStream.h"
  28. #include "console/consoleTypes.h"
  29. #include "console/consoleObject.h"
  30. #include "ts/tsShapeInstance.h"
  31. #include "core/stream/bitStream.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "console/engineAPI.h"
  34. #include "lighting/lightQuery.h"
  35. #include "T3D/gameBase/gameConnection.h"
  36. #include "T3D/containerQuery.h"
  37. #include "math/mathIO.h"
  38. //////////////////////////////////////////////////////////////////////////
  39. // Constructor/Destructor
  40. //////////////////////////////////////////////////////////////////////////
  41. PhysicsComponent::PhysicsComponent() : Component()
  42. {
  43. addComponentField("isStatic", "If enabled, object will not simulate physics", "bool", "0", "");
  44. addComponentField("gravity", "The direction of gravity affecting this object, as a vector", "vector", "0 0 -9", "");
  45. addComponentField("drag", "The drag coefficient that constantly affects the object", "float", "0.7", "");
  46. addComponentField("mass", "The mass of the object", "float", "1", "");
  47. mStatic = false;
  48. mAtRest = false;
  49. mAtRestCounter = 0;
  50. mGravity = VectorF(0, 0, 0);
  51. mVelocity = VectorF(0, 0, 0);
  52. mDrag = 0.7f;
  53. mMass = 1.f;
  54. mGravityMod = 1.f;
  55. csmAtRestTimer = 64;
  56. sAtRestVelocity = 0.15f;
  57. mDelta.pos = Point3F(0, 0, 0);
  58. mDelta.posVec = Point3F(0, 0, 0);
  59. mDelta.warpTicks = mDelta.warpCount = 0;
  60. mDelta.dt = 1;
  61. mDelta.move = NullMove;
  62. mPredictionCount = 0;
  63. }
  64. PhysicsComponent::~PhysicsComponent()
  65. {
  66. for(S32 i = 0;i < mFields.size();++i)
  67. {
  68. ComponentField &field = mFields[i];
  69. SAFE_DELETE_ARRAY(field.mFieldDescription);
  70. }
  71. SAFE_DELETE_ARRAY(mDescription);
  72. }
  73. IMPLEMENT_CO_NETOBJECT_V1(PhysicsComponent);
  74. void PhysicsComponent::onComponentAdd()
  75. {
  76. Parent::onComponentAdd();
  77. // Initialize interpolation vars.
  78. mDelta.rot[1] = mDelta.rot[0] = QuatF(mOwner->getTransform());
  79. mDelta.pos = mOwner->getPosition();
  80. mDelta.posVec = Point3F(0,0,0);
  81. }
  82. void PhysicsComponent::initPersistFields()
  83. {
  84. Parent::initPersistFields();
  85. addField("gravity", TypePoint3F, Offset(mGravity, PhysicsComponent));
  86. addField("velocity", TypePoint3F, Offset(mVelocity, PhysicsComponent));
  87. addField("isStatic", TypeBool, Offset(mStatic, PhysicsComponent));
  88. }
  89. U32 PhysicsComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  90. {
  91. U32 retMask = Parent::packUpdate(con, mask, stream);
  92. if(stream->writeFlag(mask & VelocityMask))
  93. mathWrite( *stream, mVelocity );
  94. if(stream->writeFlag(mask & UpdateMask))
  95. {
  96. stream->writeFlag(mStatic);
  97. stream->writeFlag(mAtRest);
  98. stream->writeInt(mAtRestCounter,8);
  99. mathWrite( *stream, mGravity );
  100. stream->writeFloat(mDrag, 12);
  101. //stream->writeFloat(mMass, 12);
  102. stream->writeFloat(mGravityMod, 12);
  103. }
  104. return retMask;
  105. }
  106. void PhysicsComponent::unpackUpdate(NetConnection *con, BitStream *stream)
  107. {
  108. Parent::unpackUpdate(con, stream);
  109. if(stream->readFlag())
  110. mathRead( *stream, &mVelocity );
  111. if(stream->readFlag())
  112. {
  113. mStatic = stream->readFlag();
  114. mAtRest = stream->readFlag();
  115. mAtRestCounter = stream->readInt(8);
  116. mathRead( *stream, &mGravity );
  117. mDrag = stream->readFloat(12);
  118. //mMass = stream->readFloat(12);
  119. mGravityMod = stream->readFloat(12);
  120. }
  121. }
  122. //
  123. void PhysicsComponent::interpolateTick(F32 dt)
  124. {
  125. Point3F pos = mDelta.pos + mDelta.posVec * dt;
  126. //Point3F rot = mDelta.rot + mDelta.rotVec * dt;
  127. setRenderPosition(pos,dt);
  128. }
  129. //
  130. void PhysicsComponent::updateContainer()
  131. {
  132. PROFILE_SCOPE( PhysicsBehaviorInstance_updateContainer );
  133. // Update container drag and buoyancy properties
  134. // Set default values.
  135. //mDrag = mDataBlock->drag;
  136. //mBuoyancy = 0.0f;
  137. //mGravityMod = 1.0;
  138. //mAppliedForce.set(0,0,0);
  139. ContainerQueryInfo info;
  140. info.box = mOwner->getWorldBox();
  141. info.mass = mMass;
  142. mOwner->getContainer()->findObjects(info.box, WaterObjectType|PhysicalZoneObjectType,findRouter,&info);
  143. //mWaterCoverage = info.waterCoverage;
  144. //mLiquidType = info.liquidType;
  145. //mLiquidHeight = info.waterHeight;
  146. //setCurrentWaterObject( info.waterObject );
  147. // This value might be useful as a datablock value,
  148. // This is what allows the player to stand in shallow water (below this coverage)
  149. // without jiggling from buoyancy
  150. if (info.waterCoverage >= 0.25f)
  151. {
  152. // water viscosity is used as drag for in water.
  153. // ShapeBaseData drag is used for drag outside of water.
  154. // Combine these two components to calculate this ShapeBase object's
  155. // current drag.
  156. mDrag = ( info.waterCoverage * info.waterViscosity ) +
  157. ( 1.0f - info.waterCoverage ) * mDrag;
  158. //mBuoyancy = (info.waterDensity / mDataBlock->density) * info.waterCoverage;
  159. }
  160. //mAppliedForce = info.appliedForce;
  161. mGravityMod = info.gravityScale;
  162. }
  163. //
  164. void PhysicsComponent::_updatePhysics()
  165. {
  166. /*SAFE_DELETE( mOwner->mPhysicsRep );
  167. if ( !PHYSICSMGR )
  168. return;
  169. if (mDataBlock->simpleServerCollision)
  170. {
  171. // We only need the trigger on the server.
  172. if ( isServerObject() )
  173. {
  174. PhysicsCollision *colShape = PHYSICSMGR->createCollision();
  175. colShape->addBox( mObjBox.getExtents() * 0.5f, MatrixF::Identity );
  176. PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" );
  177. mPhysicsRep = PHYSICSMGR->createBody();
  178. mPhysicsRep->init( colShape, 0, PhysicsBody::BF_TRIGGER | PhysicsBody::BF_KINEMATIC, this, world );
  179. mPhysicsRep->setTransform( getTransform() );
  180. }
  181. }
  182. else
  183. {
  184. if ( !mShapeInstance )
  185. return;
  186. PhysicsCollision* colShape = mShapeInstance->getShape()->buildColShape( false, getScale() );
  187. if ( colShape )
  188. {
  189. PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" );
  190. mPhysicsRep = PHYSICSMGR->createBody();
  191. mPhysicsRep->init( colShape, 0, PhysicsBody::BF_KINEMATIC, this, world );
  192. mPhysicsRep->setTransform( getTransform() );
  193. }
  194. }*/
  195. return;
  196. }
  197. PhysicsBody *PhysicsComponent::getPhysicsRep()
  198. {
  199. /*if(mOwner)
  200. {
  201. Entity* ac = dynamic_cast<Entity*>(mOwner);
  202. if(ac)
  203. return ac->mPhysicsRep;
  204. }*/
  205. return NULL;
  206. }
  207. //
  208. void PhysicsComponent::setTransform(const MatrixF& mat)
  209. {
  210. mOwner->setTransform(mat);
  211. if (!mStatic)
  212. {
  213. mAtRest = false;
  214. mAtRestCounter = 0;
  215. }
  216. if ( getPhysicsRep() )
  217. getPhysicsRep()->setTransform( mOwner->getTransform() );
  218. setMaskBits(UpdateMask);
  219. }
  220. void PhysicsComponent::setPosition(const Point3F& pos)
  221. {
  222. MatrixF mat = mOwner->getTransform();
  223. if (mOwner->isMounted()) {
  224. // Use transform from mounted object
  225. //mOwner->getObjectMount()->getMountTransform( mOwner->getMountNode(), mMount.xfm, &mat );
  226. return;
  227. }
  228. else {
  229. mat.setColumn(3,pos);
  230. }
  231. mOwner->setTransform(mat);
  232. if ( getPhysicsRep() )
  233. getPhysicsRep()->setTransform( mat );
  234. }
  235. void PhysicsComponent::setRenderPosition(const Point3F& pos, F32 dt)
  236. {
  237. MatrixF mat = mOwner->getRenderTransform();
  238. if (mOwner->isMounted()) {
  239. // Use transform from mounted object
  240. //mOwner->getObjectMount()->getMountRenderTransform( dt, mOwner->getMountNode(), mMount.xfm, &mat );
  241. return;
  242. }
  243. else {
  244. mat.setColumn(3,pos);
  245. }
  246. mOwner->setRenderTransform(mat);
  247. }
  248. void PhysicsComponent::updateVelocity(const F32 dt)
  249. {
  250. }
  251. void PhysicsComponent::setVelocity(const VectorF& vel)
  252. {
  253. mVelocity = vel;
  254. mAtRest = false;
  255. mAtRestCounter = 0;
  256. setMaskBits(VelocityMask);
  257. }
  258. void PhysicsComponent::getVelocity(const Point3F& r, Point3F* v)
  259. {
  260. *v = mVelocity;
  261. }
  262. void PhysicsComponent::getOriginVector(const Point3F &p,Point3F* r)
  263. {
  264. *r = p - mOwner->getObjBox().getCenter();
  265. }
  266. F32 PhysicsComponent::getZeroImpulse(const Point3F& r,const Point3F& normal)
  267. {
  268. Point3F a,b,c;
  269. //set up our inverse matrix
  270. MatrixF iv,qmat;
  271. MatrixF inverse = MatrixF::Identity;
  272. qmat = mOwner->getTransform();
  273. iv.mul(qmat,inverse);
  274. qmat.transpose();
  275. inverse.mul(iv,qmat);
  276. mCross(r, normal, &a);
  277. inverse.mulV(a, &b);
  278. mCross(b, r, &c);
  279. return 1 / ((1/mMass) + mDot(c, normal));
  280. }
  281. void PhysicsComponent::accumulateForce(F32 dt, Point3F force)
  282. {
  283. mVelocity += force * dt;
  284. }
  285. void PhysicsComponent::applyImpulse(const Point3F&,const VectorF& vec)
  286. {
  287. // Items ignore angular velocity
  288. VectorF vel;
  289. vel.x = vec.x / mMass;
  290. vel.y = vec.y / mMass;
  291. vel.z = vec.z / mMass;
  292. setVelocity(mVelocity + vel);
  293. }
  294. DefineEngineMethod( PhysicsComponent, applyImpulse, bool, ( Point3F pos, VectorF vel ),,
  295. "@brief Apply an impulse to this object as defined by a world position and velocity vector.\n\n"
  296. "@param pos impulse world position\n"
  297. "@param vel impulse velocity (impulse force F = m * v)\n"
  298. "@return Always true\n"
  299. "@note Not all objects that derrive from GameBase have this defined.\n")
  300. {
  301. object->applyImpulse(pos,vel);
  302. return true;
  303. }