diff --git a/src/Components/CompoundShape.h b/src/Components/CompoundShape.h new file mode 100644 index 0000000..c2739e6 --- /dev/null +++ b/src/Components/CompoundShape.h @@ -0,0 +1,14 @@ +#ifndef Components_CompoundShape_h__ +#define Components_CompoundShape_h__ + +#include "Component.h" + +namespace Components +{ + struct CompoundShape : Component + { + + }; +} + +#endif // Components_CompoundShape_h__ \ No newline at end of file diff --git a/src/GameWorld.cpp b/src/GameWorld.cpp index 79b810e..4565bd7 100755 --- a/src/GameWorld.cpp +++ b/src/GameWorld.cpp @@ -5,143 +5,98 @@ void GameWorld::Initialize() { World::Initialize(); - std::shared_ptr transform; - std::shared_ptr model; - - auto camera = CreateEntity(); - transform = AddComponent(camera, "Transform"); - transform->Position.z = 150.f; - transform->Position.y = 100.f; - transform->Orientation = glm::quat(glm::vec3(glm::pi() / 8.f, 0.f, 0.f)); - auto cameraComp = AddComponent(camera, "Camera"); - cameraComp->FarClip = 2000.f; - AddComponent(camera, "Input"); - auto freeSteering = AddComponent(camera, "FreeSteering"); - - - auto terrain = CreateEntity(); - transform = AddComponent(terrain, "Transform"); - transform->Scale = glm::vec3(1000.0f); - transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, glm::pi()/20.f)); - model = AddComponent(terrain, "Model"); - model->ModelFile = "Models/PhysicsTest/Plane.obj"; - auto physics = AddComponent(terrain, "Physics"); - auto Box = AddComponent(terrain, "BoxShape"); - Box->Width = 1; - Box->Height = 0; - Box->Depth = 1; - physics->Friction = 0.5f; - - terrain = CreateEntity(); - transform = AddComponent(terrain, "Transform"); - transform->Scale = glm::vec3(1000.0f); - transform->Position = glm::vec3(-500, 0, 0); - transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, -glm::pi() / 20.f)); - model = AddComponent(terrain, "Model"); - model->ModelFile = "Models/PhysicsTest/Plane.obj"; - physics = AddComponent(terrain, "Physics"); - Box = AddComponent(terrain, "BoxShape"); - Box->Width = 1; - Box->Height = 0; - Box->Depth = 1; - physics->Friction = 0.5f; - - - - auto Boxed = CreateEntity(); - transform = AddComponent(Boxed, "Transform"); - transform->Position.y = 100.f; - transform->Position.x = 4.f; - transform->Scale = glm::vec3(5.0f); - model = AddComponent(Boxed, "Model"); - model->ModelFile = "Models/PhysicsTest/Cube.obj"; - physics = AddComponent(Boxed, "Physics"); - physics->Mass = 10; - physics->Friction = 0.5f; - Box = AddComponent(Boxed, "BoxShape"); - Box->Width = 1; - Box->Height = 1; - Box->Depth = 1; - - for (int i = 0; i < 20; i++) { - auto Sphered = CreateEntity(); - transform = AddComponent(Sphered, "Transform"); - transform->Position.y = 15.f; - transform->Position.x = 4.f; - transform->Scale = glm::vec3(1.0f); - model = AddComponent(Sphered, "Model"); - model->ModelFile = "Models/PhysicsTest/Sphere.obj"; - physics = AddComponent(Sphered, "Physics"); - physics->Mass = 100; - physics->Friction = 0.5f; - auto sphere = AddComponent(Sphered, "SphereShape"); - sphere->Radius = 1; - sphere->RollingFriction = 0.5f; - - - { - auto tank_top = CreateEntity(Sphered); - transform = AddComponent(tank_top, "Transform"); - transform->Scale = glm::vec3(1.0f/100.f); - model = AddComponent(tank_top, "Model"); - model->ModelFile = "Models/tank/tank_top.obj"; - { - auto tank_barrel = CreateEntity(tank_top); - transform = AddComponent(tank_barrel, "Transform"); - - model = AddComponent(tank_barrel, "Model"); - model->ModelFile = "Models/tank/tank_barrel.obj"; - } - } + auto camera = CreateEntity(); + auto transform = AddComponent(camera, "Transform"); + transform->Position.z = 150.f; + transform->Position.y = 100.f; + transform->Orientation = glm::quat(glm::vec3(glm::pi() / 8.f, 0.f, 0.f)); + auto cameraComp = AddComponent(camera, "Camera"); + cameraComp->FarClip = 2000.f; + AddComponent(camera, "Input"); + auto freeSteering = AddComponent(camera, "FreeSteering"); } - - /*auto tank = CreateEntity(); - transform = AddComponent(tank, "Transform"); - transform->Position.y = 10.f; - transform->Position.x = 4.f; - transform->Scale = glm::vec3(.01f); - model = AddComponent(tank, "Model"); - model->ModelFile = "Models/tank/tank_base.obj"; - physics = AddComponent(tank, "Physics"); - physics->Mass = 100; - physics->Friction = 0.5f;*/ - - - /*auto sphere = AddComponent(tank, "SphereShape"); - sphere->Radius = 10.*(1.f / .01f); - sphere->RollingFriction = 0.5f;*/ -/* - Box = AddComponent(tank, "BoxShape"); - Box->Width = 100; - Box->Height = 50; - Box->Depth = 100;*/ - -/* { - auto tank_top = CreateEntity(tank); - transform = AddComponent(tank_top, "Transform"); - //transform->Scale = glm::vec3(.0005f); - model = AddComponent(tank_top, "Model"); - model->ModelFile = "Models/tank/tank_top.obj"; + auto terrain = CreateEntity(); + auto transform = AddComponent(terrain, "Transform"); + transform->Scale = glm::vec3(1000.0f); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + auto model = AddComponent(terrain, "Model"); + model->ModelFile = "Models/PhysicsTest/Plane.obj"; + auto physics = AddComponent(terrain, "Physics"); + auto Box = AddComponent(terrain, "BoxShape"); + Box->Width = 1; + Box->Height = 0; + Box->Depth = 1; + physics->Friction = 0.5f; + } + + + + { + auto entity = CreateEntity(); + auto transform = AddComponent(entity, "Transform"); + transform->Scale = glm::vec3(1.0f); + transform->Position = glm::vec3(0, 15, 0); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + + auto physics = AddComponent(entity, "Physics"); + physics->Mass = 10; + physics->Friction = 0.5; + + auto compound = AddComponent(entity, "CompoundShape"); + { - auto tank_barrel = CreateEntity(tank_top); - transform = AddComponent(tank_barrel, "Transform"); - //transform->Scale = glm::vec3(.0005f); - model = AddComponent(tank_barrel, "Model"); - model->ModelFile = "Models/tank/tank_barrel.obj"; + auto entity0 = CreateEntity(entity); + auto transform = AddComponent(entity0, "Transform"); + transform->Scale = glm::vec3(1.f); + auto model = AddComponent(entity0, "Model"); + model->ModelFile = "Models/PhysicsTest/Sphere.obj"; + + auto sphere = AddComponent(entity0, "SphereShape"); + sphere->Radius = 0.5f; + } + + { + auto entity1 = CreateEntity(entity); + auto transform = AddComponent(entity1, "Transform"); + transform->Scale = glm::vec3(1.0f); + transform->Position = glm::vec3(-1, 1, 0); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + auto model = AddComponent(entity1, "Model"); + model->ModelFile = "Models/PhysicsTest/Cube.obj"; + + auto box = AddComponent(entity1, "BoxShape"); + box->Width = 0.5; + box->Height = 0.5; + box->Depth = 0.5; } - }*/ - //auto light = CreateEntity(); - //transform = AddComponent(light, "Transform"); - //transform->Position.y = 10.f; - //auto pointLight = AddComponent(light, "PointLight"); - //pointLight->Diffuse = glm::vec3(0.1f, 0.1f, 1.0f); - //pointLight->linearAttenuation = 1.0f; - //pointLight->quadraticAttenuation = 1.0f; + { + auto entity = CreateEntity(); + auto transform = AddComponent(entity, "Transform"); + transform->Scale = glm::vec3(1.0f); + transform->Position = glm::vec3(1, 6, 0); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + auto model = AddComponent(entity, "Model"); + model->ModelFile = "Models/PhysicsTest/Cube.obj"; + + auto physics = AddComponent(entity, "Physics"); + physics->Mass = 10; + + auto box = AddComponent(entity, "BoxShape"); + box->Width = 0.5; + box->Height = 0.5; + box->Depth = 0.5; + } + + } + + + + } void GameWorld::Update(double dt) @@ -165,9 +120,10 @@ void GameWorld::RegisterComponents() m_ComponentFactory.Register("Transform", []() { return new Components::Transform(); }); m_ComponentFactory.Register("FreeSteering", []() { return new Components::FreeSteering(); }); + m_ComponentFactory.Register("Physics", []() { return new Components::Physics(); }); + m_ComponentFactory.Register("CompoundShape", []() { return new Components::CompoundShape(); }); m_ComponentFactory.Register("SphereShape", []() { return new Components::SphereShape(); }); m_ComponentFactory.Register("BoxShape", []() { return new Components::BoxShape(); }); - m_ComponentFactory.Register("Physics", []() { return new Components::Physics(); }); } diff --git a/src/GameWorld.h b/src/GameWorld.h index 0419cca..1f728d7 100755 --- a/src/GameWorld.h +++ b/src/GameWorld.h @@ -30,9 +30,10 @@ #include "Components/Template.h" #include "Components/Transform.h" -#include "Components\BoxShape.h" -#include "Components\SphereShape.h" -#include "Components\Physics.h" +#include "Components/CompoundShape.h" +#include "Components/BoxShape.h" +#include "Components/SphereShape.h" +#include "Components/Physics.h" class GameWorld : public World { diff --git a/src/Systems/PhysicsSystem.cpp b/src/Systems/PhysicsSystem.cpp index f074ee6..34d0eba 100644 --- a/src/Systems/PhysicsSystem.cpp +++ b/src/Systems/PhysicsSystem.cpp @@ -59,10 +59,10 @@ void Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID p auto sphereShapeComponent = m_World->GetComponent(entity, "SphereShape"); auto boxShapeComponent = m_World->GetComponent(entity, "BoxShape"); - if (physicsComponent && (sphereShapeComponent || boxShapeComponent)) + if (physicsComponent || sphereShapeComponent || boxShapeComponent) { if (m_PhysicsData.find(entity) == m_PhysicsData.end()) { - SetUpPhysicsState(entity); + SetUpPhysicsState(entity, parent); } if (parent != 0) @@ -83,7 +83,7 @@ void Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID p else { if (m_PhysicsData.find(entity) != m_PhysicsData.end()) { - TearDownPhysicsState(entity); + TearDownPhysicsState(entity, parent); } } } @@ -98,51 +98,99 @@ void Systems::PhysicsSystem::OnComponentRemoved(std::string type, Component* com } -void Systems::PhysicsSystem::SetUpPhysicsState(EntityID entity) +void Systems::PhysicsSystem::SetUpPhysicsState(EntityID entity, EntityID parent) { auto transformComponent = m_World->GetComponent(entity, "Transform"); + if (!transformComponent) { + LOG_WARNING("Physics component missing transform component on entity %i", entity); + return; + } + auto physicsComponent = m_World->GetComponent(entity, "Physics"); + auto compoundShapeComponent = m_World->GetComponent(entity, "CompoundShape"); auto sphereShapeComponent = m_World->GetComponent(entity, "SphereShape"); auto boxShapeComponent = m_World->GetComponent(entity, "BoxShape"); + + if (compoundShapeComponent && (sphereShapeComponent || boxShapeComponent)) { + LOG_WARNING("Entity %i has both compound shape and normal shape! Normal shapes must be children to entity with compound shape.", entity); + } + PhysicsData* physicsData = &m_PhysicsData[entity]; + /*EntityID baseParent = m_World->GetEntityBaseParent(entity); + auto baseCompoundShape = m_World->GetComponent(baseParent, "CompoundShape");*/ - if (boxShapeComponent) - { - physicsData->CollisionShape = new btBoxShape(btVector3(boxShapeComponent->Width, boxShapeComponent->Height, boxShapeComponent->Depth)); - } - else if(sphereShapeComponent) - { - physicsData->CollisionShape = new btSphereShape(sphereShapeComponent->Radius); - } + // Set-up compound shape + if (compoundShapeComponent) { + btCompoundShape* compoundShape = new btCompoundShape(); + physicsData->CollisionShape = compoundShape; - if (transformComponent) - { btTransform transform; transform.setFromOpenGLMatrix(glm::value_ptr(glm::translate(glm::mat4(), transformComponent->Position) * glm::toMat4(transformComponent->Orientation))); physicsData->MotionState = new btDefaultMotionState(transform); - } + btVector3 inertia; + if (physicsComponent->Mass != 0) { + physicsData->CollisionShape->calculateLocalInertia(physicsComponent->Mass, inertia); + } - btVector3 inertia; - if (physicsComponent->Mass != 0) - physicsData->CollisionShape->calculateLocalInertia(physicsComponent->Mass, inertia); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(physicsComponent->Mass, physicsData->MotionState, physicsData->CollisionShape, inertia); + physicsData->RigidBody = new btRigidBody(rigidBodyCI); - btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(physicsComponent->Mass, physicsData->MotionState, physicsData->CollisionShape, inertia); - rigidBodyCI.m_friction = physicsComponent->Friction; - if (sphereShapeComponent) - { - rigidBodyCI.m_rollingFriction = sphereShapeComponent->RollingFriction; + m_DynamicsWorld->addRigidBody(physicsData->RigidBody); } - physicsData->RigidBody = new btRigidBody(rigidBodyCI); + // Set-up normal shapes + else if (boxShapeComponent) { + physicsData->CollisionShape = new btBoxShape(btVector3(boxShapeComponent->Width, boxShapeComponent->Height, boxShapeComponent->Depth)); + } else if (sphereShapeComponent) { + physicsData->CollisionShape = new btSphereShape(sphereShapeComponent->Radius); + } + if (boxShapeComponent || sphereShapeComponent) { + btTransform transform; + transform.setFromOpenGLMatrix(glm::value_ptr(glm::translate(glm::mat4(), transformComponent->Position) * glm::toMat4(transformComponent->Orientation))); - + // If there's a local physics component + if (physicsComponent) { + physicsData->MotionState = new btDefaultMotionState(transform); - m_DynamicsWorld->addRigidBody(physicsData->RigidBody); + btVector3 inertia; + if (physicsComponent->Mass != 0) { + physicsData->CollisionShape->calculateLocalInertia(physicsComponent->Mass, inertia); + } + + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(physicsComponent->Mass, physicsData->MotionState, physicsData->CollisionShape, inertia); + physicsData->RigidBody = new btRigidBody(rigidBodyCI); + + m_DynamicsWorld->addRigidBody(physicsData->RigidBody); + } else { + // Otherwise, find our base parent and attach to compound shape + EntityID baseParent = m_World->GetEntityBaseParent(entity); + auto basePhysicsComponent = m_World->GetComponent(baseParent, "Physics"); + if (!basePhysicsComponent) { + LOG_WARNING("Failed to attach orphan collision shape on entity %i: missing physics component on base parent entity %i", entity, baseParent); + return; + } + auto baseCompoundShapeComponent = m_World->GetComponent(baseParent, "CompoundShape"); + if (!baseCompoundShapeComponent) { + LOG_WARNING("Failed to attach orphan collision shape on entity %i: missing compound shape on base parent entity %i", entity, baseParent); + return; + } + PhysicsData* basePhysicsData = &m_PhysicsData.at(baseParent); + + btCompoundShape* baseCompoundShape = dynamic_cast(basePhysicsData->CollisionShape); + baseCompoundShape->addChildShape(transform, physicsData->CollisionShape); + + btVector3 inertia; + baseCompoundShape->calculateLocalInertia(basePhysicsComponent->Mass, inertia); + + basePhysicsData->RigidBody->setMassProps(basePhysicsComponent->Mass, inertia); + basePhysicsData->RigidBody->updateInertiaTensor(); + } + } } -void Systems::PhysicsSystem::TearDownPhysicsState(EntityID entity) +void Systems::PhysicsSystem::TearDownPhysicsState(EntityID entity, EntityID parent) { PhysicsData* physicsData = &m_PhysicsData[entity]; diff --git a/src/Systems/PhysicsSystem.h b/src/Systems/PhysicsSystem.h index 8421e34..9928018 100644 --- a/src/Systems/PhysicsSystem.h +++ b/src/Systems/PhysicsSystem.h @@ -4,6 +4,7 @@ #include "System.h" #include "Components/Transform.h" #include "Components/Physics.h" +#include "Components/CompoundShape.h" #include "Components/BoxShape.h" #include "Components/SphereShape.h" @@ -38,8 +39,8 @@ namespace Systems std::map m_PhysicsData; - void SetUpPhysicsState(EntityID entity); - void TearDownPhysicsState(EntityID entity); + void SetUpPhysicsState(EntityID entity, EntityID parent); + void TearDownPhysicsState(EntityID entity, EntityID parent); diff --git a/src/World.cpp b/src/World.cpp index 29bde4b..ae3b3fa 100755 --- a/src/World.cpp +++ b/src/World.cpp @@ -56,6 +56,15 @@ EntityID World::GetEntityParent(EntityID entity) return it == m_EntityParents.end() ? 0 : it->second; } +EntityID World::GetEntityBaseParent(EntityID entity) +{ + EntityID parent = GetEntityParent(entity); + if (parent == 0) + return entity; + else + return GetEntityBaseParent(parent); +} + bool World::ValidEntity(EntityID entity) { return m_EntityParents.find(entity) != m_EntityParents.end(); diff --git a/src/World.h b/src/World.h index ecc9fd1..8d3f08d 100755 --- a/src/World.h +++ b/src/World.h @@ -41,6 +41,7 @@ public: bool ValidEntity(EntityID entity); EntityID GetEntityParent(EntityID entity); + EntityID GetEntityBaseParent(EntityID entity); template T GetProperty(EntityID entity, std::string property) diff --git a/vs12/Returngeance/Returngeance.vcxproj b/vs12/Returngeance/Returngeance.vcxproj index 631e276..4933bfe 100755 --- a/vs12/Returngeance/Returngeance.vcxproj +++ b/vs12/Returngeance/Returngeance.vcxproj @@ -112,6 +112,7 @@ + diff --git a/vs12/Returngeance/Returngeance.vcxproj.filters b/vs12/Returngeance/Returngeance.vcxproj.filters index 74260f3..695be4f 100755 --- a/vs12/Returngeance/Returngeance.vcxproj.filters +++ b/vs12/Returngeance/Returngeance.vcxproj.filters @@ -142,6 +142,9 @@ Systems + + Components +