From 985dcf9691386f0ba5888fa46e5a4b9f0fa7dab9 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 09:15:21 +0100 Subject: [PATCH 01/10] Set up and stop angular movement support added --- .../Implementation/PhysicsAPI_Impl.cpp | 36 +++++++--------- .../Implementation/PhysicsAPI_Impl.h | 4 ++ .../Implementation/SimpleRigidBody.cpp | 43 +++++++++++++++++++ .../Implementation/SimpleRigidBody.h | 8 +++- Code/GamePhysics/PhysicsAPI.h | 6 +++ 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 9026a60f..e68c860f 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -24,6 +24,8 @@ API_Impl::API_Impl() this->dispatcher = NULL; this->solver = NULL; this->dynamicsWorld = NULL; + + this->timeStep = 1.0f/120.0f; } API_Impl::~API_Impl() @@ -39,7 +41,7 @@ API_Impl::~API_Impl() delete this->broadphase; this->broadphase = NULL; - for(int i = 0; i < this->customBodies.size(); i++) + for(unsigned int i = 0; i < this->customBodies.size(); i++) { delete this->customBodies[i]; this->customBodies[i] = NULL; @@ -164,27 +166,33 @@ ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::O return body; } +void API_Impl::SetTimeStep(float timeStep) +{ + this->timeStep = timeStep; +} + void API_Impl::UpdateWorld() { - this->dynamicsWorld->stepSimulation(1.0f/60.0f, 1.0f, 1.0f/60.0f); + this->dynamicsWorld->stepSimulation(this->timeStep, 1, this->timeStep); ICustomBody::State state; for(unsigned int i = 0; i < this->customBodies.size(); i++ ) { + SimpleRigidBody* simpleBody = dynamic_cast(this->customBodies[i]); btTransform trans; - dynamic_cast(this->customBodies[i])->GetMotionState()->getWorldTransform(trans); + simpleBody->GetMotionState()->getWorldTransform(trans); this->customBodies[i]->SetPosition(Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z())); this->customBodies[i]->SetRotation(Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w())); - if(dynamic_cast(this->customBodies[i])->GetRigidBody()->getActivationState() == ACTIVE_TAG) + if(simpleBody->GetRigidBody()->getActivationState() == ACTIVE_TAG) { - dynamic_cast(this->customBodies[i])->CallSubscription_Move(); + simpleBody->CallSubscription_Move(); } } int numManifolds = this->dynamicsWorld->getDispatcher()->getNumManifolds(); - for (int i=0;idynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i); const btCollisionObject* obA = contactManifold->getBody0(); @@ -195,18 +203,6 @@ void API_Impl::UpdateWorld() dynamic_cast(bodyA)->CallSubscription_AfterCollisionResponse(bodyA, bodyB, 0.0f); dynamic_cast(bodyB)->CallSubscription_AfterCollisionResponse(bodyB, bodyA, 0.0f); - - int numContacts = contactManifold->getNumContacts(); - for (int j=0;jgetContactPoint(j); - if (pt.getDistance()<0.f) - { - const btVector3& ptA = pt.getPositionWorldOnA(); - const btVector3& ptB = pt.getPositionWorldOnB(); - const btVector3& normalOnB = pt.m_normalWorldOnB; - } - } } } @@ -257,9 +253,7 @@ namespace Oyster } void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ) - { /* Do nothing except returning business as usual. */ - - } + { /* Do nothing except returning business as usual. */ } void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ) { /* Do nothing. */ } diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 28111d26..2d4c55ed 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -26,6 +26,8 @@ namespace Oyster ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); + void SetTimeStep(float timeStep); + void UpdateWorld(); void ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) ); @@ -37,6 +39,8 @@ namespace Oyster btSequentialImpulseConstraintSolver* solver; btDiscreteDynamicsWorld* dynamicsWorld; std::vector customBodies; + + float timeStep; }; namespace Default diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 879ff8bc..c2ae4cde 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -134,6 +134,49 @@ void SimpleRigidBody::SetRotation(Float3 eulerAngles) this->state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()); } +void SimpleRigidBody::SetAngularFactor(Float factor) +{ + this->rigidBody->setAngularFactor(factor); +} + +void SimpleRigidBody::SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right) +{ + btMatrix3x3 rotation; + btVector3 upVector(up.x, up.y, up.z); + btVector3 rightVector(right.x, right.y, right.z); + rotation[1] = upVector.normalized(); + rotation[0] = rightVector.normalized(); + rotation[2] = upVector.cross(rightVector).normalized(); + + btQuaternion quaternion; + rotation.getRotation(quaternion); + this->state.quaternion = Quaternion(Float3(quaternion.x(), quaternion.y(), quaternion.z()), quaternion.w()); + + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(quaternion); + this->motionState->setWorldTransform(trans); +} + +void SimpleRigidBody::SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward) +{ + btMatrix3x3 rotation; + btVector3 upVector(up.x, up.y, up.z); + btVector3 forwardVector(forward.x, forward.y, forward.z); + rotation[1] = upVector.normalized(); + rotation[0] = forwardVector.normalized(); + rotation[2] = upVector.cross(forwardVector).normalized(); + + btQuaternion quaternion; + rotation.getRotation(quaternion); + this->state.quaternion = Quaternion(Float3(quaternion.x(), quaternion.y(), quaternion.z()), quaternion.w()); + + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(quaternion); + this->motionState->setWorldTransform(trans); +} + Float4x4 SimpleRigidBody::GetRotation() const { return this->state.GetRotation(); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 55ae4fe3..f85b24df 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -26,10 +26,14 @@ namespace Oyster void SetSubscription(EventAction_Move function); void SetLinearVelocity(Math::Float3 velocity); - void SetPosition(::Oyster::Math::Float3 position); + void SetPosition(Math::Float3 position); void SetRotation(Math::Float4 quaternion); - void SetRotation(::Oyster::Math::Quaternion quaternion); + void SetRotation(Math::Quaternion quaternion); void SetRotation(Math::Float3 eulerAngles); + void SetAngularFactor(Math::Float factor); + + void SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right); + void SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward); Math::Float4x4 GetRotation() const; Math::Float4x4 GetOrientation() const; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index f57fe130..767caa98 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -84,6 +84,8 @@ namespace Oyster virtual ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; virtual ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; + virtual void SetTimeStep(float timeStep) = 0; + virtual void UpdateWorld() = 0; @@ -135,6 +137,10 @@ namespace Oyster virtual void SetRotation(::Oyster::Math::Float4 quaternion) = 0; virtual void SetRotation(::Oyster::Math::Quaternion quaternion) = 0; virtual void SetRotation(::Oyster::Math::Float3 eulerAngles) = 0; + virtual void SetAngularFactor(::Oyster::Math::Float factor) = 0; + + virtual void SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right) = 0; + virtual void SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward) = 0; ::Oyster::Math::Float4x4 GetRotation() const; ::Oyster::Math::Float4x4 GetOrientation() const; From d16d223c2ba3988f6f9147dfd5deada56443d746 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Tue, 11 Feb 2014 10:11:38 +0100 Subject: [PATCH 02/10] GL - player moving --- .../DanBiasGame/GameClientState/C_Object.cpp | 23 +++++++++--- .../DanBiasGame/GameClientState/C_Object.h | 8 +++-- .../GameClientState/C_obj/C_DynamicObj.cpp | 30 +--------------- .../GameClientState/C_obj/C_DynamicObj.h | 5 --- .../GameClientState/C_obj/C_Player.cpp | 34 +----------------- .../GameClientState/C_obj/C_Player.h | 7 ---- .../GameClientState/C_obj/C_StaticObj.cpp | 32 +---------------- .../GameClientState/C_obj/C_StaticObj.h | 5 --- .../GameClientState/C_obj/C_UIobject.cpp | 32 ----------------- .../GameClientState/C_obj/C_UIobject.h | 7 +--- .../DanBiasGame/GameClientState/GameState.cpp | 11 +++--- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Object.cpp | 16 +-------- Code/Game/GameLogic/Object.h | 2 -- Code/Game/GameLogic/Player.cpp | 36 +++++++++---------- 15 files changed, 52 insertions(+), 198 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp index 20b882d2..c5078224 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp @@ -5,6 +5,9 @@ void C_Object::Init(ModelInitData modelInit) position = modelInit.position; rotation = modelInit.rotation; scale = modelInit.scale; + id = modelInit.id; + model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); + model->Visible = modelInit.visible; updateWorld(); } void C_Object::updateWorld() @@ -17,10 +20,12 @@ void C_Object::updateWorld() scale.v[1].y = this->scale[1]; scale.v[2].z = this->scale[2]; world = translation * rot * scale; + + model->WorldMatrix = world; } void C_Object::setWorld(Oyster::Math::Float4x4 world) { - + model->WorldMatrix = world; } Oyster::Math::Float4x4 C_Object::getWorld() const { @@ -68,7 +73,15 @@ Oyster::Math::Float3 C_Object::getScale() const { return this->scale; } -//int C_Object::GetId() const -//{ -// return -//} +int C_Object::GetId() const +{ + return id; +} +void C_Object::Render() +{ + Oyster::Graphics::API::RenderModel(*(model)); +} +void C_Object::Release() +{ + Oyster::Graphics::API::DeleteModel(model); +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.h b/Code/Game/DanBiasGame/GameClientState/C_Object.h index 13932930..9c06d2da 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.h +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.h @@ -23,6 +23,8 @@ private: Oyster::Math::Float3 position; Oyster::Math::Quaternion rotation; Oyster::Math::Float3 scale; + Oyster::Graphics::Model::Model *model; + int id; void updateWorld(); public: @@ -40,8 +42,8 @@ public: void addScale(Oyster::Math::Float3 deltaScale); Oyster::Math::Float3 getScale() const; - virtual void Render() = 0; - virtual void Release() = 0; - virtual int GetId() = 0; + virtual void Render(); + virtual void Release(); + virtual int GetId() const; };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp index 71c46f4a..e654348f 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp @@ -1,15 +1,7 @@ #include "C_DynamicObj.h" #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_DynamicObj::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; - // light - // sound - // effect -}privData; + C_DynamicObj::C_DynamicObj(void) { } @@ -22,24 +14,4 @@ C_DynamicObj::~C_DynamicObj(void) void C_DynamicObj::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; } - -void C_DynamicObj::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_DynamicObj::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_DynamicObj::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h index d8e7023a..f73514da 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h @@ -8,15 +8,10 @@ namespace DanBias class C_DynamicObj : public C_Object { private: - struct myData; - myData* privData; public: C_DynamicObj(void); virtual ~C_DynamicObj(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp index 5e5525e9..02cc58fc 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp @@ -2,21 +2,11 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_Player::myData -{ - myData(){} - Oyster::Math3D::Float4x4 view; - Oyster::Math3D::Float4x4 proj; - Oyster::Graphics::Model::Model *model; - Oyster::Math3D::Float4 lookDir; - int ID; -}privData; - C_Player::C_Player(void) :C_DynamicObj() { -} +} C_Player::~C_Player(void) { @@ -26,26 +16,4 @@ C_Player::~C_Player(void) void C_Player::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - privData->lookDir = Oyster::Math3D::Float4 (0,0,1,0); } - - -void C_Player::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_Player::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_Player::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h index 556fd6dc..65a7e498 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h @@ -8,18 +8,11 @@ namespace DanBias class C_Player : public C_DynamicObj { private: - struct myData; - myData* privData; - public: C_Player(void); virtual ~C_Player(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); - };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp index 6e7a20e9..9b13c460 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp @@ -3,18 +3,10 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_StaticObj::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; - -}privData; C_StaticObj::C_StaticObj(void) { + } - - C_StaticObj::~C_StaticObj(void) { @@ -22,26 +14,4 @@ C_StaticObj::~C_StaticObj(void) void C_StaticObj::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - } - - -void C_StaticObj::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_StaticObj::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_StaticObj::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h index 3bae1961..d2bcb2a9 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h @@ -8,15 +8,10 @@ namespace DanBias class C_StaticObj : public C_Object { private: - struct myData; - myData* privData; public: C_StaticObj(void); virtual ~C_StaticObj(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); };};}; #endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp index fc9c7d53..570fa22f 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp @@ -2,13 +2,6 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_UIobject::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; -}privData; - C_UIobject::C_UIobject(void) { } @@ -20,29 +13,4 @@ C_UIobject::~C_UIobject(void) void C_UIobject::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - } -void C_UIobject::setPos(Oyster::Math::Float4x4 world) -{ - privData->model->WorldMatrix = world; -} - -void C_UIobject::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_UIobject::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_UIobject::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h index b41fb047..f002fcb2 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h @@ -8,16 +8,11 @@ namespace DanBias class C_UIobject : public C_Object { private: - struct myData; - myData* privData; + public: C_UIobject(void); virtual ~C_UIobject(void); void Init(ModelInitData modelInit); void setPos(Oyster::Math::Float4x4 world); - - void Render(); - void Release(); - int GetId(); };};}; #endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 8fecd86f..5214875a 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -122,7 +122,7 @@ bool GameState::LoadModels() this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); } - + /* // add crystal model modelData.position = Oyster::Math::Float3(10, 301, 0); modelData.modelPath = L"crystalformation_b.dan"; @@ -174,7 +174,7 @@ bool GameState::LoadModels() modelData.id = id++; // load models this->dynamicObjects.Push(new C_DynamicObj()); - this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); + this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);*/ return true; } bool GameState::LoadModels(std::string mapFile) @@ -316,7 +316,7 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo camera->setLook(objForward); up *= 2; - objForward *= -3; + objForward *= 3; Oyster::Math::Float3 cameraPos = up + pos + objForward; camera->SetPosition(cameraPos); @@ -566,8 +566,9 @@ void GameState::Protocol( ObjPos* pos ) if(dynamicObjects[i]->GetId() == pos->object_ID) { - dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); - + + //dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); + dynamicObjects[i]->setWorld(world); if(dynamicObjects[i]->GetId() == myId) // playerobj { diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 25fd51c1..15de4399 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -8,7 +8,7 @@ Game::PlayerData::PlayerData() //set some stats that are appropriate to a player Oyster::Math::Float3 centerPosition = Oyster::Math::Float3(0,608,-5); Oyster::Math::Float3 size = Oyster::Math::Float3(0.25f,1.0f,0.5f); - Oyster::Math::Float mass = 15; + Oyster::Math::Float mass = 60; Oyster::Math::Float restitutionCoeff = 0.5; Oyster::Math::Float frictionCoeff_Static = 0.4; Oyster::Math::Float frictionCoeff_Dynamic = 0.3; diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 77c256eb..b2b74838 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -20,8 +20,6 @@ Object::Object() this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(OBJECT_TYPE type) @@ -29,8 +27,6 @@ Object::Object(OBJECT_TYPE type) this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) @@ -38,8 +34,6 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) this->rigidBody = rigidBody; this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -48,8 +42,6 @@ Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -58,19 +50,14 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefor this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter), Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), OBJECT_TYPE type) { this->rigidBody = rigidBody; - this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } void Object::ApplyLinearImpulse(Oyster::Math::Float3 force) @@ -102,12 +89,11 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { - this->rigidBody->SetState(this->newPhysicsState); } // update physic void Object::EndFrame() { - this->newPhysicsState = this->currPhysicsState; + } void Object::setBeforeCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter)) diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h index 5450e9fe..1098cb56 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -51,8 +51,6 @@ namespace GameLogic protected: Oyster::Physics::ICustomBody *rigidBody; - Oyster::Physics::ICustomBody::State newPhysicsState; - Oyster::Physics::ICustomBody::State currPhysicsState; static const Game* gameInstance; Oyster::Math::Float3 currLook; diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index de45f8cb..acbb33a9 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -70,12 +70,11 @@ void Player::EndFrame() Object::EndFrame(); // rotate - Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; - Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; + //Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + //Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; //currPhysicsState.AddRotation(deltaAxis); - dx = 0; - this->newPhysicsState = this->currPhysicsState; + } void Player::Move(const PLAYER_MOVEMENT &movement) @@ -106,33 +105,32 @@ void Player::Move(const PLAYER_MOVEMENT &movement) void Player::MoveForward() { - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime())); - //rigidBody->SetLinearVelocity( 10 * this->gameInstance->GetFrameTime() ); + rigidBody->SetLinearVelocity( 10 * forward.GetNormalized() ); } void Player::MoveBackwards() { - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //newPhysicsState.ApplyLinearImpulse(-forward * MOVE_FORCE * this->gameInstance->GetFrameTime()); + rigidBody->SetLinearVelocity( 10 * -forward.GetNormalized() ); } void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - Oyster::Math::Float3 r = (-currPhysicsState.centerPos.Normalize()).Cross(forward); - //rigidBody->SetLinearVelocity(-r * 10 * this->gameInstance->GetFrameTime() ); + Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); + rigidBody->SetLinearVelocity(r * 10); } void Player::MoveLeft() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero - //newPhysicsState.ApplyLinearImpulse(r * MOVE_FORCE * this->gameInstance->GetFrameTime()); + Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); + rigidBody->SetLinearVelocity(-r * 10); } void Player::UseWeapon(const WEAPON_FIRE &usage) @@ -145,7 +143,7 @@ void Player::Respawn(Oyster::Math::Float3 spawnPoint) this->life = 100; this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE; this->lookDir = Oyster::Math::Float4(1,0,0); - this->newPhysicsState.centerPos = spawnPoint; + //this->newPhysicsState.centerPos = spawnPoint; } void Player::Rotate(const Oyster::Math3D::Float4 lookDir) @@ -162,7 +160,7 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir) void Player::Jump() { - Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1]; //newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime()); } @@ -181,11 +179,11 @@ bool Player::IsIdle() Oyster::Math::Float3 Player::GetPosition() const { - return (Oyster::Math::Float3)currPhysicsState.centerPos; + return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos; } Oyster::Math::Float4x4 Player::GetOrientation() const { - return this->currPhysicsState.GetOrientation(); + return this->rigidBody->GetState().GetOrientation(); } Oyster::Math::Float3 Player::GetLookDir() const { From ee1dc530fa4eca13ecd0065e54d1902fe392099e Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 10:49:37 +0100 Subject: [PATCH 03/10] Fixed up functions --- .../Implementation/PhysicsAPI_Impl.cpp | 2 +- .../Implementation/SimpleRigidBody.cpp | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index e68c860f..99f40d56 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -184,7 +184,7 @@ void API_Impl::UpdateWorld() simpleBody->GetMotionState()->getWorldTransform(trans); this->customBodies[i]->SetPosition(Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z())); this->customBodies[i]->SetRotation(Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w())); - + //simpleBody->SetUpAndRight(Float3(0,1,0), Float3(-1,0,0)); if(simpleBody->GetRigidBody()->getActivationState() == ACTIVE_TAG) { simpleBody->CallSubscription_Move(); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index c2ae4cde..cb136aa9 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -141,40 +141,40 @@ void SimpleRigidBody::SetAngularFactor(Float factor) void SimpleRigidBody::SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right) { + btTransform trans; btMatrix3x3 rotation; btVector3 upVector(up.x, up.y, up.z); btVector3 rightVector(right.x, right.y, right.z); rotation[1] = upVector.normalized(); rotation[0] = rightVector.normalized(); - rotation[2] = upVector.cross(rightVector).normalized(); + rotation[2] = rightVector.cross(upVector).normalized(); + + this->motionState->getWorldTransform(trans); + trans.setBasis(rotation); + this->motionState->setWorldTransform(trans); btQuaternion quaternion; - rotation.getRotation(quaternion); + quaternion = trans.getRotation(); this->state.quaternion = Quaternion(Float3(quaternion.x(), quaternion.y(), quaternion.z()), quaternion.w()); - - btTransform trans; - this->motionState->getWorldTransform(trans); - trans.setRotation(quaternion); - this->motionState->setWorldTransform(trans); } void SimpleRigidBody::SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward) { + btTransform trans; btMatrix3x3 rotation; btVector3 upVector(up.x, up.y, up.z); btVector3 forwardVector(forward.x, forward.y, forward.z); rotation[1] = upVector.normalized(); - rotation[0] = forwardVector.normalized(); - rotation[2] = upVector.cross(forwardVector).normalized(); + rotation[2] = forwardVector.normalized(); + rotation[0] = forwardVector.cross(upVector).normalized(); + + this->motionState->getWorldTransform(trans); + trans.setBasis(rotation); + this->motionState->setWorldTransform(trans); btQuaternion quaternion; - rotation.getRotation(quaternion); + quaternion = trans.getRotation(); this->state.quaternion = Quaternion(Float3(quaternion.x(), quaternion.y(), quaternion.z()), quaternion.w()); - - btTransform trans; - this->motionState->getWorldTransform(trans); - trans.setRotation(quaternion); - this->motionState->setWorldTransform(trans); } Float4x4 SimpleRigidBody::GetRotation() const From b5631457d305aa36d1bb32df3dd5a21b3d1ea242 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 11:45:16 +0100 Subject: [PATCH 04/10] Fixed up functions again --- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 2 +- Code/GamePhysics/Implementation/SimpleRigidBody.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 99f40d56..e68c860f 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -184,7 +184,7 @@ void API_Impl::UpdateWorld() simpleBody->GetMotionState()->getWorldTransform(trans); this->customBodies[i]->SetPosition(Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z())); this->customBodies[i]->SetRotation(Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w())); - //simpleBody->SetUpAndRight(Float3(0,1,0), Float3(-1,0,0)); + if(simpleBody->GetRigidBody()->getActivationState() == ACTIVE_TAG) { simpleBody->CallSubscription_Move(); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index cb136aa9..784bd0cc 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -149,9 +149,9 @@ void SimpleRigidBody::SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::F rotation[0] = rightVector.normalized(); rotation[2] = rightVector.cross(upVector).normalized(); - this->motionState->getWorldTransform(trans); + trans = this->rigidBody->getWorldTransform(); trans.setBasis(rotation); - this->motionState->setWorldTransform(trans); + this->rigidBody->setWorldTransform(trans); btQuaternion quaternion; quaternion = trans.getRotation(); @@ -168,9 +168,9 @@ void SimpleRigidBody::SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math: rotation[2] = forwardVector.normalized(); rotation[0] = forwardVector.cross(upVector).normalized(); - this->motionState->getWorldTransform(trans); + trans = this->rigidBody->getWorldTransform(); trans.setBasis(rotation); - this->motionState->setWorldTransform(trans); + this->rigidBody->setWorldTransform(trans); btQuaternion quaternion; quaternion = trans.getRotation(); From 528a591fabcbd7d1bfb40c7181cc4161251ac17f Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Tue, 11 Feb 2014 11:46:06 +0100 Subject: [PATCH 05/10] GL - almost rotating --- .../DanBiasGame/GameClientState/GameState.cpp | 4 ++-- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Object.cpp | 8 ++----- Code/Game/GameLogic/Player.cpp | 21 ++++++++----------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 5214875a..f3ce7b46 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -453,14 +453,14 @@ void GameState::readKeyInput(InputClass* KeyInput) } //send delta mouse movement - //if (KeyInput->IsMousePressed()) + if (KeyInput->IsMousePressed()) { camera->Yaw(-KeyInput->GetYaw()); camera->Pitch(KeyInput->GetPitch()); pitch = KeyInput->GetPitch(); camera->UpdateViewMatrix(); GameLogic::Protocol_PlayerLook playerLookDir; - Oyster::Math::Float4 look = camera->GetLook(); + Oyster::Math::Float4 look = camera->GetRight(); playerLookDir.lookDirX = look.x; playerLookDir.lookDirY = look.y; playerLookDir.lookDirZ = look.z; diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 15de4399..c8cbc997 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -16,7 +16,7 @@ Game::PlayerData::PlayerData() //create rigid body Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass, 0.5f, 0.8f, 0.6f ); - + //rigidBody->SetAngularFactor(0.0f); //create player with this rigid body this->player = new Player(rigidBody,Level::LevelCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index b2b74838..535268b7 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -107,13 +107,9 @@ void Object::setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage Oyster::Math::Float3 Object::GetPosition() { - Oyster::Physics::ICustomBody::State state; - state = this->rigidBody->GetState(); - return state.centerPos; + return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos; } Oyster::Math::Float4x4 Object::GetOrientation() { - Oyster::Physics::ICustomBody::State state; - state = this->rigidBody->GetState(); - return state.GetOrientation(); + return this->rigidBody->GetState().GetOrientation(); } \ No newline at end of file diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index acbb33a9..9e826ef5 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -22,7 +22,6 @@ Player::Player(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) { InitPlayer(); } - Player::Player(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) :DynamicObject(collisionFuncBefore,collisionFuncAfter,type) { @@ -60,21 +59,14 @@ Player::~Player(void) void Player::BeginFrame() { - weapon->Update(0.002f); + //weapon->Update(0.002f); Object::BeginFrame(); } void Player::EndFrame() { // snap to axis - Object::EndFrame(); - // rotate - - //Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; - //Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; - - //currPhysicsState.AddRotation(deltaAxis); - + Object::EndFrame(); } void Player::Move(const PLAYER_MOVEMENT &movement) @@ -143,11 +135,12 @@ void Player::Respawn(Oyster::Math::Float3 spawnPoint) this->life = 100; this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE; this->lookDir = Oyster::Math::Float4(1,0,0); - //this->newPhysicsState.centerPos = spawnPoint; + this->rigidBody->SetPosition(spawnPoint); } void Player::Rotate(const Oyster::Math3D::Float4 lookDir) { + // right Oyster::Math::Float dx = lookDir.w; if(dx > 0.0f) { @@ -156,12 +149,16 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir) this->lookDir = lookDir.xyz; this->dx = lookDir.w; + + + Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1]; + this->rigidBody->SetUpAndRight(up, lookDir.xyz); } void Player::Jump() { Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1]; - //newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime()); + //this->rigidBody->GetState().SetLinearVelocity(up *10); } bool Player::IsWalking() From 462413b5270f793c2685cf0e34ab4ee1930f2b75 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 13:09:46 +0100 Subject: [PATCH 06/10] Added support for gravity change --- Code/GamePhysics/Implementation/SimpleRigidBody.cpp | 7 ++++++- Code/GamePhysics/Implementation/SimpleRigidBody.h | 5 +++++ Code/GamePhysics/PhysicsAPI.h | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 784bd0cc..1201cad8 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -139,6 +139,12 @@ void SimpleRigidBody::SetAngularFactor(Float factor) this->rigidBody->setAngularFactor(factor); } +void SimpleRigidBody::SetGravity(Float3 gravity) +{ + this->rigidBody->setGravity(btVector3(gravity.x, gravity.y, gravity.z)); + this->gravity = gravity; +} + void SimpleRigidBody::SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right) { btTransform trans; @@ -167,7 +173,6 @@ void SimpleRigidBody::SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math: rotation[1] = upVector.normalized(); rotation[2] = forwardVector.normalized(); rotation[0] = forwardVector.cross(upVector).normalized(); - trans = this->rigidBody->getWorldTransform(); trans.setBasis(rotation); this->rigidBody->setWorldTransform(trans); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index f85b24df..70709c83 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -32,6 +32,8 @@ namespace Oyster void SetRotation(Math::Float3 eulerAngles); void SetAngularFactor(Math::Float factor); + void SetGravity(Math::Float3 gravity); + void SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right); void SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward); @@ -51,6 +53,7 @@ namespace Oyster void* GetCustomTag() const; private: + btCollisionShape* collisionShape; btDefaultMotionState* motionState; btRigidBody* rigidBody; @@ -61,6 +64,8 @@ namespace Oyster EventAction_Move onMovement; void *customTag; + + ::Oyster::Math::Float3 gravity; }; } } diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 767caa98..d44cb2db 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -139,6 +139,8 @@ namespace Oyster virtual void SetRotation(::Oyster::Math::Float3 eulerAngles) = 0; virtual void SetAngularFactor(::Oyster::Math::Float factor) = 0; + virtual void SetGravity(::Oyster::Math::Float3 gravity) = 0; + virtual void SetUpAndRight(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 right) = 0; virtual void SetUpAndForward(::Oyster::Math::Float3 up, ::Oyster::Math::Float3 forward) = 0; From 70c388779edd685dbf79fd8d89c8256f2aa75418 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 13:21:22 +0100 Subject: [PATCH 07/10] Lib change for bullet --- .../lib/Debug/BulletDynamics_Debug.lib | Bin 3733436 -> 3729574 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Code/Physics/lib/Debug/BulletDynamics_Debug.lib b/Code/Physics/lib/Debug/BulletDynamics_Debug.lib index 43b0628ed8d3d4cb4bdeb42cd08273c25241c4a2..3a9d1ab3ea091010cae6ff66ad1743148480a160 100644 GIT binary patch delta 86202 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⩔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 E2Z(JNu>b%7 delta 87820 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 b?uWnt2!laz91MYB5CJ0~T5H{oRd@db-TB=Z From 7075e6add62c905296ce6347b29d60007c308e66 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Tue, 11 Feb 2014 13:36:14 +0100 Subject: [PATCH 08/10] Gravity well --- .../Implementation/PhysicsAPI_Impl.cpp | 18 ++++++++++++++++++ .../Implementation/PhysicsAPI_Impl.h | 6 ++++++ Code/GamePhysics/PhysicsAPI.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index e68c860f..43e86a30 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -26,6 +26,9 @@ API_Impl::API_Impl() this->dynamicsWorld = NULL; this->timeStep = 1.0f/120.0f; + + this->gravityPoint = Float3(0.0f, 0.0f, 0.0f); + this->gravity = 10.0f; } API_Impl::~API_Impl() @@ -48,6 +51,16 @@ API_Impl::~API_Impl() } } +void API_Impl::SetGravityPoint(::Oyster::Math::Float3 gravityPoint) +{ + this->gravityPoint = gravityPoint; +} + +void API_Impl::SetGravity(float gravity) +{ + this->gravity = gravity; +} + // Bullet physics ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { @@ -173,6 +186,11 @@ void API_Impl::SetTimeStep(float timeStep) void API_Impl::UpdateWorld() { + for(unsigned int i = 0; i < this->customBodies.size(); i++ ) + { + this->customBodies[i]->SetGravity(-(this->customBodies[i]->GetState().centerPos - this->gravityPoint).GetNormalized()*this->gravity); + } + this->dynamicsWorld->stepSimulation(this->timeStep, 1, this->timeStep); ICustomBody::State state; diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 2d4c55ed..3cef6373 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -21,6 +21,9 @@ namespace Oyster void MoveToLimbo( const ICustomBody* objRef ); void ReleaseFromLimbo( const ICustomBody* objRef ); + void SetGravityPoint(::Oyster::Math::Float3 gravityPoint); + void SetGravity(float gravity); + // Bullet physics ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); @@ -41,6 +44,9 @@ namespace Oyster std::vector customBodies; float timeStep; + + ::Oyster::Math::Float3 gravityPoint; + float gravity; }; namespace Default diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index d44cb2db..ff2ba374 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -78,6 +78,8 @@ namespace Oyster ********************************************************/ virtual void ReleaseFromLimbo( const ICustomBody* objRef ) = 0; + virtual void SetGravityPoint(::Oyster::Math::Float3 gravityPoint) = 0; + virtual void SetGravity(float gravity) = 0; // Bullet physics virtual ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; From d771a5181d24a999ee015fc002a338007e523a1f Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Tue, 11 Feb 2014 13:41:38 +0100 Subject: [PATCH 09/10] GL - rotation and gravity fixed --- .../DanBiasGame/GameClientState/GameState.cpp | 6 +-- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 32 +----------- Code/Game/GameLogic/Object.cpp | 2 +- Code/Game/GameLogic/Player.cpp | 19 ++++--- .../Implementation/GameSession_Gameplay.cpp | 49 ------------------- .../Implementation/GameSession_General.cpp | 4 +- 7 files changed, 17 insertions(+), 97 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index f3ce7b46..2d49da99 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -565,8 +565,6 @@ void GameState::Protocol( ObjPos* pos ) { if(dynamicObjects[i]->GetId() == pos->object_ID) { - - //dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); dynamicObjects[i]->setWorld(world); @@ -592,10 +590,10 @@ void GameState::Protocol( ObjPos* pos ) //camera->setUp(up); //camera->setLook(objForward); - up *= 1; + up *= 2; objForward *= -2; Oyster::Math::Float3 cameraPos = pos + up + objForward; - //camera->SetPosition(cameraPos); + camera->SetPosition(cameraPos); //camera->UpdateViewMatrix(); } diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index c8cbc997..6b25c94f 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -16,7 +16,7 @@ Game::PlayerData::PlayerData() //create rigid body Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass, 0.5f, 0.8f, 0.6f ); - //rigidBody->SetAngularFactor(0.0f); + rigidBody->SetAngularFactor(0.0f); //create player with this rigid body this->player = new Player(rigidBody,Level::LevelCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 06d461fa..e2e52854 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -112,36 +112,8 @@ void Level::InitiateLevel(std::string levelPath) } void Level::InitiateLevel(float radius) { - float heading = Utility::Value::Radian(180.0f); - float attitude = Utility::Value::Radian(0.0f); - float bank = Utility::Value::Radian(0); - - double c1 = cos(heading/2); - double s1 = sin(heading/2); - double c2 = cos(attitude/2); - double s2 = sin(attitude/2); - double c3 = cos(bank/2); - double s3 = sin(bank/2); - double c1c2 = c1*c2; - double s1s2 = s1*s2; - double w =c1c2*c3 - s1s2*s3; - double x =c1c2*s3 + s1s2*c3; - double y =s1*c2*c3 + c1*s2*s3; - double z =c1*s2*c3 - s1*c2*s3; - double angle = 2 * acos(w); - - double norm = x*x+y*y+z*z; - if (norm < 0.001) { // when all euler angles are zero angle =0 so - // we can set axis to anything to avoid divide by zero - x=1; - y=z=0; - } else { - norm = sqrt(norm); - x /= norm; - y /= norm; - z /= norm; - } - + API::Instance().SetGravityPoint(Oyster::Math3D::Float3(0,0,0)); + API::Instance().SetGravity(50); int idCount = 100; // add level sphere ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 535268b7..6fbc8189 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -88,7 +88,7 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { - + } // update physic void Object::EndFrame() diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index 9e826ef5..039cae63 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -6,7 +6,7 @@ using namespace GameLogic; using namespace Oyster::Physics; -const int MOVE_FORCE = 500; +const int MOVE_FORCE = 30; Player::Player() :DynamicObject() { @@ -61,6 +61,8 @@ void Player::BeginFrame() { //weapon->Update(0.002f); Object::BeginFrame(); + + } void Player::EndFrame() @@ -98,31 +100,26 @@ void Player::Move(const PLAYER_MOVEMENT &movement) void Player::MoveForward() { Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; - //Oyster::Math::Float3 forward = lookDir; - rigidBody->SetLinearVelocity( 10 * forward.GetNormalized() ); + rigidBody->SetLinearVelocity( MOVE_FORCE * forward.GetNormalized() ); } void Player::MoveBackwards() { Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; - //Oyster::Math::Float3 forward = lookDir; - rigidBody->SetLinearVelocity( 10 * -forward.GetNormalized() ); + rigidBody->SetLinearVelocity( MOVE_FORCE * -forward.GetNormalized() ); } void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; - - //Oyster::Math::Float3 forward = lookDir; Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); - rigidBody->SetLinearVelocity(r * 10); + rigidBody->SetLinearVelocity(r * MOVE_FORCE); } void Player::MoveLeft() { //Do cross product with forward vector and negative gravity vector Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; - //Oyster::Math::Float3 forward = lookDir; Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); - rigidBody->SetLinearVelocity(-r * 10); + rigidBody->SetLinearVelocity(-r * MOVE_FORCE); } void Player::UseWeapon(const WEAPON_FIRE &usage) @@ -153,6 +150,8 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir) Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1]; this->rigidBody->SetUpAndRight(up, lookDir.xyz); + this->rigidBody->SetUpAndRight(this->rigidBody->GetState().centerPos.GetNormalized(), this->rigidBody->GetState().GetOrientation().v[0].xyz.GetNormalized()); + } void Player::Jump() diff --git a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp index b7d11e42..6cf5ec5c 100644 --- a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp @@ -97,59 +97,10 @@ namespace DanBias GameSession::gameSession->networkTimer.reset(); GameLogic::IObjectData* obj = movedObject; - if(movedObject->GetID() == testID) //TODO: TEST - { - float sec = (float)testTimer.getElapsedSeconds(); - sec = 0; - } int id = obj->GetID(); Protocol_ObjectPosition p(obj->GetOrientation(), id); - //if(id != 1) GameSession::gameSession->Send(p.GetProtocol()); - - - /* - if(dynamic_cast(obj)) - { - obj = ((GameLogic::ILevelData*)movedObject)->GetObjectAt(0); - if(obj) - { - if(obj->GetObjectType() == OBJECT_TYPE_WORLD) - { - int id = obj->GetID(); - Oyster::Math::Float4x4 world =obj->GetOrientation(); - - Protocol_ObjectPosition p(world, id); - gameSession->Send(p.GetProtocol()); - } - } - - obj =((GameLogic::ILevelData*)movedObject)->GetObjectAt(1); - if(obj) - { - if(obj->GetObjectType() == OBJECT_TYPE_BOX) - { - int id = obj->GetID(); - Oyster::Math::Float4x4 world = obj->GetOrientation(); - Protocol_ObjectPosition p(world, id); - gameSession->Send(p.GetProtocol()); - } - } - - obj =((GameLogic::ILevelData*)movedObject)->GetObjectAt(2); - if(obj) - { - if(obj->GetObjectType() == OBJECT_TYPE_BOX) - { - int id = obj->GetID(); - Oyster::Math::Float4x4 world = obj->GetOrientation(); - Protocol_ObjectPosition p(world, id); - GameSession::gameSession->Send(p.GetProtocol()); - } - } - } - */ } } diff --git a/Code/Game/GameServer/Implementation/GameSession_General.cpp b/Code/Game/GameServer/Implementation/GameSession_General.cpp index d6e6106c..941c4b6a 100644 --- a/Code/Game/GameServer/Implementation/GameSession_General.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_General.cpp @@ -136,7 +136,7 @@ namespace DanBias } else { - Protocol_LobbyCreateGame p(readyList[i]->GetPlayer()->GetID(), "char_white.dan", readyList[i]->GetPlayer()->GetOrientation()); + Protocol_LobbyCreateGame p(readyList[i]->GetPlayer()->GetID(), "char_temporary.dan", readyList[i]->GetPlayer()->GetOrientation()); readyList[i]->GetClient()->Send(p); } } @@ -156,7 +156,7 @@ namespace DanBias { if((this->clients[k] && readyList[i]) && readyList[i]->GetClient()->GetID() != this->clients[k]->GetClient()->GetID()) { - Protocol_ObjectCreate p(this->clients[k]->GetPlayer()->GetOrientation(), this->clients[k]->GetPlayer()->GetID(), "char_white.dan"); //The model name will be custom later.. + Protocol_ObjectCreate p(this->clients[k]->GetPlayer()->GetOrientation(), this->clients[k]->GetPlayer()->GetID(), "char_temporary.dan"); //The model name will be custom later.. readyList[i]->GetClient()->Send(p); } } From 89189f93d89100c88264b98e3276fa8d3e72c4c4 Mon Sep 17 00:00:00 2001 From: Erik Persson Date: Tue, 11 Feb 2014 14:03:14 +0100 Subject: [PATCH 10/10] asd --- Code/Game/GameLogic/Object.cpp | 36 +++++++++++++++++++++++++++++----- Code/Game/GameLogic/Object.h | 14 ++++++++++++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 6fbc8189..6e198e45 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -105,11 +105,37 @@ void Object::setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse)(collisionFuncAfter)); } -Oyster::Math::Float3 Object::GetPosition() -{ - return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos; -} + Oyster::Math::Float4x4 Object::GetOrientation() { - return this->rigidBody->GetState().GetOrientation(); + Oyster::Physics::ICustomBody::State state; + state = this->rigidBody->GetState(); + return state.GetOrientation(); +} + + +Oyster::Math::Float3 Object::GetPosition() +{ + return this->position; +} +Oyster::Math::Float3 Object::GetRotation() +{ + return this->rotation; +} +Oyster::Math::Float3 Object::GetScaling() +{ + return this->scale; +} + +void Object::SetPosition(Oyster::Math::Float3 position) +{ + this->position = position; +} +void Object::SetRotation(Oyster::Math::Float3 rotation) +{ + this->rotation = rotation; +} +void Object::SetScaling(Oyster::Math::Float3 scale) +{ + this->scale = scale; } \ No newline at end of file diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h index 1098cb56..6e4b9a81 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -29,10 +29,17 @@ namespace GameLogic OBJECT_TYPE GetObjectType() const; void setID(int id); int GetID() const; - Oyster::Math::Float3 GetPosition(); Oyster::Math::Float4x4 GetOrientation(); + Oyster::Math::Float3 GetPosition(); + Oyster::Math::Float3 GetRotation(); + Oyster::Math::Float3 GetScaling(); + + void SetPosition(Oyster::Math::Float3 position); + void SetRotation(Oyster::Math::Float3 rotation); + void SetScaling(Oyster::Math::Float3 scale); + Oyster::Physics::ICustomBody* GetRigidBody(); void ApplyLinearImpulse(Oyster::Math::Float3 force); @@ -55,6 +62,11 @@ namespace GameLogic static const Game* gameInstance; Oyster::Math::Float3 currLook; Oyster::Math::Float3 newLook; + + Oyster::Math::Float3 position; + Oyster::Math::Float3 rotation; + Oyster::Math::Float3 scale; + }; }