123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- //-----------------------------------------------------------------------------
- // Torque Game Engine
- // Copyright (C) GarageGames.com, Inc.
- //-----------------------------------------------------------------------------
- #include "T3D/components/physics/simplePhysicsComponent.h"
- #include "T3D/components/collision/collisionComponent.h"
- #include "platform/platform.h"
- #include "console/consoleTypes.h"
- #include "core/util/safeDelete.h"
- #include "core/resourceManager.h"
- #include "core/stream/fileStream.h"
- #include "console/consoleTypes.h"
- #include "console/consoleObject.h"
- #include "ts/tsShapeInstance.h"
- #include "core/stream/bitStream.h"
- #include "gfx/gfxTransformSaver.h"
- #include "console/engineAPI.h"
- #include "lighting/lightQuery.h"
- #include "T3D/gameBase/gameConnection.h"
- #include "collision/collision.h"
- //////////////////////////////////////////////////////////////////////////
- // Callbacks
- IMPLEMENT_CALLBACK( SimplePhysicsComponent, updateMove, void, ( SimplePhysicsComponent* obj ), ( obj ),
- "Called when the player updates it's movement, only called if object is set to callback in script(doUpdateMove).\n"
- "@param obj the Player object\n" );
- //////////////////////////////////////////////////////////////////////////
- // Constructor/Destructor
- //////////////////////////////////////////////////////////////////////////
- SimplePhysicsComponent::SimplePhysicsComponent() : PhysicsComponent()
- {
- mBuoyancy = 0.f;
- mFriction = 0.3f;
- mElasticity = 0.4f;
- mMaxVelocity = 3000.f;
- mSticky = false;
- mDrag = 0.5;
- mVelocity = Point3F::Zero;
- moveSpeed = Point3F(1, 1, 1);
- mFriendlyName = "Simple Physics";
- mComponentType = "Physics";
- mDescription = getDescriptionText("Simple physics Component that allows gravity and impulses.");
- }
- SimplePhysicsComponent::~SimplePhysicsComponent()
- {
- for(S32 i = 0;i < mFields.size();++i)
- {
- ComponentField &field = mFields[i];
- SAFE_DELETE_ARRAY(field.mFieldDescription);
- }
- SAFE_DELETE_ARRAY(mDescription);
- }
- IMPLEMENT_CONOBJECT(SimplePhysicsComponent);
- //////////////////////////////////////////////////////////////////////////
- bool SimplePhysicsComponent::onAdd()
- {
- if(! Parent::onAdd())
- return false;
- return true;
- }
- void SimplePhysicsComponent::onRemove()
- {
- Parent::onRemove();
- }
- void SimplePhysicsComponent::initPersistFields()
- {
- Parent::initPersistFields();
- addField( "moveSpeed", TypePoint3F, Offset(moveSpeed, SimplePhysicsComponent), "");
- }
- U32 SimplePhysicsComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
- {
- U32 retMask = Parent::packUpdate(con, mask, stream);
- return retMask;
- }
- void SimplePhysicsComponent::unpackUpdate(NetConnection *con, BitStream *stream)
- {
- Parent::unpackUpdate(con, stream);
- }
- //
- void SimplePhysicsComponent::processTick()
- {
- Parent::processTick();
- if (!isServerObject() || !isActive())
- return;
- //
- //if (mCollisionObject && !--mCollisionTimeout)
- // mCollisionObject = 0;
- // Warp to catch up to server
- if (mDelta.warpCount < mDelta.warpTicks)
- {
- mDelta.warpCount++;
- // Set new pos.
- mOwner->getTransform().getColumn(3,&mDelta.pos);
- mDelta.pos += mDelta.warpOffset;
- //mDelta.rot[0] = mDelta.rot[1];
- //mDelta.rot[1].interpolate(mDelta.warpRot[0],mDelta.warpRot[1],F32(mDelta.warpCount)/mDelta.warpTicks);
- MatrixF trans;
- mDelta.rot[1].setMatrix(&trans);
- trans.setPosition(mDelta.pos);
- setTransform(trans);
- // Pos backstepping
- mDelta.posVec.x = -mDelta.warpOffset.x;
- mDelta.posVec.y = -mDelta.warpOffset.y;
- mDelta.posVec.z = -mDelta.warpOffset.z;
- }
- else
- {
- // Save current rigid state interpolation
- mDelta.posVec = mOwner->getPosition();
- //mDelta.rot[0] = mOwner->getTransform();
- updateForces();
- updatePos(TickSec);
- // Wrap up interpolation info
- mDelta.pos = mOwner->getPosition();
- mDelta.posVec -= mOwner->getPosition();
- //mDelta.rot[1] = mRigid.angPosition;
- // Update container database
- setTransform(mOwner->getTransform());
- setMaskBits(UpdateMask);
- updateContainer();
- }
- }
- void SimplePhysicsComponent::interpolateTick(F32 dt)
- {
- // Client side interpolation
- Point3F pos = mDelta.pos + mDelta.posVec * dt;
- MatrixF mat = mOwner->getRenderTransform();
- mat.setColumn(3,pos);
- mOwner->setRenderTransform(mat);
- mDelta.dt = dt;
- }
- void SimplePhysicsComponent::updatePos(const F32 travelTime)
- {
- mOwner->getTransform().getColumn(3,&mDelta.posVec);
- // When mounted to another object, only Z rotation used.
- if (mOwner->isMounted()) {
- mVelocity = mOwner->getObjectMount()->getVelocity();
- setPosition(Point3F(0.0f, 0.0f, 0.0f));
- setMaskBits(UpdateMask);
- return;
- }
- Point3F newPos;
- if ( mVelocity.isZero() )
- newPos = mDelta.posVec;
- else
- newPos = _move( travelTime );
- //}
- // Set new position
- // If on the client, calc delta for backstepping
- if (isClientObject())
- {
- mDelta.pos = newPos;
- mDelta.posVec = mDelta.posVec - mDelta.pos;
- mDelta.dt = 1.0f;
- }
- setPosition( newPos );
- setMaskBits( UpdateMask );
- updateContainer();
- /*if (!isGhost())
- {
- // Do mission area callbacks on the server as well
- checkMissionArea();
- }*/
- return;
- }
- Point3F SimplePhysicsComponent::_move( const F32 travelTime )
- {
- // Try and move to new pos
- F32 totalMotion = 0.0f;
- Point3F start;
- Point3F initialPosition;
- mOwner->getTransform().getColumn(3,&start);
- initialPosition = start;
- VectorF firstNormal(0.0f, 0.0f, 0.0f);
- //F32 maxStep = mDataBlock->maxStepHeight;
- F32 time = travelTime;
- U32 count = 0;
- S32 sMoveRetryCount = 5;
- CollisionComponent* colComp = mOwner->getComponent<CollisionComponent>();
- if(!colComp)
- return start + mVelocity * time;
- colComp->clearCollisionList();
- for (; count < sMoveRetryCount; count++)
- {
- F32 speed = mVelocity.len();
- if (!speed)
- break;
- Point3F end = start + mVelocity * time;
- Point3F distance = end - start;
- bool collided = colComp->checkCollisions(time, &mVelocity, start);
- if (colComp->getCollisionList()->getCount() != 0 && colComp->getCollisionList()->getTime() < 1.0f)
- {
- // Set to collision point
- F32 velLen = mVelocity.len();
- F32 dt = time * getMin(colComp->getCollisionList()->getTime(), 1.0f);
- start += mVelocity * dt;
- time -= dt;
- totalMotion += velLen * dt;
- // Back off...
- if ( velLen > 0.f )
- {
- F32 newT = getMin(0.01f / velLen, dt);
- start -= mVelocity * newT;
- totalMotion -= velLen * newT;
- }
- // Pick the surface most parallel to the face that was hit.
- U32 colCount = colComp->getCollisionList()->getCount();
- const Collision *collision = colComp->getCollision(0);
- const Collision *cp = collision + 1;
- const Collision *ep = collision + colComp->getCollisionList()->getCount();
- for (; cp != ep; cp++)
- {
- U32 colCountLoop = colComp->getCollisionList()->getCount();
- //TODO: Move this somewhere else
- if(Entity* colEnt = dynamic_cast<Entity*>(collision->object))
- {
- if(CollisionComponent *collidingEntityColComp = colEnt->getComponent<CollisionComponent>())
- {
- if(!collidingEntityColComp->doesBlockColliding())
- {
- continue;
- }
- }
- }
- if (cp->faceDot > collision->faceDot)
- collision = cp;
- }
- //check the last/first one just incase
- if(Entity* colEnt = dynamic_cast<Entity*>(collision->object))
- {
- if(CollisionComponent *collidingEntityColComp = colEnt->getComponent<CollisionComponent>())
- {
- if(!collidingEntityColComp->doesBlockColliding())
- {
- //if our ideal surface doesn't stop us, just move along
- return start + mVelocity * time;
- }
- }
- }
- //F32 bd = _doCollisionImpact( collision, wasFalling );
- F32 bd = -mDot( mVelocity, collision->normal);
- // Subtract out velocity
- F32 sNormalElasticity = 0.01f;
- VectorF dv = collision->normal * (bd + sNormalElasticity);
- mVelocity += dv;
- if (count == 0)
- {
- firstNormal = collision->normal;
- }
- else
- {
- if (count == 1)
- {
- // Re-orient velocity along the crease.
- if (mDot(dv,firstNormal) < 0.0f &&
- mDot(collision->normal,firstNormal) < 0.0f)
- {
- VectorF nv;
- mCross(collision->normal,firstNormal,&nv);
- F32 nvl = nv.len();
- if (nvl)
- {
- if (mDot(nv,mVelocity) < 0.0f)
- nvl = -nvl;
- nv *= mVelocity.len() / nvl;
- mVelocity = nv;
- }
- }
- }
- }
- }
- else
- {
- totalMotion += (end - start).len();
- start = end;
- break;
- }
- }
- U32 colCountThree = colComp->getCollisionList()->getCount();
- if (colCountThree != 0)
- bool derp = true;
- if (count == sMoveRetryCount)
- {
- // Failed to move
- start = initialPosition;
- mVelocity.set(0.0f, 0.0f, 0.0f);
- }
- return start;
- }
- void SimplePhysicsComponent::updateForces()
- {
- // Acceleration due to gravity
- mVelocity += (mGravity * mGravityMod) * TickMs;
- F32 len = mVelocity.len();
- if (mMaxVelocity > 0 && mAbs(len) > mMaxVelocity)
- {
- Point3F excess = mVelocity * (1.0 - (mMaxVelocity / len));
- excess *= 0.1f;
- mVelocity -= excess;
- }
- // Container buoyancy & drag
- if(mOwner->getContainerInfo().waterCoverage > 0.65f)
- mVelocity -= mBuoyancy * (mGravity * mGravityMod) * TickMs;
- mVelocity -= mVelocity * mDrag * TickMs;
- if( mVelocity.isZero() )
- mVelocity = Point3F::Zero;
- else
- setMaskBits(VelocityMask);
- }
- //
- void SimplePhysicsComponent::setVelocity(const VectorF& vel)
- {
- Parent::setVelocity(vel);
- // Clamp against the maximum velocity.
- if ( mMaxVelocity > 0 )
- {
- F32 len = mVelocity.magnitudeSafe();
- if ( len > mMaxVelocity )
- {
- Point3F excess = mVelocity * ( 1.0f - (mMaxVelocity / len ) );
- mVelocity -= excess;
- }
- }
- }
|