diff --git a/Bin/Level.txt b/Bin/Level.txt deleted file mode 100644 index d86dd3db..00000000 Binary files a/Bin/Level.txt and /dev/null differ diff --git a/Bin/map b/Bin/map deleted file mode 100644 index a578cc32..00000000 Binary files a/Bin/map and /dev/null differ diff --git a/Bin/map.txt b/Bin/map.txt deleted file mode 100644 index e5c751fb..00000000 Binary files a/Bin/map.txt and /dev/null differ diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index e8d9dfe2..97b64c33 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -86,6 +86,9 @@ namespace DanBias float dt = (float)m_data->timer.getElapsedSeconds(); m_data->timer.reset(); + if(m_data->recieverObj->IsConnected()) + m_data->recieverObj->Update(); + capFrame += dt; if(capFrame > 0.03) { @@ -135,8 +138,7 @@ namespace DanBias HRESULT DanBiasGame::Update(float deltaTime) { - if(m_data->recieverObj->IsConnected()) - m_data->recieverObj->Update(); + m_data->inputObj->Update(); diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 70fdba4e..5921dd12 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -44,7 +44,7 @@ bool GameState::Init(Oyster::Network::NetworkClient* nwClient) privData->state = gameStateState_loading; privData->nwClient = nwClient; privData->state = LoadGame(); - + pitch = 0; //tELL SERver ready nwClient->Send(GameLogic::Protocol_General_Status(GameLogic::Protocol_General_Status::States_ready)); @@ -120,7 +120,7 @@ bool GameState::LoadModels(std::wstring mapFile) // add player model 2 modelData.world = Oyster::Math3D::Float4x4::identity; - translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(10, 320, 0)); + translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(50, 320, 0)); modelData.world = modelData.world * translate; modelData.visible = true; @@ -131,6 +131,32 @@ bool GameState::LoadModels(std::wstring mapFile) privData->object.push_back(obj); privData->object[privData->object.size() -1 ]->Init(modelData); + // add house model + modelData.world = Oyster::Math3D::Float4x4::identity; + translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(50, 300, 0)); + //Oyster::Math3D::RotationMatrix_AxisZ() + modelData.world = modelData.world * translate; + modelData.visible = false; + modelData.modelPath = L"building_corporation.dan"; + modelData.id = 4; + // load models + obj = new C_Player(); + privData->object.push_back(obj); + privData->object[privData->object.size() -1 ]->Init(modelData); + + // add crystal model + modelData.world = Oyster::Math3D::Float4x4::identity; + translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(10, 305, 0)); + + modelData.world = modelData.world * translate; + modelData.visible = true; + modelData.modelPath = L"crystalformation_b.dan"; + modelData.id = 5; + // load models + obj = new C_Player(); + privData->object.push_back(obj); + privData->object[privData->object.size() -1 ]->Init(modelData); + return true; } @@ -286,14 +312,17 @@ void GameState::readKeyInput(InputClass* KeyInput) //send delta mouse movement if (KeyInput->IsMousePressed()) { - camera->Yaw(KeyInput->GetYaw()); - camera->Pitch(KeyInput->GetPitch()); + camera->Yaw(-KeyInput->GetYaw()); + //camera->Pitch(KeyInput->GetPitch()); + //pitch = KeyInput->GetPitch(); camera->UpdateViewMatrix(); GameLogic::Protocol_PlayerLook playerLookDir; - Oyster::Math::Float3 look = camera->GetLook(); + Oyster::Math::Float4 look = camera->GetLook(); playerLookDir.lookDirX = look.x; playerLookDir.lookDirY = look.y; playerLookDir.lookDirZ = look.z; + playerLookDir.deltaX = -KeyInput->GetYaw(); + privData->nwClient->Send(playerLookDir); } @@ -354,18 +383,34 @@ void GameState::Protocol( ObjPos* pos ) { world[i] = pos->worldPos[i]; } - + //printf("pos for obj %d, ",pos->object_ID ); for (unsigned int i = 0; i < privData->object.size(); i++) { if(privData->object[i]->GetId() == pos->object_ID) { privData->object[i]->setPos(world); //camera->setRight((Oyster::Math::Float3(world[0], world[1], world[2]))); - //camera->setUp((Oyster::Math::Float3(world[4], world[5], world[6]))); + // //camera->setLook((Oyster::Math::Float3(world[8], world[9], world[10]))); if(i == myId) // playerobj { - camera->SetPosition(Oyster::Math::Float3(world[12], world[13]+2.2f, world[14]-1)); + camera->setRight((Oyster::Math::Float3(world[0], world[1], world[2]))); + camera->setUp(Oyster::Math::Float3(world[4], world[5], world[6])); + Oyster::Math::Float3 cameraLook = camera->GetLook(); + Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10])); + + camera->setLook(objForward); + camera->UpdateViewMatrix(); + Oyster::Math::Float3 pos = Oyster::Math::Float3(world[12], world[13], world[14]); + Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]); + + up *= 2; + objForward *= -3; + Oyster::Math::Float3 cameraPos = up + pos + objForward; + //camera->Pitch(pitch); + camera->SetPosition(cameraPos); + //camera->LookAt(pos, dir, up); + //Oyster::Math::Float3 newLook = objForward; camera->UpdateViewMatrix(); } } diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.h b/Code/Game/DanBiasGame/GameClientState/GameState.h index 04d5b791..d555134c 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.h +++ b/Code/Game/DanBiasGame/GameClientState/GameState.h @@ -27,6 +27,7 @@ private: Camera* camera; int myId; + float pitch; struct myData; myData* privData; public: diff --git a/Code/Game/DanBiasLauncher/DanBiasLauncher.vcxproj b/Code/Game/DanBiasLauncher/DanBiasLauncher.vcxproj index 5e543af9..fec9d7dd 100644 --- a/Code/Game/DanBiasLauncher/DanBiasLauncher.vcxproj +++ b/Code/Game/DanBiasLauncher/DanBiasLauncher.vcxproj @@ -173,6 +173,11 @@ + + + {2a1bc987-af42-4500-802d-89cd32fc1309} + + diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.cpp b/Code/Game/GameLogic/AttatchmentMassDriver.cpp index a63b6e1d..1d8e06a4 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.cpp +++ b/Code/Game/GameLogic/AttatchmentMassDriver.cpp @@ -9,12 +9,16 @@ using namespace GameLogic; AttatchmentMassDriver::AttatchmentMassDriver(void) { this->owner = 0; + this->heldObject = NULL; + this->hasObject = false; } AttatchmentMassDriver::AttatchmentMassDriver(Player &owner) { this->owner = &owner; + this->heldObject = NULL; + this->hasObject = false; } @@ -35,22 +39,68 @@ void AttatchmentMassDriver::UseAttatchment(const GameLogic::WEAPON_FIRE &usage, ForcePush(usage,dt); break; case WEAPON_FIRE::WEAPON_USE_SECONDARY_PRESS: + + if(hasObject) + { + ForcePush(usage,dt);//WARNING THIS IS A CRAP TEST TO MAKE SURE YOU CAN SHOOT BOXES + break; + } ForcePull(usage,dt); break; + case WEAPON_FIRE::WEAPON_USE_UTILLITY_PRESS: + ForceZip(usage,dt); + break; } } +void AttatchmentMassDriver::Update(float dt) +{ + + //update position of heldObject if there is an object being held + if(hasObject) + { + Oyster::Physics::ICustomBody::State state; + state = heldObject->GetState(); + Oyster::Math::Float3 ownerPos = owner->GetPosition(); + ownerPos.y += 2; + Oyster::Math::Float3 pos = ownerPos + owner->GetLookDir().GetNormalized()*2; + + state.SetCenterPosition(pos); + + heldObject->SetState(state); + } +} + /******************************************************** * Pushes objects in a cone in front of the weapon when fired +*alternativly it puts a large force on the currently held object ********************************************************/ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float dt) { + //if the weapon has an object then it is only the object that will be shot away + Oyster::Math::Float4 pushForce; - Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (500 * dt); - Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + if(hasObject) + { + Oyster::Physics::API::Instance().ReleaseFromLimbo(heldObject); + pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (2000); + Oyster::Physics::ICustomBody::State state = heldObject->GetState(); + state.ApplyLinearImpulse((Oyster::Math::Float3)pushForce); + heldObject->SetState(state); + + hasObject = false; + heldObject = NULL; + return; + } + Oyster::Math::Float3 up = owner->GetOrientation().v[1]; + Oyster::Math::Float3 look = owner->GetLookDir(); + Oyster::Math::Float3 pos = owner->GetPosition(); - Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (50000 * dt); + Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(look, up, pos); + + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/8,1,1,5); Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); forcePushData args; args.pushForce = pushForce; @@ -61,7 +111,7 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float /******************************************************** * Pulls the player in the direction he is looking, used for fast movement(kinda like a jetpack) ********************************************************/ -void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) +void AttatchmentMassDriver::ForceZip(const WEAPON_FIRE &usage, float dt) { Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState(); @@ -72,3 +122,37 @@ void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) } +void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) +{ + if(hasObject) return; //this test checks if the weapon already has something picked up, if so then it cant use this function + + PickUpObject(usage,dt); //first test if there is a nearby object to pickup + + if(hasObject) return; //this test checks if the weapon has now picked up an object, if so then it shall not apply a force to suck in objects + + + //if no object has been picked up then suck objects towards you + Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (100 * dt); + Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); + forcePushData args; + args.pushForce = -pushForce; + + Oyster::Physics::API::Instance().ApplyEffect(hitFrustum,&args,ForcePushAction); +} + +void AttatchmentMassDriver::PickUpObject(const WEAPON_FIRE &usage, float dt) +{ + Oyster::Math::Float3 pos = owner->GetPosition() + owner->GetLookDir().GetNormalized()*5; + Oyster::Collision3D::Sphere hitSphere = Oyster::Collision3D::Sphere(pos,20); + /*Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + + Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); + Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); +*/ + + + Oyster::Physics::API::Instance().ApplyEffect(hitSphere,this,AttemptPickUp); +} diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.h b/Code/Game/GameLogic/AttatchmentMassDriver.h index 594ea4fd..51368e91 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.h +++ b/Code/Game/GameLogic/AttatchmentMassDriver.h @@ -16,29 +16,42 @@ namespace GameLogic void UseAttatchment(const WEAPON_FIRE &usage, float dt); + void Update(float dt); private: /******************************************************** * Pushes objects and players in a cone in front of the player - * @param fireInput: allows switching on different functionality in this specific function + * @param usage: allows switching on different functionality in this specific function ********************************************************/ void ForcePush(const WEAPON_FIRE &usage, float dt); /******************************************************** * Pulls the player forward, this is a movement tool - * @param fireInput: allows switching on different functionality in this specific function + * @param usage: allows switching on different functionality in this specific function + ********************************************************/ + void ForceZip(const WEAPON_FIRE &usage, float dt); + + /******************************************************** + * Sucks objects towards the player, the player can then pick up an object and throw it as a projectile + * @param usage: allows switching on different functionality in this specific function ********************************************************/ void ForcePull(const WEAPON_FIRE &usage, float dt); /******************************************************** * Sucks objects towards the player, the player can then pick up an object and throw it as a projectile - * @param fireInput: allows switching on different functionality in this specific function + * @param usage: allows switching on different functionality in this specific function ********************************************************/ - void ForceSuck(const WEAPON_FIRE &usage, float dt); + void PickUpObject(const WEAPON_FIRE &usage, float dt); + static void ForcePushAction(Oyster::Physics::ICustomBody *obj, void* args); + static void AttemptPickUp(Oyster::Physics::ICustomBody *obj, void* args); + + private: + Oyster::Physics::ICustomBody *heldObject; + bool hasObject; }; } diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp index c0b21462..911e08f8 100644 --- a/Code/Game/GameLogic/CollisionManager.cpp +++ b/Code/Game/GameLogic/CollisionManager.cpp @@ -5,13 +5,15 @@ #include "Level.h" #include "AttatchmentMassDriver.h" #include "Game.h" +#include "CollisionManager.h" +#include "JumpPad.h" using namespace Oyster; using namespace GameLogic; - void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss); void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss); + void SendObjectFlying(Oyster::Physics::ICustomBody &obj, Oyster::Math::Float3 force); //Physics::ICustomBody::SubscriptMessage void Player::PlayerCollision(Oyster::Physics::ICustomBody *rigidBodyPlayer, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) @@ -28,34 +30,56 @@ using namespace GameLogic; break; case OBJECT_TYPE::OBJECT_TYPE_BOX: - PlayerVBox(*player,(*(DynamicObject*) realObj), kineticEnergyLoss); + PlayerVObject(*player,*realObj, kineticEnergyLoss); //return Physics::ICustomBody::SubscriptMessage_none; break; case OBJECT_TYPE::OBJECT_TYPE_PLAYER: //return Physics::ICustomBody::SubscriptMessage_none; break; case OBJECT_TYPE::OBJECT_TYPE_WORLD: - int test = 5; + PlayerVObject(*player,*realObj, kineticEnergyLoss); break; } //return Physics::ICustomBody::SubscriptMessage_none; } - - void PlayerVBox(Player &player, DynamicObject &box, Oyster::Math::Float kineticEnergyLoss) + + void JumpPad::JumpPadActivated(Oyster::Physics::ICustomBody *rigidBodyJumpPad, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) { - //use kinetic energyloss of the collision in order too determin how much damage to take - //use as part of the damage algorithm - player.DamageLife(20); + JumpPad *jumpPad = (JumpPad*)(rigidBodyJumpPad->GetCustomTag()); + Object *realObj = (Object*)obj->GetCustomTag(); //needs to be changed? + + switch (realObj->GetObjectType()) + { + case OBJECT_TYPE::OBJECT_TYPE_GENERIC: + break; + case OBJECT_TYPE::OBJECT_TYPE_BOX: + break; + case OBJECT_TYPE::OBJECT_TYPE_PLAYER: + SendObjectFlying(*obj, jumpPad->pushForce); + break; + case OBJECT_TYPE::OBJECT_TYPE_WORLD: + break; + } } + void SendObjectFlying(Oyster::Physics::ICustomBody &obj, Oyster::Math::Float3 force) + { + Oyster::Physics::ICustomBody::State state; + + state = obj.GetState(); + state.ApplyLinearImpulse(force); + obj.SetState(state); + } + + void PlayerVObject(Player &player, Object &obj, Oyster::Math::Float kineticEnergyLoss) { //Collision between a player and a general static or dynamic object //use kinetic energyloss of the collision in order too determin how much damage to take //use as part of the damage algorithm int damageDone = 0; - int forceThreashHold = 200; + int forceThreashHold = 200000; if(kineticEnergyLoss > forceThreashHold) //should only take damage if the force is high enough { @@ -77,6 +101,13 @@ using namespace GameLogic; { return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; } + + Oyster::Physics::ICustomBody::SubscriptMessage CollisionManager::IgnoreCollision(Oyster::Physics::ICustomBody *rigidBody, Oyster::Physics::ICustomBody *obj) + { + return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; + } + + Oyster::Physics::ICustomBody::SubscriptMessage Level::LevelCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss) { return Physics::ICustomBody::SubscriptMessage_ignore_collision_response; @@ -93,4 +124,33 @@ using namespace GameLogic; state = obj->GetState(); state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce); obj->SetState(state); + } + + void AttatchmentMassDriver::AttemptPickUp(Oyster::Physics::ICustomBody *obj, void* args) + { + AttatchmentMassDriver *weapon = ((AttatchmentMassDriver*)args); + + if(weapon->hasObject) + { + //do nothing + } + else + { + Object* realObj = (Object*)(obj->GetCustomTag()); + //check so that it is an object that you can pickup + + switch(realObj->GetObjectType()) + { + case OBJECT_TYPE::OBJECT_TYPE_BOX: + //move obj to limbo in physics to make sure it wont collide with anything + Oyster::Physics::API::Instance().MoveToLimbo(obj); + weapon->heldObject = obj; //weapon now holds the object + weapon->hasObject = true; + + break; + } + + } + + } \ No newline at end of file diff --git a/Code/Game/GameLogic/CollisionManager.h b/Code/Game/GameLogic/CollisionManager.h index 6179333f..d3be9809 100644 --- a/Code/Game/GameLogic/CollisionManager.h +++ b/Code/Game/GameLogic/CollisionManager.h @@ -11,6 +11,7 @@ namespace GameLogic { public: //put general collision functions here that are not part of a specific object + static Oyster::Physics::ICustomBody::SubscriptMessage IgnoreCollision(Oyster::Physics::ICustomBody *rigidBody, Oyster::Physics::ICustomBody *obj); }; diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index ae030c19..ccb2a37d 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -42,7 +42,7 @@ GameAPI& GameAPI::Instance() Game::Game(void) : initiated(false) , onMoveFnc(0) - , onDeadFnc(0) + , onDisableFnc(0) , frameTime(1.0f/120.0f) {} @@ -129,7 +129,7 @@ void Game::SetSubscription(GameEvent::ObjectEventFunctionType type, GameEvent::O this->onMoveFnc = functionPointer; break; case GameLogic::GameEvent::ObjectEventFunctionType_OnDead: - this->onDeadFnc = functionPointer; + this->onDisableFnc = functionPointer; break; } @@ -162,6 +162,6 @@ void Game::PhysicsOnMove(const ICustomBody *object) } void Game::PhysicsOnDestroy(::Utility::DynamicMemory::UniquePointer proto) { - + if(gameInstance.onDisableFnc) gameInstance.onDisableFnc(0); } diff --git a/Code/Game/GameLogic/Game.h b/Code/Game/GameLogic/Game.h index a1427689..ddcfc086 100644 --- a/Code/Game/GameLogic/Game.h +++ b/Code/Game/GameLogic/Game.h @@ -39,7 +39,7 @@ namespace GameLogic Oyster::Math::Float4x4 GetOrientation() override; int GetID() const override; OBJECT_TYPE GetObjectType() const override; - void Rotate(const Oyster::Math3D::Float3 lookDir) override; + void Rotate(const Oyster::Math3D::Float4 lookDir) override; Player *player; }; @@ -80,7 +80,7 @@ namespace GameLogic LevelData* level; float frameTime; bool initiated; - GameEvent::ObjectEventFunction onDeadFnc; + GameEvent::ObjectEventFunction onDisableFnc; GameEvent::ObjectEventFunction onMoveFnc; }; diff --git a/Code/Game/GameLogic/GameAPI.h b/Code/Game/GameLogic/GameAPI.h index ee4bad83..f0ce50b1 100644 --- a/Code/Game/GameLogic/GameAPI.h +++ b/Code/Game/GameLogic/GameAPI.h @@ -79,7 +79,7 @@ namespace GameLogic * @param x: The relative x axis * @param y: The relative y axis **/ - virtual void Rotate(const Oyster::Math3D::Float3 lookDir) = 0; + virtual void Rotate(const Oyster::Math3D::Float4 lookDir) = 0; /******************************************************** * Uses the chosen players weapon based on input diff --git a/Code/Game/GameLogic/GameLogic.vcxproj b/Code/Game/GameLogic/GameLogic.vcxproj index 809c82b5..674773bf 100644 --- a/Code/Game/GameLogic/GameLogic.vcxproj +++ b/Code/Game/GameLogic/GameLogic.vcxproj @@ -183,6 +183,7 @@ + @@ -206,6 +207,7 @@ + diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index e19af2f3..bf2cbcbe 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -11,13 +11,19 @@ Game::PlayerData::PlayerData() sbDesc.size = Oyster::Math::Float3(4,7,4); sbDesc.mass = 70; sbDesc.restitutionCoeff = 0.5; + sbDesc.rotation = Oyster::Math::Float3(0, Oyster::Math::pi, 0); + //create rigid body Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); //create player with this rigid body this->player = new Player(rigidBody,Object::DefaultCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); - + /*Oyster::Physics::ICustomBody::State state; + this->player->GetRigidBody()->GetState(state); + state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0)); + this->player->GetRigidBody()->SetState(state); + player->EndFrame();*/ } Game::PlayerData::PlayerData(int playerID,int teamID) { @@ -61,7 +67,7 @@ OBJECT_TYPE Game::PlayerData::GetObjectType() const { return this->player->GetObjectType(); } -void Game::PlayerData::Rotate(const Oyster::Math3D::Float3 lookDir) +void Game::PlayerData::Rotate(const Oyster::Math3D::Float4 lookDir) { this->player->Rotate(lookDir); } \ No newline at end of file diff --git a/Code/Game/GameLogic/IAttatchment.h b/Code/Game/GameLogic/IAttatchment.h index e458fdbf..9984303a 100644 --- a/Code/Game/GameLogic/IAttatchment.h +++ b/Code/Game/GameLogic/IAttatchment.h @@ -20,6 +20,7 @@ namespace GameLogic ~IAttatchment(void); virtual void UseAttatchment(const WEAPON_FIRE &usage, float dt) = 0; + virtual void Update(float dt) = 0; private: diff --git a/Code/Game/GameLogic/JumpPad.cpp b/Code/Game/GameLogic/JumpPad.cpp new file mode 100644 index 00000000..c60e248c --- /dev/null +++ b/Code/Game/GameLogic/JumpPad.cpp @@ -0,0 +1,21 @@ +#include "JumpPad.h" +#include "PhysicsAPI.h" + +using namespace GameLogic; +using namespace Oyster::Physics; + +JumpPad::JumpPad(void) +{ +} + +JumpPad::JumpPad(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, Oyster::Math::Float3 pushForce) + :StaticObject(rigidBody, collisionFuncBefore, collisionFuncAfter, type) +{ + +} + + + +JumpPad::~JumpPad(void) +{ +} diff --git a/Code/Game/GameLogic/JumpPad.h b/Code/Game/GameLogic/JumpPad.h new file mode 100644 index 00000000..b9fe2253 --- /dev/null +++ b/Code/Game/GameLogic/JumpPad.h @@ -0,0 +1,26 @@ +#ifndef JUMPPAD_H +#define JUMPPAD_H +#include "StaticObject.h" +namespace GameLogic +{ + class JumpPad : public StaticObject + { + public: + JumpPad(void); + + JumpPad(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, Oyster::Math::Float3 pushForce); + + ~JumpPad(void); + + static void JumpPadActivated(Oyster::Physics::ICustomBody *rigidBodyJumpPad, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss); + + private: + Oyster::Math::Float3 pushForce; + + + }; +} +#endif diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 2f08a671..806af52d 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -34,7 +34,8 @@ void Level::InitiateLevel(float radius) sbDesc.ignoreGravity = true; sbDesc.radius = 300; sbDesc.mass = 10e12f; - + sbDesc.frictionCoeff_Static = 0; + sbDesc.frictionCoeff_Dynamic = 0; ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); ICustomBody::State state; @@ -45,19 +46,15 @@ void Level::InitiateLevel(float radius) this->levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); rigidBody->SetCustomTag(levelObj); - // add gravitation - API::Gravity gravityWell; - gravityWell.gravityType = API::Gravity::GravityType_Well; - gravityWell.well.mass = 1e15f; - gravityWell.well.position = Oyster::Math::Float3(0,0,0); - API::Instance().AddGravity(gravityWell); // add box API::SimpleBodyDescription sbDesc_TestBox; sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,0); sbDesc_TestBox.ignoreGravity = false; + sbDesc_TestBox.mass = 50; sbDesc_TestBox.size = Oyster::Math::Float4(4,4,4,0); + ICustomBody* rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -65,8 +62,16 @@ void Level::InitiateLevel(float radius) testBox = new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX); rigidBody_TestBox->SetCustomTag(testBox); rigidBody_TestBox->GetState(state); - state.ApplyLinearImpulse(Oyster::Math::Float3(1,0,0)); + state.ApplyLinearImpulse(Oyster::Math::Float3(0,0,0)); rigidBody_TestBox->SetState(state); + + + // add gravitation + API::Gravity gravityWell; + gravityWell.gravityType = API::Gravity::GravityType_Well; + gravityWell.well.mass = 1e18f; + gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); + API::Instance().AddGravity(gravityWell); } void Level::AddPlayerToTeam(Player *player, int teamID) diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp index d60aac66..5bb916ab 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp +++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp @@ -3,16 +3,30 @@ ////////////////////////////////// #include "LevelLoader.h" +#include "LevelParser.h" using namespace GameLogic; using namespace GameLogic::LevelFileLoader; - -std::vector LevelLoader::LoadLevel(std::string fileName) +struct LevelLoader::PrivData { - return parser.Parse(fileName); + LevelParser parser; +}; + +LevelLoader::LevelLoader() + : pData(new PrivData) +{ +} + +LevelLoader::~LevelLoader() +{ +} + +std::vector> LevelLoader::LoadLevel(std::string fileName) +{ + return pData->parser.Parse(fileName); } LevelMetaData LevelLoader::LoadLevelHeader(std::string fileName) { - return parser.ParseHeader(fileName); + return pData->parser.ParseHeader(fileName); } \ No newline at end of file diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.h b/Code/Game/GameLogic/LevelLoader/LevelLoader.h index 4ac7a950..bcd6e587 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelLoader.h +++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.h @@ -7,36 +7,36 @@ #include #include -#include +#include "../Misc/Utilities.h" #include "ObjectDefines.h" -#include "LevelParser.h" namespace GameLogic { - class LevelLoader - { + class LevelLoader + { - public: - LevelLoader(){this->parser = GameLogic::LevelFileLoader::LevelParser(); } - ~LevelLoader(){} + public: + LevelLoader(); + ~LevelLoader(); - /******************************************************** - * Loads the level and objects from file. - * @param fileName: Path to the level-file that you want to load. - * @return: Returns all structs with objects and information about the level. - ********************************************************/ - std::vector LoadLevel(std::string fileName); + /******************************************************** + * Loads the level and objects from file. + * @param fileName: Path to the level-file that you want to load. + * @return: Returns all structs with objects and information about the level. + ********************************************************/ + std::vector> LoadLevel(std::string fileName); - /******************************************************** - * Just for fast access for the meta information about the level. - * @param fileName: Path to the level-file that you want to load. - * @return: Returns the meta information about the level. - ********************************************************/ - LevelMetaData LoadLevelHeader(std::string fileName); //. + /******************************************************** + * Just for fast access for the meta information about the level. + * @param fileName: Path to the level-file that you want to load. + * @return: Returns the meta information about the level. + ********************************************************/ + LevelMetaData LoadLevelHeader(std::string fileName); //. - private: - GameLogic::LevelFileLoader::LevelParser parser; - }; + private: + struct PrivData; + Utility::DynamicMemory::SmartPointer pData; + }; } #endif \ No newline at end of file diff --git a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp index 3ab3c203..088c3916 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp +++ b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp @@ -5,6 +5,7 @@ using namespace GameLogic; using namespace ::LevelFileLoader; +using namespace Utility::DynamicMemory; LevelParser::LevelParser() { @@ -16,12 +17,12 @@ LevelParser::~LevelParser() { } -std::vector LevelParser::Parse(std::string filename) +std::vector> LevelParser::Parse(std::string filename) { int bufferSize = 0; int counter = 0; - std::vector objects; + std::vector> objects; //Read entire level file. Loader loader; @@ -29,39 +30,79 @@ std::vector LevelParser::Parse(std::string filename) //Read format version FormatVersion levelFormatVersion; - //ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion)); + ParseObject(&buffer[counter], &levelFormatVersion, sizeof(levelFormatVersion)); + counter += sizeof(levelFormatVersion); if(this->formatVersion != levelFormatVersion) { //Do something if it's not the same version } - while(counter < bufferSize) + while(counter < bufferSize) { //Get typeID ObjectTypeHeader typeID; ParseObject(&buffer[counter], &typeID, sizeof(typeID)); switch((int)typeID.typeID) { - case ObjectType_LevelMetaData: - { - LevelMetaData header; - ParseLevelMetaData(&buffer[counter], header, counter); - objects.push_back(header); - break; - } + case ObjectType_LevelMetaData: + { + LevelMetaData* header = new LevelMetaData; + ParseLevelMetaData(&buffer[counter], *header, counter); + objects.push_back(header); + break; + } - case ObjectType_Dynamic: - { - ObjectHeader header; - ParseObject(&buffer[counter], &header, sizeof(header)); - objects.push_back(header); - counter += sizeof(header); - break; - } + //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them. + case ObjectType_Static: case ObjectType_Dynamic: + { + ObjectHeader* header = new ObjectHeader; + ParseObject(&buffer[counter], *header, counter); + objects.push_back(header); + break; + } - default: - //Couldn't find typeID. FAIL!!!!!! - break; + case ObjectType_Light: + { + LightType lightType; + + //Get Light type + ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); + + switch(lightType) + { + case LightType_PointLight: + { + PointLight* header = new PointLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + case LightType_DirectionalLight: + { + DirectionalLight* header = new DirectionalLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + case LightType_SpotLight: + { + SpotLight* header = new SpotLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + default: + //Undefined LightType. + break; + } + break; + } + default: + //Couldn't find typeID. FAIL!!!!!! + break; } } @@ -83,7 +124,8 @@ LevelMetaData LevelParser::ParseHeader(std::string filename) //Read format version FormatVersion levelFormatVersion; - //ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion)); + ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion)); + counter += sizeof(levelFormatVersion); if(this->formatVersion != levelFormatVersion) { //Do something if it's not the same version @@ -101,11 +143,42 @@ LevelMetaData LevelParser::ParseHeader(std::string filename) ParseLevelMetaData(&buffer[counter], levelHeader, counter); return levelHeader; break; - case ObjectType_Dynamic: - //Do not call parse this object, since we are only interested in the LevelMetaData - //Only increase the counter size - counter += sizeof(ObjectHeader); + + //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them. + case ObjectType_Static: case ObjectType_Dynamic: + { + ObjectHeader header; + ParseObject(&buffer[counter], header, counter); break; + } + + case ObjectType_Light: + { + LightType lightType; + ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); + + switch(lightType) + { + case LightType_PointLight: + { + counter += sizeof(PointLight); + break; + } + case LightType_DirectionalLight: + { + counter += sizeof(DirectionalLight); + break; + } + case LightType_SpotLight: + { + counter += sizeof(SpotLight); + break; + } + default: + //Undefined LightType. + break; + } + } default: //Couldn't find typeID. FAIL!!!!!! diff --git a/Code/Game/GameLogic/LevelLoader/LevelParser.h b/Code/Game/GameLogic/LevelLoader/LevelParser.h index 6dce25f8..9ad30642 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelParser.h +++ b/Code/Game/GameLogic/LevelLoader/LevelParser.h @@ -4,6 +4,7 @@ #include #include #include "ObjectDefines.h" +#include "../Misc/Utilities.h" namespace GameLogic { @@ -16,7 +17,7 @@ namespace GameLogic ~LevelParser(); // - std::vector Parse(std::string filename); + std::vector> Parse(std::string filename); // LevelMetaData ParseHeader(std::string filename); diff --git a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h index dcf960a5..7c924976 100644 --- a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h +++ b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h @@ -15,11 +15,12 @@ namespace GameLogic ObjectType_LevelMetaData, ObjectType_Static, ObjectType_Dynamic, + ObjectType_Light, //Etc ObjectType_NUM_OF_TYPES, - ObjectType_Unknown = -1, + ObjectType_Unknown = -1 }; enum UsePhysics @@ -27,9 +28,20 @@ namespace GameLogic UsePhysics_UseFullPhysics, UsePhysics_IgnoreGravity, UsePhysics_IgnorePhysics, + UsePhysics_IgnoreCollision, UsePhysics_Count, - UsePhysics_Unknown = -1, + UsePhysics_Unknown = -1 + }; + + enum LightType + { + LightType_PointLight, + LightType_DirectionalLight, + LightType_SpotLight, + + LightType_Count, + LightType_Unknown = -1 }; //Should this be moved somewhere else? @@ -40,7 +52,7 @@ namespace GameLogic //Etc GameMode_Count, - GameMode_Unknown = -1, + GameMode_Unknown = -1 }; @@ -71,32 +83,31 @@ namespace GameLogic struct PhysicsObject { + UsePhysics usePhysics; float mass; - float elasticity; + float inertiaMagnitude[3]; + float inertiaRotation[3]; float frictionCoeffStatic; float frictionCoeffDynamic; - float inertiaTensor[16]; - UsePhysics usePhysics; + }; struct LevelMetaData : ObjectTypeHeader { std::string levelName; - FormatVersion levelVersion; + int levelVersion; std::string levelDescription; std::string levelAuthor; int maxNumberOfPlayer; - float worldSize; - int overviewPictureID; + int worldSize; + std::string overviewPicturePath; std::vector gameModesSupported; }; struct ObjectHeader : public ObjectTypeHeader { //Model, - int ModelID; - //Texture - int TextureID; + std::string ModelFile; //Position float position[3]; //Rotation @@ -104,6 +115,36 @@ namespace GameLogic //Scale float scale[3]; }; + + + /************************************ + Lights + *************************************/ + + struct BasicLight : public ObjectTypeHeader + { + LightType lightType; + float ambientColor[3]; + float diffuseColor[3]; + float specularColor[3]; + }; + + struct PointLight : public BasicLight + { + float position[3]; + }; + + struct DirectionalLight : public BasicLight + { + float direction[3]; + }; + + struct SpotLight : public BasicLight + { + float direction[3]; + float range; + float attenuation[3]; + }; } #endif \ No newline at end of file diff --git a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp index f456b2d7..68631bf0 100644 --- a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp +++ b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp @@ -20,11 +20,33 @@ namespace GameLogic memcpy(header, buffer, size); } + void ParseObject(char* buffer, ObjectHeader& header, int& size) + { + char tempName[128]; + int tempSize = 0; + int start = 0; + + memcpy(&header.typeID, &buffer[start], 4); + start += 4; + + memcpy(&tempSize, &buffer[start], 4); + start += 4; + + memcpy(&tempName, &buffer[start], tempSize); + header.ModelFile.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + memcpy(&header.position, &buffer[start], 36); + start += 36; + + size += start; + } + void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size) { int start = 0; int tempSize; - char tempName[100]; + char tempName[128]; memcpy(&header.typeID, &buffer[start], 4); start += 4; @@ -36,8 +58,8 @@ namespace GameLogic header.levelName.assign(&tempName[0], &tempName[tempSize]); start += tempSize; - memcpy(&header.levelVersion, &buffer[start], 8); - start += 8; + memcpy(&header.levelVersion, &buffer[start], 4); + start += 4; memcpy(&tempSize, &buffer[start], 4); start +=4; @@ -59,9 +81,13 @@ namespace GameLogic memcpy(&header.worldSize, &buffer[start], 4); start += 4; - memcpy(&header.overviewPictureID, &buffer[start], 4); + memcpy(&tempSize, &buffer[start], 4); start += 4; + memcpy(&tempName, &buffer[start], tempSize); + header.overviewPicturePath.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + memcpy(&tempSize, &buffer[start], 4); start += 4; diff --git a/Code/Game/GameLogic/LevelLoader/ParseFunctions.h b/Code/Game/GameLogic/LevelLoader/ParseFunctions.h index 08962b4a..f68a9289 100644 --- a/Code/Game/GameLogic/LevelLoader/ParseFunctions.h +++ b/Code/Game/GameLogic/LevelLoader/ParseFunctions.h @@ -10,8 +10,17 @@ namespace GameLogic { namespace LevelFileLoader { + /* + These functions will copy data from where the buffer pointer points. + header is the destination where the data will be copied. + size is either the size of the data to be copied (if it is NOT sent by reference). + Or the current index that is being used to parse the entire file (if it is sent by reference) this means you have to increase size with the appropiate size after you have copied. + + */ + void ParseObject(char* buffer, void *header, int size); - void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size); + void ParseObject(char* buffer, ObjectHeader& header, int& size); + void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size); } } diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index a0823247..a000eaed 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -22,8 +22,8 @@ Object::Object() this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + this->newPhysicsState = this->currPhysicsState; } Object::Object(OBJECT_TYPE type) @@ -34,8 +34,8 @@ Object::Object(OBJECT_TYPE type) Oyster::Physics::API::Instance().AddObject(rigidBody); this->type = type; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) @@ -44,8 +44,8 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) this->rigidBody = rigidBody; this->type = type; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + this->newPhysicsState = this->currPhysicsState; } Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -57,8 +57,8 @@ Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE this->type = type; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -71,8 +71,8 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefor this->type = type; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + 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) @@ -86,13 +86,13 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustom this->type = type; this->objectID = GID(); - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + this->newPhysicsState = this->currPhysicsState; } void Object::ApplyLinearImpulse(Oyster::Math::Float3 force) { - setState.ApplyLinearImpulse(force); + newPhysicsState.ApplyLinearImpulse(force); } @@ -118,24 +118,33 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { - Oyster::Math::Float4 axis; - if(setState.GetGravityNormal()!= Float3::null) - { - Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(setState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(setState.GetGravityNormal()), axis); - setState.SetRotation(axis.xyz); - setState.SetAngularMomentum(Float3::null); - Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); - debug += setState.GetGravityNormal(); - } + + - - this->rigidBody->SetState(this->setState); + + + this->rigidBody->SetState(this->newPhysicsState); } // update physic void Object::EndFrame() { - this->getState = this->rigidBody->GetState(); - this->setState = this->getState; + this->currPhysicsState = this->rigidBody->GetState(); + + if(currPhysicsState.GetGravityNormal()!= Float3::null) + { + Oyster::Math::Float4 axis; + Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(currPhysicsState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(currPhysicsState.GetGravityNormal()), axis); + if(axis !=axis) + { + //error + int i =0 ; + } + currPhysicsState.SetRotation(axis.xyz); + currPhysicsState.SetAngularMomentum(Float3::null); + Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); + debug += currPhysicsState.GetGravityNormal(); + } + 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 d3a3690f..c484701c 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -35,8 +35,8 @@ namespace GameLogic Oyster::Physics::ICustomBody* GetRigidBody(); void ApplyLinearImpulse(Oyster::Math::Float3 force); - void BeginFrame(); - void EndFrame(); + virtual void BeginFrame(); + virtual void EndFrame(); void setBeforeCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter)); void setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss)); @@ -49,11 +49,12 @@ namespace GameLogic protected: Oyster::Physics::ICustomBody *rigidBody; - Oyster::Physics::ICustomBody::State setState; - Oyster::Physics::ICustomBody::State getState; + Oyster::Physics::ICustomBody::State newPhysicsState; + Oyster::Physics::ICustomBody::State currPhysicsState; static const Game* gameInstance; - + Oyster::Math::Float3 currLook; + Oyster::Math::Float3 newLook; }; } diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index ea36b284..e9510f57 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -58,6 +58,18 @@ Player::~Player(void) } } +void Player::BeginFrame() +{ + weapon->Update(0.002f); + Object::BeginFrame(); +} + +void Player::EndFrame() +{ + + Object::EndFrame(); +} + void Player::Move(const PLAYER_MOVEMENT &movement) { switch(movement) @@ -86,24 +98,32 @@ void Player::Move(const PLAYER_MOVEMENT &movement) void Player::MoveForward() { - setState.ApplyLinearImpulse(this->lookDir * (2000 * this->gameInstance->GetFrameTime())); + Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + //Oyster::Math::Float3 forward = lookDir; + newPhysicsState.ApplyLinearImpulse(forward * (30000 * this->gameInstance->GetFrameTime())); } void Player::MoveBackwards() { - setState.ApplyLinearImpulse(-this->lookDir * 2000 * this->gameInstance->GetFrameTime()); + Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + //Oyster::Math::Float3 forward = lookDir; + newPhysicsState.ApplyLinearImpulse(-forward * 30000 * this->gameInstance->GetFrameTime()); } void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 r = (-rigidBody->GetGravityNormal()).Cross((Oyster::Math::Float3)this->lookDir); - setState.ApplyLinearImpulse(r * 2000 * this->gameInstance->GetFrameTime()); + Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + //Oyster::Math::Float3 forward = lookDir; + Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); + newPhysicsState.ApplyLinearImpulse(-r * 30000 * this->gameInstance->GetFrameTime()); } void Player::MoveLeft() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 r = -(-rigidBody->GetGravityNormal()).Cross((Oyster::Math::Float3)this->lookDir); //Still get zero - setState.ApplyLinearImpulse(-r * 2000 * this->gameInstance->GetFrameTime()); + Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + //Oyster::Math::Float3 forward = lookDir; + Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero + newPhysicsState.ApplyLinearImpulse(r * 30000 * this->gameInstance->GetFrameTime()); } void Player::UseWeapon(const WEAPON_FIRE &usage) @@ -113,31 +133,32 @@ void Player::UseWeapon(const WEAPON_FIRE &usage) 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.SetCenterPosition(spawnPoint); } -void Player::Rotate(const Oyster::Math3D::Float3 lookDir) +void Player::Rotate(const Oyster::Math3D::Float4 lookDir) { - this->lookDir = lookDir; - - Oyster::Math::Float4 up = -setState.GetGravityNormal(); - Oyster::Math::Float4 pos = setState.GetCenterPosition(); - Oyster::Math::Float4x4 world = Oyster::Math3D::OrientationMatrix_LookAtDirection(lookDir, up.xyz, pos.xyz); - // cant set rotation - //setState.SetOrientation(world); - //this->lookDir = lookDir - up.xyz; - //this->lookDir = lookDir; + Oyster::Math::Float dx = lookDir.w; + if(dx > 0.0f) + { + int i =0 ; + } + Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; + Oyster::Math::Float3 oldOrt = currPhysicsState.GetRotation(); - //this->setState.AddRotation(Oyster::Math::Float4(x, y)); - //this->setState.SetRotation(); + newPhysicsState.SetRotation(oldOrt + deltaAxis); + + this->lookDir = lookDir.xyz; } void Player::Jump() { - + Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + newPhysicsState.ApplyLinearImpulse(up * 30000 * this->gameInstance->GetFrameTime()); } bool Player::IsWalking() @@ -155,11 +176,11 @@ bool Player::IsIdle() Oyster::Math::Float3 Player::GetPosition() const { - return (Oyster::Math::Float3)getState.GetCenterPosition(); + return (Oyster::Math::Float3)currPhysicsState.GetCenterPosition(); } Oyster::Math::Float4x4 Player::GetOrientation() const { - return this->getState.GetOrientation(); + return this->currPhysicsState.GetOrientation(); } Oyster::Math::Float3 Player::GetLookDir() const { @@ -177,5 +198,13 @@ PLAYER_STATE Player::GetState() const void Player::DamageLife(int damage) { this->life -= damage; + this->life = 0; + + if(this->life <= 0) + { + this->life = 0; + playerState = PLAYER_STATE_DEAD; + this->gameInstance->onDisableFnc(this); + } } diff --git a/Code/Game/GameLogic/Player.h b/Code/Game/GameLogic/Player.h index 0df0d040..fddf4b44 100644 --- a/Code/Game/GameLogic/Player.h +++ b/Code/Game/GameLogic/Player.h @@ -48,7 +48,7 @@ namespace GameLogic void Respawn(Oyster::Math::Float3 spawnPoint); - void Rotate(const Oyster::Math3D::Float3 lookDir); + void Rotate(const Oyster::Math3D::Float4 lookDir); /******************************************************** * Collision function for player, this is to be sent to physics through the subscribe function with the rigidbody @@ -71,6 +71,9 @@ namespace GameLogic void DamageLife(int damage); + void BeginFrame(); + void EndFrame(); + private: void Jump(); diff --git a/Code/Game/GameLogic/StaticObject.cpp b/Code/Game/GameLogic/StaticObject.cpp index 21b339be..c007b919 100644 --- a/Code/Game/GameLogic/StaticObject.cpp +++ b/Code/Game/GameLogic/StaticObject.cpp @@ -1,4 +1,5 @@ #include "StaticObject.h" +#include "CollisionManager.h" using namespace GameLogic; @@ -17,7 +18,8 @@ StaticObject::StaticObject(OBJECT_TYPE type) StaticObject::StaticObject(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) :Object(rigidBody,type) { - + this->rigidBody->SetGravity(true); + this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(CollisionManager::IgnoreCollision)); } StaticObject::StaticObject(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) diff --git a/Code/Game/GameLogic/Weapon.cpp b/Code/Game/GameLogic/Weapon.cpp index 942f7074..55296e70 100644 --- a/Code/Game/GameLogic/Weapon.cpp +++ b/Code/Game/GameLogic/Weapon.cpp @@ -137,4 +137,9 @@ void Weapon::SelectAttatchment(int socketID) selectedSocketID = socketID; } +} + +void Weapon::Update(float dt) +{ + selectedAttatchment->Update(dt); } \ No newline at end of file diff --git a/Code/Game/GameLogic/Weapon.h b/Code/Game/GameLogic/Weapon.h index 5138b2ac..8f226f12 100644 --- a/Code/Game/GameLogic/Weapon.h +++ b/Code/Game/GameLogic/Weapon.h @@ -20,6 +20,7 @@ namespace GameLogic ~Weapon(void); void Use(const WEAPON_FIRE &usage, float dt); + void Update(float dt); void AddNewAttatchment(IAttatchment *attatchment, Player *owner); void SwitchAttatchment(IAttatchment *attatchment, int socketID, Player *owner); diff --git a/Code/Game/GameProtocols/PlayerProtocols.h b/Code/Game/GameProtocols/PlayerProtocols.h index 361b8d6e..8517775d 100644 --- a/Code/Game/GameProtocols/PlayerProtocols.h +++ b/Code/Game/GameProtocols/PlayerProtocols.h @@ -69,6 +69,7 @@ namespace GameLogic float lookDirX; float lookDirY; float lookDirZ; + float deltaX; Protocol_PlayerLook() { @@ -78,6 +79,7 @@ namespace GameLogic this->protocol[1].type = Oyster::Network::NetAttributeType_Float; this->protocol[2].type = Oyster::Network::NetAttributeType_Float; this->protocol[3].type = Oyster::Network::NetAttributeType_Float; + this->protocol[4].type = Oyster::Network::NetAttributeType_Float; } Protocol_PlayerLook(Oyster::Network::CustomNetProtocol& p) @@ -85,12 +87,14 @@ namespace GameLogic lookDirX = p[1].value.netFloat; lookDirY = p[2].value.netFloat; lookDirZ = p[3].value.netFloat; + deltaX = p[4].value.netFloat; } const Protocol_PlayerLook& operator=(Oyster::Network::CustomNetProtocol& val) { lookDirX = val[1].value.netFloat; lookDirY = val[2].value.netFloat; lookDirZ = val[3].value.netFloat; + deltaX = val[4].value.netFloat; return *this; } @@ -99,6 +103,8 @@ namespace GameLogic this->protocol[1].value = lookDirX; this->protocol[2].value = lookDirY; this->protocol[3].value = lookDirZ; + this->protocol[4].value = deltaX; + return protocol; } diff --git a/Code/Game/GameServer/GameServer.vcxproj b/Code/Game/GameServer/GameServer.vcxproj index 6c0f3ea9..23bf0eb0 100644 --- a/Code/Game/GameServer/GameServer.vcxproj +++ b/Code/Game/GameServer/GameServer.vcxproj @@ -200,6 +200,9 @@ {f10cbc03-9809-4cba-95d8-327c287b18ee} + + {b1195bb9-b3a5-47f0-906c-8dea384d1520} + diff --git a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp index 495e34c3..27752de4 100644 --- a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp +++ b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp @@ -176,10 +176,11 @@ namespace DanBias } void GameSession::Gameplay_PlayerLookDir ( Protocol_PlayerLook& p, DanBias::GameClient* c ) { - Oyster::Math3D::Float3 lookDir; + Oyster::Math3D::Float4 lookDir; lookDir.x = p.lookDirX; lookDir.y = p.lookDirY; lookDir.z = p.lookDirZ; + lookDir.w = p.deltaX; c->GetPlayer()->Rotate(lookDir); } void GameSession::Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon& p, DanBias::GameClient* c ) @@ -188,7 +189,9 @@ namespace DanBias } void GameSession::Gameplay_PlayerShot ( Protocol_PlayerShot& p, DanBias::GameClient* c ) { - c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_PRIMARY_PRESS); + //c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_PRIMARY_PRESS); + c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_SECONDARY_PRESS); + //c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_PRIMARY_PRESS); } void GameSession::Gameplay_PlayerJump ( Protocol_PlayerJump& p, DanBias::GameClient* c ) { diff --git a/Code/GamePhysics/Implementation/Octree.cpp b/Code/GamePhysics/Implementation/Octree.cpp index b4395516..47bf3e39 100644 --- a/Code/GamePhysics/Implementation/Octree.cpp +++ b/Code/GamePhysics/Implementation/Octree.cpp @@ -40,6 +40,7 @@ void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef) data.next = NULL; data.prev = NULL; data.customBodyRef = customBodyRef; + data.limbo = false; this->mapReferences.insert(std::pair (data.customBodyRef, this->leafData.size())); this->leafData.push_back(data); @@ -64,6 +65,33 @@ void Octree::MoveToUpdateQueue(UniquePointer< ICustomBody > customBodyRef) this->updateQueue.push_back(&this->leafData[this->mapReferences[customBodyRef]]);*/ } +void Octree::MoveToLimbo(const ICustomBody* customBodyRef) +{ + auto object = this->mapReferences.find(customBodyRef); + + unsigned int tempRef = object->second; + + this->leafData[tempRef].limbo = true; +} + +bool Octree::IsInLimbo(const ICustomBody* customBodyRef) +{ + auto object = this->mapReferences.find(customBodyRef); + + unsigned int tempRef = object->second; + + return this->leafData[tempRef].limbo; +} + +void Octree::ReleaseFromLimbo(const ICustomBody* customBodyRef) +{ + auto object = this->mapReferences.find(customBodyRef); + + unsigned int tempRef = object->second; + + this->leafData[tempRef].limbo = false; +} + void Octree::DestroyObject(UniquePointer< ICustomBody > customBodyRef) { std::map::iterator it = this->mapReferences.find(customBodyRef); @@ -86,7 +114,7 @@ std::vector& Octree::Sample(ICustomBody* customBodyRef, std::vecto for(unsigned int i = 0; ileafData.size(); i++) { - if(tempRef != i) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) + if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) { updateList.push_back(this->leafData[i].customBodyRef); } @@ -99,7 +127,7 @@ std::vector& Octree::Sample(const Oyster::Collision3D::ICollideabl { for(unsigned int i = 0; ileafData.size(); i++) { - if(this->leafData[i].container.Intersects(collideable)) + if(!this->leafData[i].limbo && this->leafData[i].container.Intersects(collideable)) { updateList.push_back(this->leafData[i].customBodyRef); } @@ -121,7 +149,7 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction ) for(unsigned int i = 0; ileafData.size(); i++) { - if(tempRef != i) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) + if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) { hitAction(*this, tempRef, i); } @@ -132,7 +160,7 @@ void Octree::Visit(const Oyster::Collision3D::ICollideable& collideable, void* a { for(unsigned int i = 0; ileafData.size(); i++) { - if(collideable.Intersects(this->leafData[i].container)) + if(!this->leafData[i].limbo && collideable.Intersects(this->leafData[i].container)) { hitAction( this->GetCustomBody(i), args ); } diff --git a/Code/GamePhysics/Implementation/Octree.h b/Code/GamePhysics/Implementation/Octree.h index 50b9569a..573738f2 100644 --- a/Code/GamePhysics/Implementation/Octree.h +++ b/Code/GamePhysics/Implementation/Octree.h @@ -29,6 +29,8 @@ namespace Oyster ::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef; + bool limbo; + unsigned int queueRef; }; @@ -48,6 +50,10 @@ namespace Oyster void MoveToUpdateQueue(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef); + void MoveToLimbo(const ICustomBody* customBodyRef); + bool IsInLimbo(const ICustomBody* customBodyRef); + void ReleaseFromLimbo(const ICustomBody* customBodyRef); + void DestroyObject(::Utility::DynamicMemory::UniquePointer< ICustomBody > customBodyRef); std::vector& Sample(ICustomBody* customBodyRef, std::vector& updateList); @@ -66,6 +72,7 @@ namespace Oyster private: std::vector < Data > leafData; std::vector < Data* > updateQueue; + std::vector < Data* > limbo; std::map< const ICustomBody*, unsigned int > mapReferences; diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 12c46cd5..614014e2 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -60,6 +60,8 @@ namespace return; } + // calculate and store time interpolation value, for later rebound. + proto->SetTimeOfContact( worldPointOfContact ); // bounce Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), @@ -78,10 +80,14 @@ namespace deuterState.GetMass(), deuterG_Magnitude ); Float4 bounce = Average( bounceD, bounceP ); + + Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal, + Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), + Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); - protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); + protoState.ApplyImpulse( bounce.xyz - friction.xyz, worldPointOfContact.xyz, normal.xyz ); proto->SetState( protoState ); Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); @@ -233,17 +239,16 @@ void API_Impl::Update() bool API_Impl::IsInLimbo( const ICustomBody* objRef ) { - //! @todo TODO: implement stub - return true; + return this->worldScene.IsInLimbo( objRef ); } void API_Impl::MoveToLimbo( const ICustomBody* objRef ) { - /** @todo TODO: Fix this function.*/ + this->worldScene.MoveToLimbo( objRef ); } void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef ) { - /** @todo TODO: Fix this function.*/ + this->worldScene.ReleaseFromLimbo( objRef ); } void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer handle ) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index a2871229..034cedea 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -49,23 +49,38 @@ SimpleRigidBody::SimpleRigidBody() this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onMovement = Default::EventAction_Move; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = this->isForwarded = false; } SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) -{ - //this->rigid.SetRotation( desc.rotation ); - this->rigid.centerPos = desc.centerPosition; +{ + this->rigid = RigidBody(); + this->rigid.SetRotation( desc.rotation ); + this->rigid.centerPos = desc.centerPosition; this->rigid.SetSize( desc.size ); + this->rigid.restitutionCoeff = desc.restitutionCoeff; + this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static; + this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic; this->rigid.SetMass_KeepMomentum( desc.mass ); this->rigid.SetMomentOfInertia_KeepMomentum( desc.inertiaTensor ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; + this->deltaPos = Float4::null; + this->deltaAxis = Float4::null; this->gravityNormal = Float3::null; + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + if( desc.subscription_onCollision ) { this->onCollision = desc.subscription_onCollision; @@ -198,6 +213,26 @@ bool SimpleRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointO return object.Intersects( Box(this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize()), worldPointOfContact ); } +void SimpleRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) +{ + Point pointOfContact = Point( worldPointOfContact ); + Box start = Box(); + { + start.rotation = RotationMatrix( this->collisionRebound.previousSpatial.axis ); + start.center = this->collisionRebound.previousSpatial.center; + start.boundingOffset = this->collisionRebound.previousSpatial.reach; + } + Box end = Box(); + { + end.rotation = RotationMatrix( this->rigid.axis ); + end.center = this->rigid.centerPos; + end.boundingOffset = this->rigid.boundingReach; + } + Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); + + this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); +} + Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const { return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() ); @@ -290,21 +325,49 @@ void * SimpleRigidBody::GetCustomTag() const // return this->rigid.GetLinearVelocity(); //} - UpdateState SimpleRigidBody::Update( Float timeStepLength ) { - if( this->isForwarded ) + if( this->collisionRebound.timeOfContact < 1.0f ) + { // Rebound if needed + this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); + this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); + this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); + this->collisionRebound.timeOfContact = 1.0f; + } + + // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) + Float4 temp; + ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); + this->rigid.axis -= ((2.0f * pi) * temp).xyz; + + // Update rebound data + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + + // Check if this is close enough to be set resting + temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); + if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) { - this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; - this->isForwarded = false; + unsigned char resting = 0; + if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Linear = Float3::null; + resting = 1; + } + if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Angular = Float3::null; + ++resting; + } + if( resting == 2 ) + { + this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null; + return UpdateState_resting; + } } this->rigid.Update_LeapFrog( timeStepLength ); - - //! @todo TODO: compare previous and new state and return result - //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; return UpdateState_altered; } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 9e61cee3..1811c911 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -30,6 +30,8 @@ namespace Oyster { namespace Physics bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; + void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); + ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; @@ -65,9 +67,17 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; + + struct + { + struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; + ::Oyster::Math::Float timeOfContact; + } collisionRebound; + EventAction_BeforeCollisionResponse onCollision; EventAction_AfterCollisionResponse onCollisionResponse; EventAction_Move onMovement; + Octree *scene; void *customTag; bool ignoreGravity, isForwarded; diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index f6f89c64..6b4cd4ed 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -11,11 +11,17 @@ using namespace ::Utility::Value; SphericalRigidBody::SphericalRigidBody() { this->rigid = RigidBody(); - this->rigid.SetMass_KeepMomentum( 10.0f ); + this->rigid.SetMass_KeepMomentum( 16.0f ); this->gravityNormal = Float3::null; this->onCollision = Default::EventAction_BeforeCollisionResponse; this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; this->onMovement = Default::EventAction_Move; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = this->isForwarded = false; @@ -23,17 +29,25 @@ SphericalRigidBody::SphericalRigidBody() SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc ) { - this->rigid = RigidBody(); - //this->rigid.SetRotation( desc.rotation ); - this->rigid.centerPos = desc.centerPosition; - this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f ); + this->rigid = RigidBody(); + this->rigid.SetRotation( desc.rotation ); + this->rigid.centerPos = desc.centerPosition; + this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f ); + this->rigid.restitutionCoeff = desc.restitutionCoeff; + this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static; + this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic; this->rigid.SetMass_KeepMomentum( desc.mass ); this->rigid.SetMomentOfInertia_KeepMomentum( MomentOfInertia::Sphere(desc.mass, desc.radius) ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; + this->deltaPos = Float4::null; + this->deltaAxis = Float4::null; this->gravityNormal = Float3::null; + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; + if( desc.subscription_onCollision ) { this->onCollision = desc.subscription_onCollision; @@ -64,6 +78,11 @@ SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &des this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = desc.ignoreGravity; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; } SphericalRigidBody::~SphericalRigidBody() {} @@ -165,6 +184,17 @@ bool SphericalRigidBody::Intersects( const ICustomBody &object, Float4 &worldPoi return object.Intersects( Sphere(this->rigid.centerPos, this->rigid.boundingReach.x), worldPointOfContact ); } +void SphericalRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) +{ + Point pointOfContact = Point( worldPointOfContact ); + Sphere start = Sphere( this->collisionRebound.previousSpatial.center, this->collisionRebound.previousSpatial.reach.x ); + Sphere end = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); + + Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); + + this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); +} + Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const { return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); @@ -219,18 +249,47 @@ void * SphericalRigidBody::GetCustomTag() const UpdateState SphericalRigidBody::Update( Float timeStepLength ) { - if( this->isForwarded ) + if( this->collisionRebound.timeOfContact < 1.0f ) + { // Rebound if needed + this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); + this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); + this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); + this->collisionRebound.timeOfContact = 1.0f; + } + + // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) + Float4 temp; + ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); + this->rigid.axis -= ((2.0f * pi) * temp).xyz; + + // Update rebound data + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + + // Check if this is close enough to be set resting + temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); + if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) { - this->rigid.Move( this->deltaPos.xyz, this->deltaAxis.xyz ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; - this->isForwarded = false; + unsigned char resting = 0; + if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Linear = Float3::null; + resting = 1; + } + if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) + { + this->rigid.momentum_Angular = Float3::null; + ++resting; + } + if( resting == 2 ) + { + this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null; + return UpdateState_resting; + } } this->rigid.Update_LeapFrog( timeStepLength ); - - // compare previous and new state and return result - //return this->current == this->previous ? UpdateState_resting : UpdateState_altered; return UpdateState_altered; } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h index 390b7171..c2dc8131 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.h +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Physics bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; + void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); + ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; @@ -66,6 +68,13 @@ namespace Oyster { namespace Physics ::Oyster::Physics3D::RigidBody rigid; ::Oyster::Math::Float4 deltaPos, deltaAxis; ::Oyster::Math::Float3 gravityNormal; + + struct + { + struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; + ::Oyster::Math::Float timeOfContact; + } collisionRebound; + EventAction_BeforeCollisionResponse onCollision; EventAction_AfterCollisionResponse onCollisionResponse; EventAction_Move onMovement; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 080b8d30..f636bb73 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -322,6 +322,11 @@ namespace Oyster ********************************************************/ virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; + /******************************************************** + * Sets how far back it needs to be interpolated to not be overlapping worldPointOfContact. + ********************************************************/ + virtual void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ) = 0; + /******************************************************** * Required by Engine's Collision Search. * @param targetMem: Provided memory that written into and then returned. diff --git a/Code/GamePhysics/PhysicsFormula-Impl.h b/Code/GamePhysics/PhysicsFormula-Impl.h index 323fd732..189691f6 100644 --- a/Code/GamePhysics/PhysicsFormula-Impl.h +++ b/Code/GamePhysics/PhysicsFormula-Impl.h @@ -48,26 +48,32 @@ namespace Oyster { namespace Physics { namespace Formula // Relative momentum after normal impulse ::Oyster::Math::Float4 relativeMomentum = momB - momA; - ::Oyster::Math::Float4 tanFriction = relativeMomentum - relativeMomentum.Dot( iN )*iN; - tanFriction.Normalize(); + ::Oyster::Math::Float4 tanFriction = relativeMomentum - relativeMomentum.Dot( iN ) * iN; - ::Oyster::Math::Float magnitudeFriction = -relativeMomentum.Dot( tanFriction ); - magnitudeFriction = magnitudeFriction*mA*mB/( mA + mB ); + if( tanFriction.Dot(tanFriction) > 0.0f ) + { // no friction if moving directly into surface, or not at all. + tanFriction.Normalize(); - ::Oyster::Math::Float mu = 0.5f*( sFA + sFB ); + ::Oyster::Math::Float magnitudeFriction = -relativeMomentum.Dot( tanFriction ); + magnitudeFriction = magnitudeFriction * mA * mB / ( mA + mB ); + + ::Oyster::Math::Float mu = 0.5f * ( sFA + sFB ); - ::Oyster::Math::Float4 frictionImpulse; - if( abs(magnitudeFriction) < i*mu ) - { - frictionImpulse = magnitudeFriction*tanFriction; + ::Oyster::Math::Float4 frictionImpulse; + if( abs(magnitudeFriction) < i * mu ) + { + frictionImpulse = magnitudeFriction * tanFriction; + } + else + { + ::Oyster::Math::Float dynamicFriction = 0.5f * ( dFA + dFB ); + frictionImpulse = ( -i * dynamicFriction ) * tanFriction; + } + + return ( 1 / mA ) * frictionImpulse; } else - { - ::Oyster::Math::Float dynamicFriction = 0.5f*( dFA + dFB ); - frictionImpulse = -i*tanFriction*dynamicFriction; - } - - return ( 1 / mA )*frictionImpulse; + return ::Oyster::Math::Float4::null; } } diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index af2fb91c..311b81f8 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -12,7 +12,7 @@ namespace Oyster { inline SimpleBodyDescription::SimpleBodyDescription() { - this->rotation = ::Oyster::Math::Float4x4::identity; + this->rotation = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null; this->size = ::Oyster::Math::Float3( 1.0f ); this->mass = 6.0f; @@ -28,7 +28,7 @@ namespace Oyster inline SphericalBodyDescription::SphericalBodyDescription() { - this->rotation = ::Oyster::Math::Float4x4::identity; + this->rotation = ::Oyster::Math::Float3::null; this->centerPosition = ::Oyster::Math::Float3::null; this->radius = 0.5f; this->mass = 10.0f; diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index aef157a8..61a0569f 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -11,7 +11,7 @@ namespace Oyster { namespace Physics { struct SimpleBodyDescription { - ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 rotation; ::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float3 size; ::Oyster::Math::Float mass; @@ -29,7 +29,7 @@ namespace Oyster { namespace Physics struct SphericalBodyDescription { - ::Oyster::Math::Float4x4 rotation; + ::Oyster::Math::Float3 rotation; ::Oyster::Math::Float3 centerPosition; ::Oyster::Math::Float radius; ::Oyster::Math::Float mass; diff --git a/Code/Misc/Utilities.h b/Code/Misc/Utilities.h index 22049ac0..c259a845 100644 --- a/Code/Misc/Utilities.h +++ b/Code/Misc/Utilities.h @@ -315,6 +315,14 @@ namespace Utility { using ::std::numeric_limits; + template + inline bool Within( const ValueType &value, const ValueType &lower, const ValueType &upper ) + { + if( value < lower ) return false; + if( value > upper ) return false; + return true; + } + template inline ValueType Abs( const ValueType &value ) { return value < 0 ? value * -1 : value; } diff --git a/Code/Network/NetworkAPI/NetworkServer.h b/Code/Network/NetworkAPI/NetworkServer.h index 01b9337e..1e3ddd21 100644 --- a/Code/Network/NetworkAPI/NetworkServer.h +++ b/Code/Network/NetworkAPI/NetworkServer.h @@ -84,8 +84,8 @@ namespace Oyster */ std::string GetLanAddress(); - /** - * + /** Returns the port the server is listening on. + * @return Returns the port the server has been initiated with. */ int NetworkServer::GetPort(); diff --git a/Code/OysterMath/LinearMath.h b/Code/OysterMath/LinearMath.h index dce7a026..9b21fc02 100644 --- a/Code/OysterMath/LinearMath.h +++ b/Code/OysterMath/LinearMath.h @@ -11,27 +11,6 @@ #include "Quaternion.h" #include -namespace std -{ - template - inline ::LinearAlgebra::Vector2 asin( const ::LinearAlgebra::Vector2 &vec ) - { - return ::LinearAlgebra::Vector2( asin(vec.x), asin(vec.y) ); - } - - template - inline ::LinearAlgebra::Vector3 asin( const ::LinearAlgebra::Vector3 &vec ) - { - return ::LinearAlgebra::Vector3( asin(vec.x), asin(vec.y), asin(vec.z) ); - } - - template - inline ::LinearAlgebra::Vector4 asin( const ::LinearAlgebra::Vector4 &vec ) - { - return ::LinearAlgebra::Vector4( asin(vec.x), asin(vec.y), asin(vec.z), asin(vec.w) ); - } -} - // x2 template @@ -112,6 +91,69 @@ inline ::LinearAlgebra::Vector4 operator * ( const ::LinearAlgebra:: (vector.x * matrix.m14) + (vector.y * matrix.m24) + (vector.z * matrix.m34) + (vector.w * matrix.m44) ); } +namespace std +{ + template + inline ::LinearAlgebra::Vector2 asin( const ::LinearAlgebra::Vector2 &vec ) + { + return ::LinearAlgebra::Vector2( asin(vec.x), asin(vec.y) ); + } + + template + inline ::LinearAlgebra::Vector3 asin( const ::LinearAlgebra::Vector3 &vec ) + { + return ::LinearAlgebra::Vector3( asin(vec.x), asin(vec.y), asin(vec.z) ); + } + + template + inline ::LinearAlgebra::Vector4 asin( const ::LinearAlgebra::Vector4 &vec ) + { + return ::LinearAlgebra::Vector4( asin(vec.x), asin(vec.y), asin(vec.z), asin(vec.w) ); + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector2 modf( const ::LinearAlgebra::Vector2 &vec, ::LinearAlgebra::Vector2 &numerator ) + { + ::LinearAlgebra::Vector2 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + return denominator; + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector3 modf( const ::LinearAlgebra::Vector3 &vec, ::LinearAlgebra::Vector3 &numerator ) + { + ::LinearAlgebra::Vector3 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + denominator.z = (ScalarType)modf( vec.z, &numerator.z ); + return denominator; + } + + /******************************************************************* + * @param numerator of the vector vec + * @return the denomiator of the vector vec. + *******************************************************************/ + template + inline ::LinearAlgebra::Vector4 modf( const ::LinearAlgebra::Vector4 &vec, ::LinearAlgebra::Vector4 &numerator ) + { + ::LinearAlgebra::Vector4 denominator; + denominator.x = (ScalarType)modf( vec.x, &numerator.x ); + denominator.y = (ScalarType)modf( vec.y, &numerator.y ); + denominator.z = (ScalarType)modf( vec.z, &numerator.z ); + denominator.w = (ScalarType)modf( vec.w, &numerator.w ); + return denominator; + } +} + namespace LinearAlgebra { // Creates a solution matrix for 'outī= 'targetMem' * 'in'. @@ -752,7 +794,7 @@ namespace LinearAlgebra3D { ::LinearAlgebra::Vector4 worldStartNormal( WorldAxisOf(Rotation(startAngularAxis.xyz), localStartNormal.xyz), (ScalarType)0 ); targetMem = ::LinearAlgebra::Vector4( worldStartNormal.xyz.Cross(worldEndNormal.xyz), (ScalarType)0); - targetMem *= (ScalarType)::std::acos( worldStartNormal.Dot(worldEndNormal) ); + targetMem *= (ScalarType)::std::acos( ::Utility::Value::Clamp(worldStartNormal.Dot(worldEndNormal), (ScalarType)0, (ScalarType)1) ); return targetMem += startAngularAxis; } @@ -795,11 +837,42 @@ namespace LinearAlgebra3D } template - ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + inline ::LinearAlgebra::Matrix4x4 & InterpolateRotation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) { targetMem.v[0] = ::LinearAlgebra::Nlerp( start.v[0], end.v[0], t ); targetMem.v[1] = ::LinearAlgebra::Nlerp( start.v[1], end.v[1], t ); targetMem.v[2] = ::LinearAlgebra::Nlerp( start.v[2], end.v[2], t ); + return targetMem; + } + + template + inline ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingNonRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + InterpolateRotation_UsingNonRigidNlerp( start, end, t, targetMem ); + targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t ); + return targetMem; + } + + template + ::LinearAlgebra::Matrix4x4 & InterpolateRotation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + // Nlerp y axis + targetMem.v[1] = ::LinearAlgebra::Nlerp( start.v[1], end.v[1], t ); + + // Lerp z axis and orthogonolize against y axis + targetMem.v[2] = ::LinearAlgebra::Lerp( start.v[2], end.v[2], t ); + targetMem.v[2] -= targetMem.v[2].Dot(targetMem.v[1]) * targetMem.v[1]; + targetMem.v[2].Normalize(); + + // Cross product x axis from y and z + targetMem.v[0].xyz = targetMem.v[1].xyz.Cross(targetMem.v[2].xyz); + return targetMem; + } + + template + inline ::LinearAlgebra::Matrix4x4 & InterpolateOrientation_UsingRigidNlerp( const ::LinearAlgebra::Matrix4x4 &start, const ::LinearAlgebra::Matrix4x4 &end, ScalarType t, ::LinearAlgebra::Matrix4x4 &targetMem ) + { + InterpolateRotation_UsingRigidNlerp( start, end, t, targetMem ); targetMem.v[3] = ::LinearAlgebra::Lerp( start.v[3], end.v[3], t ); return targetMem; } diff --git a/Code/OysterMath/OysterMath.h b/Code/OysterMath/OysterMath.h index 7e123183..23ee06db 100644 --- a/Code/OysterMath/OysterMath.h +++ b/Code/OysterMath/OysterMath.h @@ -322,7 +322,10 @@ namespace Oyster { namespace Math3D //! Oyster's native math library specialized using ::LinearAlgebra3D::SnapAxisYToNormal_UsingNlerp; using ::LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp; + using ::LinearAlgebra3D::InterpolateRotation_UsingNonRigidNlerp; + using ::LinearAlgebra3D::InterpolateRotation_UsingRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingNonRigidNlerp; + using ::LinearAlgebra3D::InterpolateOrientation_UsingRigidNlerp; using ::LinearAlgebra3D::InterpolateOrientation_UsingSlerp; using ::LinearAlgebra3D::SnapAngularAxis; } } diff --git a/Code/OysterPhysics3D/Box.cpp b/Code/OysterPhysics3D/Box.cpp index f55415b7..56950e24 100644 --- a/Code/OysterPhysics3D/Box.cpp +++ b/Code/OysterPhysics3D/Box.cpp @@ -92,4 +92,27 @@ bool Box::Contains( const ICollideable &target ) const //case Type_frustrum: return false; // TODO: default: return false; } -} \ No newline at end of file +} + +Float Box::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + +namespace Oyster { namespace Math +{ + Box & Nlerp( const Box &start, const Box &end, Float t, Box &targetMem ) + { + InterpolateRotation_UsingRigidNlerp( start.rotation, end.rotation, t, targetMem.rotation ); + targetMem.center = Lerp( start.center, end.center, t ); + targetMem.boundingOffset = Lerp( start.boundingOffset, end.boundingOffset, t ); + return targetMem; + } +} } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Box.h b/Code/OysterPhysics3D/Box.h index f98ae362..553037be 100644 --- a/Code/OysterPhysics3D/Box.h +++ b/Code/OysterPhysics3D/Box.h @@ -9,35 +9,48 @@ #include "OysterMath.h" #include "ICollideable.h" -namespace Oyster { namespace Collision3D +namespace Oyster { - class Box : public ICollideable + namespace Collision3D { - public: - union + class Box : public ICollideable { - struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; }; - struct + public: + union { - ::Oyster::Math::Float4 xAxis; - ::Oyster::Math::Float4 yAxis; - ::Oyster::Math::Float4 zAxis; + struct{ ::Oyster::Math::Float4x4 rotation; ::Oyster::Math::Float4 center, boundingOffset; }; + struct + { + ::Oyster::Math::Float4 xAxis; + ::Oyster::Math::Float4 yAxis; + ::Oyster::Math::Float4 zAxis; + }; + char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)]; }; - char byte[sizeof(::Oyster::Math::Float4x4) + 2*sizeof(::Oyster::Math::Float4)]; + + Box( ); + Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &size ); + Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float4 &worldPos, const ::Oyster::Math::Float4 &size ); + virtual ~Box( ); + + Box & operator = ( const Box &box ); + + virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; + bool Intersects( const ICollideable &target ) const; + bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; + bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; + } - Box( ); - Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &size ); - Box( const ::Oyster::Math::Float4x4 &rotation, const ::Oyster::Math::Float4 &worldPos, const ::Oyster::Math::Float4 &size ); - virtual ~Box( ); - - Box & operator = ( const Box &box ); - - virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; - bool Intersects( const ICollideable &target ) const; - bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Contains( const ICollideable &target ) const; - }; -} } + namespace Math + { + /******************************************************************** + * Normalized Linear Interpolation + ********************************************************************/ + ::Oyster::Collision3D::Box & Nlerp( const ::Oyster::Collision3D::Box &start, const ::Oyster::Collision3D::Box &end, ::Oyster::Math::Float t, ::Oyster::Collision3D::Box &targetMem = ::Oyster::Collision3D::Box() ); + } +} #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/BoxAxisAligned.cpp b/Code/OysterPhysics3D/BoxAxisAligned.cpp index bd10016f..8c934617 100644 --- a/Code/OysterPhysics3D/BoxAxisAligned.cpp +++ b/Code/OysterPhysics3D/BoxAxisAligned.cpp @@ -76,4 +76,16 @@ bool BoxAxisAligned::Contains( const ICollideable &target ) const //default: return false; //} return false; +} + +Float BoxAxisAligned::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/BoxAxisAligned.h b/Code/OysterPhysics3D/BoxAxisAligned.h index 2ff39463..9ad55165 100644 --- a/Code/OysterPhysics3D/BoxAxisAligned.h +++ b/Code/OysterPhysics3D/BoxAxisAligned.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Frustrum.cpp b/Code/OysterPhysics3D/Frustrum.cpp index ce2c5256..ea7a49d2 100644 --- a/Code/OysterPhysics3D/Frustrum.cpp +++ b/Code/OysterPhysics3D/Frustrum.cpp @@ -15,37 +15,37 @@ namespace PrivateStatic Float4x4 m = vp.GetTranspose(); // left - lp.normal = m.v[3].xyz + m.v[0].xyz; + lp.normal = Float4(m.v[3].xyz + m.v[0].xyz,0); lp.phasing = lp.normal.GetMagnitude(); lp.normal /= lp.phasing; lp.phasing = (m.v[3].w + m.v[0].w) / lp.phasing; // right - rp.normal = m.v[3].xyz - m.v[0].xyz; + rp.normal = Float4(m.v[3].xyz - m.v[0].xyz,0); rp.phasing = rp.normal.GetMagnitude(); rp.normal /= rp.phasing; rp.phasing = (m.v[3].w - m.v[0].w) / rp.phasing; // bottom - bp.normal = m.v[3].xyz + m.v[1].xyz; + bp.normal = Float4(m.v[3].xyz + m.v[1].xyz,0); bp.phasing = bp.normal.GetMagnitude(); bp.normal /= bp.phasing; bp.phasing = (m.v[3].w + m.v[1].w) / bp.phasing; // top - tp.normal = m.v[3].xyz - m.v[1].xyz; + tp.normal = Float4(m.v[3].xyz - m.v[1].xyz,0); tp.phasing = tp.normal.GetMagnitude(); tp.normal /= tp.phasing; tp.phasing = (m.v[3].w - m.v[1].w) / tp.phasing; // near leftHanded DirectX - np.normal = m.v[2].xyz; + np.normal = Float4(m.v[2].xyz,0); np.phasing = np.normal.GetMagnitude(); np.normal /= np.phasing; np.phasing = m.v[2].w / np.phasing; // far lefthanded - fp.normal = m.v[3].xyz - m.v[2].xyz; + fp.normal = Float4(m.v[3].xyz - m.v[2].xyz,0); fp.phasing = fp.normal.GetMagnitude(); fp.normal /= fp.phasing; fp.phasing = (m.v[3].w - m.v[2].w) / fp.phasing; @@ -243,6 +243,18 @@ bool Frustrum::Contains( const ICollideable &target ) const } } +Float Frustrum::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + ::Oyster::Math::Float3 Frustrum::ExtractForwad() { return this->bottomPlane.normal.xyz; diff --git a/Code/OysterPhysics3D/Frustrum.h b/Code/OysterPhysics3D/Frustrum.h index ae0f086c..0c4cc04f 100644 --- a/Code/OysterPhysics3D/Frustrum.h +++ b/Code/OysterPhysics3D/Frustrum.h @@ -42,6 +42,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target, Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; + ::Oyster::Math::Float3 ExtractForwad(); }; diff --git a/Code/OysterPhysics3D/ICollideable.h b/Code/OysterPhysics3D/ICollideable.h index b3f61671..3e63200e 100644 --- a/Code/OysterPhysics3D/ICollideable.h +++ b/Code/OysterPhysics3D/ICollideable.h @@ -38,6 +38,8 @@ namespace Oyster { namespace Collision3D //! Contains a collection of 3D shapes virtual bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; virtual bool Intersects( const ICollideable &target ) const = 0; virtual bool Contains( const ICollideable &target ) const = 0; + + virtual ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const = 0; }; } } #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/Line.cpp b/Code/OysterPhysics3D/Line.cpp index cebceaff..fc81791d 100644 --- a/Code/OysterPhysics3D/Line.cpp +++ b/Code/OysterPhysics3D/Line.cpp @@ -76,3 +76,15 @@ bool Line::Intersects( const ICollideable &target, Float4 &worldPointOfContact ) bool Line::Contains( const ICollideable &target ) const { /* TODO: : */ return false; } + +Float Line::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } +} \ No newline at end of file diff --git a/Code/OysterPhysics3D/Line.h b/Code/OysterPhysics3D/Line.h index 2e6d2d55..a305622f 100644 --- a/Code/OysterPhysics3D/Line.h +++ b/Code/OysterPhysics3D/Line.h @@ -32,6 +32,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/OysterCollision3D.cpp b/Code/OysterPhysics3D/OysterCollision3D.cpp index 89b3af8a..41e11875 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.cpp +++ b/Code/OysterPhysics3D/OysterCollision3D.cpp @@ -1061,4 +1061,47 @@ namespace Oyster { namespace Collision3D { namespace Utility return container.normal == -plane.normal; return false; } + + Float TimeOfContact( const Sphere &protoStart, const Sphere &protoEnd, const Point &deuter ) + { // Bisection with 5 levels of detail + Float t = 0.5f, + d = 0.25f; + Sphere s; + for( int i = 0; i < 5; ++i ) + { + Nlerp( protoStart, protoEnd, t, s ); + if( Intersect(s, deuter) ) + { + t -= d; + } + else + { + t += d; + } + d *= 0.5f; + } + return t; + } + + Float TimeOfContact( const Box &protoStart, const Box &protoEnd, const Point &deuter ) + { // Bisection with 5 levels of detail + Float t = 0.5f, + d = 0.25f; + Box b; + for( int i = 0; i < 5; ++i ) + { + Nlerp( protoStart, protoEnd, t, b ); + if( Intersect(b, deuter) ) + { + t -= d; + } + else + { + t += d; + } + d *= 0.5f; + } + return t; + } + } } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/OysterCollision3D.h b/Code/OysterPhysics3D/OysterCollision3D.h index 20a55a18..83a6239e 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.h +++ b/Code/OysterPhysics3D/OysterCollision3D.h @@ -121,6 +121,9 @@ namespace Oyster { namespace Collision3D { namespace Utility // bool Contains( const Frustrum &container, const BoxAxisAligned &box ); // bool Contains( const Frustrum &container, const Box &box ); // bool Contains( const Frustrum &container, const Frustrum &frustrum ); + + ::Oyster::Math::Float TimeOfContact( const Sphere &protoStart, const Sphere &protoEnd, const Point &deuter ); + ::Oyster::Math::Float TimeOfContact( const Box &protoStart, const Box &protoEnd, const Point &deuter ); } } } #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters index da336ce5..f6b6d934 100644 --- a/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters +++ b/Code/OysterPhysics3D/OysterPhysics3D.vcxproj.filters @@ -27,9 +27,6 @@ - - Header Files\Collision - Header Files\Collision @@ -81,6 +78,9 @@ Header Files\Physics + + Header Files\Collision + diff --git a/Code/OysterPhysics3D/Plane.cpp b/Code/OysterPhysics3D/Plane.cpp index 59ffbc47..2923a802 100644 --- a/Code/OysterPhysics3D/Plane.cpp +++ b/Code/OysterPhysics3D/Plane.cpp @@ -83,4 +83,16 @@ bool Plane::Contains( const ICollideable &target ) const //case Type_triangle: return false; // TODO: default: return false; } +} + +Float Plane::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Plane.h b/Code/OysterPhysics3D/Plane.h index f148ed8e..a66e7f3b 100644 --- a/Code/OysterPhysics3D/Plane.h +++ b/Code/OysterPhysics3D/Plane.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Point.cpp b/Code/OysterPhysics3D/Point.cpp index 788ab32d..dd879e27 100644 --- a/Code/OysterPhysics3D/Point.cpp +++ b/Code/OysterPhysics3D/Point.cpp @@ -81,4 +81,18 @@ bool Point::Contains( const ICollideable &target ) const case Type_point: return Utility::Intersect( *this, (const Point&)target ); default: return false; } +} + +Float Point::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_sphere: return Utility::TimeOfContact( (const Sphere&)deuterStart, (const Sphere&)deuterEnd, *this ); + case Type_box: return Utility::TimeOfContact( (const Box&)deuterStart, (const Box&)deuterEnd, *this ); + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Point.h b/Code/OysterPhysics3D/Point.h index 60486373..15abc488 100644 --- a/Code/OysterPhysics3D/Point.h +++ b/Code/OysterPhysics3D/Point.h @@ -31,6 +31,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/Ray.cpp b/Code/OysterPhysics3D/Ray.cpp index e7f21de8..5e58d14b 100644 --- a/Code/OysterPhysics3D/Ray.cpp +++ b/Code/OysterPhysics3D/Ray.cpp @@ -92,4 +92,16 @@ bool Ray::Contains( const ICollideable &target ) const case Type_ray: return Utility::Contains( *this, (const Ray&)target ); default: return false; } +} + +Float Ray::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { // TODO: more to implement + case Type_universe: return 0.0f; + default: return 1.0f; + } } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Ray.h b/Code/OysterPhysics3D/Ray.h index a85580b3..cd797539 100644 --- a/Code/OysterPhysics3D/Ray.h +++ b/Code/OysterPhysics3D/Ray.h @@ -39,6 +39,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } } diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index f053e8dd..ca6dcdec 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -49,13 +49,13 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) { // by Dan Andersson: Euler leap frog update when Runga Kutta is not needed // updating the linear + //Decrease momentum with 1% as "fall-off" + //! HACK: @todo Add real solution with fluid drag + this->momentum_Linear = this->momentum_Linear*0.9999f; + this->momentum_Angular = this->momentum_Angular*0.9999f; + // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G - Float3 deltaPos = ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); - if( deltaPos.GetLength() < 0.001f ) - { - deltaPos = Float3::null; - } - this->centerPos += deltaPos; + this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H @@ -181,6 +181,12 @@ void RigidBody::SetMass_KeepMomentum( const Float &m ) } } +void RigidBody::SetRotation( const Float3 &axis ) +{ // by Dan Andersson + this->axis = axis; + this->rotation = Rotation( this->axis ); +} + void RigidBody::SetMomentum_Linear( const Float3 &worldG, const Float3 &atWorldPos ) { // by Dan Andersson Float3 worldOffset = atWorldPos - this->centerPos; diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h index c666662a..f7aebd22 100644 --- a/Code/OysterPhysics3D/RigidBody.h +++ b/Code/OysterPhysics3D/RigidBody.h @@ -64,7 +64,7 @@ namespace Oyster { namespace Physics3D void SetMass_KeepMomentum( const ::Oyster::Math::Float &m ); //void SetOrientation( const ::Oyster::Math::Float4x4 &o ); - //void SetRotation( const ::Oyster::Math::Float4x4 &r ); + void SetRotation( const ::Oyster::Math::Float3 &axis ); void SetSize( const ::Oyster::Math::Float3 &widthHeight ); void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos ); diff --git a/Code/OysterPhysics3D/Sphere.cpp b/Code/OysterPhysics3D/Sphere.cpp index c402b2ef..86230508 100644 --- a/Code/OysterPhysics3D/Sphere.cpp +++ b/Code/OysterPhysics3D/Sphere.cpp @@ -86,4 +86,30 @@ bool Sphere::Contains( const ICollideable &target ) const //case Type_frustrum: return false; // TODO: default: return false; } -} \ No newline at end of file +} + +Float Sphere::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + if( deuterStart.type != deuterEnd.type ) + return -1.0f; + + switch( deuterStart.type ) + { + //case Type_point: // not implemented + //case Type_sphere: // not implemented + //case Type_box: // not implemented + case Type_universe: return 0.0f; + default: return 1.0f; + } +} + +namespace Oyster { namespace Math +{ + Sphere & Nlerp( const Sphere &start, const Sphere &end, Float t, Sphere &targetMem ) + { + Float4 i = Lerp( Float4(start.center.xyz, start.radius), Float4(end.center.xyz, end.radius), t ); + targetMem.center.xyz = i.xyz; + targetMem.radius = i.w; + return targetMem; + } +} } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Sphere.h b/Code/OysterPhysics3D/Sphere.h index 2f483ecd..c3cc32a3 100644 --- a/Code/OysterPhysics3D/Sphere.h +++ b/Code/OysterPhysics3D/Sphere.h @@ -9,29 +9,42 @@ #include "OysterMath.h" #include "ICollideable.h" -namespace Oyster { namespace Collision3D +namespace Oyster { - class Sphere : public ICollideable + namespace Collision3D { - public: - union + class Sphere : public ICollideable { - struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; }; - char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)]; + public: + union + { + struct{ ::Oyster::Math::Float4 center; ::Oyster::Math::Float radius; }; + char byte[sizeof(::Oyster::Math::Float4) + sizeof(::Oyster::Math::Float)]; + }; + + Sphere( ); + Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius ); + Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius ); + virtual ~Sphere( ); + + Sphere & operator = ( const Sphere &sphere ); + + virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; + bool Intersects( const ICollideable &target ) const; + bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; + bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; + } - Sphere( ); - Sphere( const ::Oyster::Math::Float3 ¢er, const ::Oyster::Math::Float &radius ); - Sphere( const ::Oyster::Math::Float4 ¢er, const ::Oyster::Math::Float &radius ); - virtual ~Sphere( ); - - Sphere & operator = ( const Sphere &sphere ); - - virtual ::Utility::DynamicMemory::UniquePointer Clone( ) const; - bool Intersects( const ICollideable &target ) const; - bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Contains( const ICollideable &target ) const; - }; -} } + namespace Math + { + /******************************************************************** + * Normalized Linear Interpolation + ********************************************************************/ + ::Oyster::Collision3D::Sphere & Nlerp( const ::Oyster::Collision3D::Sphere &start, const ::Oyster::Collision3D::Sphere &end, ::Oyster::Math::Float t, ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ); + } +} #endif \ No newline at end of file diff --git a/Code/OysterPhysics3D/Universe.cpp b/Code/OysterPhysics3D/Universe.cpp index 7eb788ae..a3548ad9 100644 --- a/Code/OysterPhysics3D/Universe.cpp +++ b/Code/OysterPhysics3D/Universe.cpp @@ -78,4 +78,9 @@ bool Universe::Intersects( const ICollideable &target, Float4 &worldPointOfConta bool Universe::Contains( const ICollideable &target ) const { // universe contains everything return true; +} + +Float Universe::TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const +{ + return 0.0f; } \ No newline at end of file diff --git a/Code/OysterPhysics3D/Universe.h b/Code/OysterPhysics3D/Universe.h index 5f009e0b..7b5fb969 100644 --- a/Code/OysterPhysics3D/Universe.h +++ b/Code/OysterPhysics3D/Universe.h @@ -23,6 +23,8 @@ namespace Oyster { namespace Collision3D bool Intersects( const ICollideable &target ) const; bool Intersects( const ICollideable &target, ::Oyster::Math::Float4 &worldPointOfContact ) const; bool Contains( const ICollideable &target ) const; + + ::Oyster::Math::Float TimeOfContact( const ICollideable &deuterStart, const ICollideable &deuterEnd ) const; }; } }