From d81a1c204cfcf0897b7659d9cc50a7389bec72d9 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Wed, 26 Feb 2014 14:06:02 +0100 Subject: [PATCH] Added early triangle collisions --- Code/Game/GameLogic/Level.cpp | 37 ++++++++ Code/Game/GameLogic/Level.h | 2 + Code/Game/GameLogic/Player.cpp | 85 +++++++++++-------- .../Implementation/PhysicsAPI_Impl.cpp | 25 ++---- .../Implementation/SimpleRigidBody.cpp | 39 +++++---- .../Implementation/SimpleRigidBody.h | 3 +- Code/Physics/GamePhysics/PhysicsAPI.h | 3 +- 7 files changed, 122 insertions(+), 72 deletions(-) diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 3fa39829..546562f9 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -196,6 +196,38 @@ ICustomBody* Level::InitRigidBodySphere( const ObjectHeader* obj) rigidBody = API::Instance().AddCollisionSphere( rigidBodyRadius , rigidWorldRotation , rigidWorldPos , rigidBodyMass, obj->boundingVolume.sphere.restitutionCoeff , obj->boundingVolume.sphere.frictionCoeffStatic , obj->boundingVolume.sphere.frictionCoeffDynamic); return rigidBody; } +ICustomBody* Level::InitRigidBodyMesh( const ObjectHeader* obj) +{ + ICustomBody* rigidBody = NULL; + Oyster::Math::Float3 rigidWorldPos; + Oyster::Math::Float4 rigidWorldRotation; + float rigidBodyMass; + float rigidBodyRadius; + + //offset the rigidPosition from modelspace to worldspace; + rigidWorldPos = (Oyster::Math::Float3)obj->position + (Oyster::Math::Float3)obj->boundingVolume.cgMesh.position; + //scales the position so the collision geomentry is in the right place + rigidWorldPos = rigidWorldPos * obj->scale; + + //offset the rigidRotation from modelspace to worldspace; + Oyster::Math::Quaternion worldPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->rotation[0],obj->rotation[1],obj->rotation[2]), obj->rotation[3]); + Oyster::Math::Quaternion physicsPosQuaternion = Oyster::Math::Quaternion(Oyster::Math::Float3(obj->boundingVolume.cgMesh.rotation[0],obj->boundingVolume.cgMesh.rotation[1],obj->boundingVolume.cgMesh.rotation[2]), obj->boundingVolume.cgMesh.rotation[3]); + Oyster::Math::Quaternion rigidWorldQuaternion = worldPosQuaternion * physicsPosQuaternion; + + rigidWorldRotation = Oyster::Math::Float4(rigidWorldQuaternion); + + + //mass scaled + rigidBodyMass = obj->scale[0] * obj->scale[1] * obj->scale[2] * obj->boundingVolume.cgMesh.mass; + + //Radius scaled + //rigidBodyRadius = (obj->scale[0]) * obj->boundingVolume.sphere.radius; + //rigidBodyRadius = (obj->scale[0] * obj->scale[1] * obj->scale[2]) * obj->boundingVolume.sphere.radius; + + //create the rigid body + rigidBody = API::Instance().AddTriangleMesh(obj->boundingVolume.cgMesh.filename, rigidWorldRotation , rigidWorldPos , rigidBodyMass, obj->boundingVolume.cgMesh.restitutionCoeff , obj->boundingVolume.cgMesh.frictionCoeffStatic , obj->boundingVolume.cgMesh.frictionCoeffDynamic); + return rigidBody; +} bool Level::InitiateLevel(std::wstring levelPath) { LevelLoader ll; @@ -253,6 +285,11 @@ bool Level::InitiateLevel(std::wstring levelPath) //rigidBody_Static = InitRigidBodyCylinder(staticObjData); } + else if(staticObjData->boundingVolume.geoType == CollisionGeometryType_CG_MESH) + { + rigidBody_Static = InitRigidBodyMesh(staticObjData); + } + if(rigidBody_Static != NULL) { // create game object diff --git a/Code/Game/GameLogic/Level.h b/Code/Game/GameLogic/Level.h index 876fd034..1811c9af 100644 --- a/Code/Game/GameLogic/Level.h +++ b/Code/Game/GameLogic/Level.h @@ -37,6 +37,8 @@ namespace GameLogic bool InitiateLevel(std::wstring levelPath); Oyster::Physics::ICustomBody* InitRigidBodyCube( const ObjectHeader* obj); Oyster::Physics::ICustomBody* InitRigidBodySphere( const ObjectHeader* obj); + Oyster::Physics::ICustomBody* InitRigidBodyMesh( const ObjectHeader* obj); + Object* CreateGameObj(ObjectHeader* obj, Oyster::Physics::ICustomBody* rigidBody); /******************************************************** diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index 1d95a83b..49babcc3 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -8,11 +8,11 @@ using namespace GameLogic; using namespace Oyster::Physics; const float MOVE_FORCE = 30; const float KEY_TIMER = 0.03f; -const float AFFECTED_TIMER = 1.0f; Player::Player() :DynamicObject() { Player::initPlayerData(); + AffectedObjects.Reserve(15); this->weapon = NULL; this->teamID = -1; } @@ -22,6 +22,7 @@ Player::Player(Oyster::Physics::ICustomBody *rigidBody, void (*EventOnCollision) { this->weapon = new Weapon(2,this); Player::initPlayerData(); + AffectedObjects.Reserve(15); this->teamID = teamID; } @@ -30,15 +31,16 @@ Player::Player(Oyster::Physics::ICustomBody *rigidBody, Oyster::Physics::ICustom { this->weapon = new Weapon(2,this); Player::initPlayerData(); + AffectedObjects.Reserve(15); this->teamID = teamID; } Player::~Player(void) { - if(this->weapon) + if(weapon) { - delete this->weapon; - this->weapon = NULL; + delete weapon; + weapon = NULL; } } void Player::initPlayerData() @@ -55,7 +57,7 @@ void Player::initPlayerData() this->key_strafeRight = 0; this->key_strafeLeft = 0; this->key_jump = 0; - this->RecentlyAffected = 0; + this->invincibleCooldown = 0; this->deathTimer = 0; this->rotationUp = 0; @@ -65,21 +67,14 @@ void Player::BeginFrame() { if( this->playerState != PLAYER_STATE_DEAD && PLAYER_STATE_DIED) { - weapon->Update(0.002f); - - - + weapon->Update(0.002f); Oyster::Math::Float maxSpeed = 30; // Rotate player accordingly + this->rigidBody->AddRotationAroundY(this->rotationUp); this->rigidBody->SetUp(this->rigidBody->GetState().centerPos.GetNormalized()); - Oyster::Math::Quaternion firstUp = this->rigidBody->GetState().quaternion; - this->rigidBody->SetRotationAsAngularAxis(Oyster::Math3D::Float4(this->rigidBody->GetState().centerPos.GetNormalized(), this->rotationUp)); - Oyster::Math::Quaternion secondTurn = this->rigidBody->GetState().quaternion; - this->rigidBody->SetRotation(secondTurn*firstUp); - // Direction data Oyster::Math::Float4x4 xform; xform = this->rigidBody->GetState().GetOrientation(); @@ -126,7 +121,7 @@ void Player::BeginFrame() } // Dampen velocity if certain keys are not pressed - if(key_jump <= 0.001 && this->rigidBody->GetLambda() < 0.9f) + if(key_jump <= 0.001 && IsWalking()) { if(key_forward <= 0.001 && key_backward <= 0.001) { @@ -153,7 +148,7 @@ void Player::BeginFrame() walkDirection.Normalize(); // If on the ground, accelerate normally - if(this->rigidBody->GetLambda() < 0.9f) + if(IsWalking()) { if(forwardSpeed < maxSpeed) { @@ -165,7 +160,7 @@ void Player::BeginFrame() } } // If in the air, accelerate slower - if(this->rigidBody->GetLambda() >= 0.9f) + if(IsJumping()) { if(forwardSpeed < maxSpeed) { @@ -195,7 +190,7 @@ void Player::BeginFrame() if(key_jump > 0.001) { this->key_jump -= this->gameInstance->GetFrameTime(); - if(this->rigidBody->GetLambda() < 0.9f) + if(IsWalking()) { Oyster::Math::Float3 up = this->rigidBody->GetState().centerPos.GetNormalized(); this->rigidBody->ApplyImpulse(up*this->rigidBody->GetState().mass * 20); @@ -218,6 +213,16 @@ void Player::BeginFrame() void Player::EndFrame() { + //check if there are any objects that can be removed from the AffectedObjects list + for(int i = 0; i < this->AffectedObjects.Size(); i++) + { + if(this->AffectedObjects[i] && (this->AffectedObjects[i]->GetRigidBody()->GetState().previousVelocity).GetMagnitude() <= 0.1f) + { + this->AffectedObjects[i]->RemoveAffectedBy(); + this->AffectedObjects.Remove(i); + } + + } } void Player::Move(const PLAYER_MOVEMENT &movement) @@ -287,7 +292,7 @@ void Player::SetLookDir(const Oyster::Math3D::Float3& lookDir) } void Player::TurnLeft(Oyster::Math3D::Float deltaRadians) { - this->rotationUp += deltaRadians; + this->rotationUp = deltaRadians; } void Player::Jump() @@ -297,15 +302,15 @@ void Player::Jump() bool Player::IsWalking() { - return (this->playerState == PLAYER_STATE::PLAYER_STATE_WALKING); + return (this->rigidBody->GetLambdaUp() < 0.99f); } bool Player::IsJumping() { - return (this->playerState == PLAYER_STATE::PLAYER_STATE_JUMPING); + return (this->rigidBody->GetLambdaUp() == 1.0f); } bool Player::IsIdle() { - return (this->playerState == PLAYER_STATE::PLAYER_STATE_IDLE); + return (this->rigidBody->GetLambdaUp() == 1.0f && this->rigidBody->GetLinearVelocity().GetMagnitude() < 0.0001f); } void Player::Inactivate() @@ -336,24 +341,32 @@ PLAYER_STATE Player::GetState() const void Player::DamageLife(int damage) { - if(damage != 0) + this->playerStats.hp -= damage; + // send hp to client + this->gameInstance->onDamageTakenFnc( this, this->playerStats.hp); + + if(this->playerStats.hp <= 0) { - this->playerStats.hp -= damage; - - if(this->playerStats.hp > 100) - this->playerStats.hp = 100; - - // send hp to client - this->gameInstance->onDamageTakenFnc( this, this->playerStats.hp); - - if(this->playerStats.hp <= 0) - { - this->playerStats.hp = 0; - this->playerState = PLAYER_STATE_DIED; - } + this->playerStats.hp = 0; + this->playerState = PLAYER_STATE_DIED; } + } +void Player::AddAffectedObject(DynamicObject &AffectedObject) +{ + //check if object already exists in the list, if so then do not add + for(int i = 0; i < AffectedObjects.Size(); i++) + { + if(AffectedObjects[i]->GetID() == AffectedObject.GetID()) + { + //object already exists, exit function + return; + } + } + //else you add the object to the stack + AffectedObjects.Push(&AffectedObject); +} bool Player::deathTimerTick(float dt) { this->deathTimer -= dt; diff --git a/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index b86f3821..27cd8ba5 100644 --- a/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/Physics/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -229,15 +229,15 @@ ICustomBody* API_Impl::AddTriangleMesh(const std::wstring fileName, ::Oyster::Ma SimpleRigidBody* body = new SimpleRigidBody; SimpleRigidBody::State state; - btBulletWorldImporter bulletFile; + btBulletWorldImporter bulletFile(0); typedef std::codecvt_utf8 convert_typeX; std::wstring_convert converterX; - std::string bulletPath = converterX.to_bytes(fileName); + //std::string bulletPath = converterX.to_bytes(); // Add collision shape - bulletFile.loadFile(bulletPath.c_str()); + bulletFile.loadFile("C:\\DV1477\\Git Repository\\Danbias\\Bin\\Content\\Worlds\\cgf\\structure_corporation.bullet"); btCollisionShape* collisionShape = bulletFile.getCollisionShapeByIndex(0); body->SetCollisionShape(collisionShape); @@ -247,8 +247,8 @@ ICustomBody* API_Impl::AddTriangleMesh(const std::wstring fileName, ::Oyster::Ma // Add rigid body btVector3 fallInertia(0, 0, 0); - collisionShape->calculateLocalInertia(mass, fallInertia); - btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); + //collisionShape->calculateLocalInertia(mass, fallInertia); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(0, motionState, collisionShape, fallInertia); btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); rigidBody->setFriction(staticFriction); rigidBody->setRestitution(restitution); @@ -264,7 +264,7 @@ ICustomBody* API_Impl::AddTriangleMesh(const std::wstring fileName, ::Oyster::Ma state.dynamicFrictionCoeff = dynamicFriction; state.staticFrictionCoeff = staticFriction; state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w); - state.mass = mass; + state.mass = 0; body->SetState(state); @@ -291,7 +291,7 @@ void API_Impl::UpdateWorld() simpleBody->SetPreviousVelocity(simpleBody->GetLinearVelocity()); } - this->dynamicsWorld->stepSimulation(this->timeStep, 10, this->timeStep); + this->dynamicsWorld->stepSimulation(this->timeStep, 1, this->timeStep); ICustomBody::State state; @@ -314,23 +314,12 @@ void API_Impl::UpdateWorld() ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer(); ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer(); - - int numContacts = contactManifold->getNumContacts(); for (int j=0;jgetContactPoint(j); if (pt.getDistance()<0.f) { - if(bodyA->GetState().mass == 40 && bodyB->GetState().centerPos == Float3::null) - { - const char* breakPoint = "STOP"; - } - if(bodyB->GetState().mass == 40 && bodyA->GetState().centerPos == Float3::null) - { - const char* breakPoint = "STOP"; - } - const btVector3& ptA = pt.getPositionWorldOnA(); const btVector3& ptB = pt.getPositionWorldOnB(); const btVector3& normalOnB = pt.m_normalWorldOnB; diff --git a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp index 9b9c7739..7fbd44e8 100644 --- a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -63,7 +63,8 @@ void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) this->rigidBody->setFriction(state.staticFrictionCoeff); this->rigidBody->setRestitution(state.restitutionCoeff); btVector3 fallInertia(0, 0, 0); - collisionShape->calculateLocalInertia(state.mass, fallInertia); + if(state.mass != 0) + collisionShape->calculateLocalInertia(state.mass, fallInertia); this->rigidBody->setMassProps(state.mass, fallInertia); this->state = state; @@ -185,7 +186,8 @@ void SimpleRigidBody::SetAngularFactor(Float factor) void SimpleRigidBody::SetMass(Float mass) { btVector3 fallInertia(0, 0, 0); - collisionShape->calculateLocalInertia(mass, fallInertia); + if(mass != 0) + collisionShape->calculateLocalInertia(mass, fallInertia); this->rigidBody->setMassProps(mass, fallInertia); this->state.mass = mass; } @@ -362,29 +364,25 @@ void SimpleRigidBody::PreStep (const btCollisionWorld* collisionWorld) { btTransform xform; xform = this->rigidBody->getWorldTransform (); - Float3 normalDown = -this->state.centerPos.GetNormalized(); - btVector3 down(normalDown.x, normalDown.y, normalDown.z); - btVector3 forward = xform.getBasis()[2]; - down.normalize (); + //Float3 normalDown = -xform.getBasis().getColumn(1); + btVector3 down(-xform.getBasis().getColumn(1)); + btVector3 forward(xform.getBasis().getColumn(2)); + down.normalize(); forward.normalize(); this->raySource[0] = xform.getOrigin(); this->raySource[1] = xform.getOrigin(); - if(this->state.reach.y < 1.0f) - - - Float angle = acos(Float3(0, 1, 0).Dot(this->state.centerPos.GetNormalized())); - //down.setZ(-down.z()); - btVector3 targetPlus = down * this->state.reach.y * btScalar(1.1); - if(this->state.mass == 40) { - const char* breakpoint = "STOP"; + const char* breakPoint = "STOP!"; } + btVector3 targetPlus = down*this->state.reach.y*btScalar(1.1); + this->rayTarget[0] = this->raySource[0] + targetPlus; - this->rayTarget[1] = this->raySource[1] + forward * this->state.reach.y * btScalar(1.1); + targetPlus = this->raySource[1] + forward*this->state.reach.z*btScalar(1.1); + this->rayTarget[1] = btVector3(targetPlus.x(), targetPlus.y(), targetPlus.z()); class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback { @@ -415,6 +413,10 @@ void SimpleRigidBody::PreStep (const btCollisionWorld* collisionWorld) if (rayCallback.hasHit()) { this->rayLambda[i] = rayCallback.m_closestHitFraction; + if(i == 1 && this->state.mass == 40) + { + btVector3 hitNormal = rayCallback.m_hitNormalWorld; + } } else { @@ -423,11 +425,16 @@ void SimpleRigidBody::PreStep (const btCollisionWorld* collisionWorld) } } -float SimpleRigidBody::GetLambda() const +float SimpleRigidBody::GetLambdaUp() const { return this->rayLambda[0]; } +float SimpleRigidBody::GetLambdaForward() const +{ + return this->rayLambda[1]; +} + void SimpleRigidBody::MoveToLimbo() { this->rigidBody->setCollisionFlags(this->rigidBody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); diff --git a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h index 65c59820..dc1158d7 100644 --- a/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/Physics/GamePhysics/Implementation/SimpleRigidBody.h @@ -68,7 +68,8 @@ namespace Oyster void PreStep(const btCollisionWorld* collisionWorld); - float GetLambda() const; + float GetLambdaUp() const; + float GetLambdaForward() const; void MoveToLimbo(); void ReleaseFromLimbo(); diff --git a/Code/Physics/GamePhysics/PhysicsAPI.h b/Code/Physics/GamePhysics/PhysicsAPI.h index a536bdce..3c2ef879 100644 --- a/Code/Physics/GamePhysics/PhysicsAPI.h +++ b/Code/Physics/GamePhysics/PhysicsAPI.h @@ -185,7 +185,8 @@ namespace Oyster ********************************************************/ virtual void SetCustomTag( void *ref ) = 0; - virtual float GetLambda() const = 0; + virtual float GetLambdaUp() const = 0; + virtual float GetLambdaForward() const = 0; }; } }