diff --git a/runtime/Game/Game.cpp b/runtime/Game/Game.cpp index 877b359ec..691c27172 100644 --- a/runtime/Game/Game.cpp +++ b/runtime/Game/Game.cpp @@ -100,7 +100,6 @@ namespace spartan // add physics components shared_ptr physics_body = entity->AddComponent(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::StaticPlane); } @@ -570,7 +569,6 @@ namespace spartan { // add physics so we can walk on it PhysicsBody* physics_body = m_default_terrain->AddComponent().get(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::Terrain); // water @@ -634,7 +632,6 @@ namespace spartan // make the bark collidable shared_ptr physics_body = bark->AddComponent(); physics_body->SetShapeType(PhysicsShape::Mesh); - physics_body->SetMass(0.0f); } if (Entity* branches = entity->GetDescendantByName("Branches")) @@ -744,7 +741,6 @@ namespace spartan if (entity->IsActive() && entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -818,18 +814,8 @@ namespace spartan entity->SetPosition(Vector3(0.0f, 14.0f, -355.5300f)); entity->SetScale(Vector3(0.1f, 0.1f, 0.1f)); - // enable physics for all meshes - vector entities; - entity->GetDescendants(&entities); - for (Entity* entity : entities) - { - if (entity->GetComponent() != nullptr) - { - PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); - physics_body->SetShapeType(PhysicsShape::Mesh); - } - } + PhysicsBody* physics_body = entity->AddComponent().get(); + physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -860,7 +846,6 @@ namespace spartan if (entity->IsActive() && entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); // static physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -899,7 +884,6 @@ namespace spartan if (entity->IsActive() && entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -928,7 +912,6 @@ namespace spartan if (entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -956,7 +939,6 @@ namespace spartan if (entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); physics_body->SetShapeType(PhysicsShape::Mesh); } } @@ -1080,7 +1062,6 @@ namespace spartan if (entity->GetComponent() != nullptr) { PhysicsBody* physics_body = entity->AddComponent().get(); - physics_body->SetMass(0.0f); // static physics_body->SetShapeType(PhysicsShape::Mesh); } } diff --git a/runtime/World/Components/PhysicsBody.cpp b/runtime/World/Components/PhysicsBody.cpp index 09934dc9d..78a882eae 100644 --- a/runtime/World/Components/PhysicsBody.cpp +++ b/runtime/World/Components/PhysicsBody.cpp @@ -63,26 +63,18 @@ namespace spartan #define rigid_body static_cast(m_rigid_body) #define vehicle static_cast(m_vehicle) - btTransform compute_transform(const Vector3& position, const Quaternion& rotation, const Vector3& scale) + btTransform compute_transform(const Vector3& position, const Quaternion& rotation) { - btTransform transform; - transform.setIdentity(); - + // to bullet btQuaternion bt_rotation = quaternion_to_bt(rotation); btVector3 bt_position = vector_to_bt(position); - - btMatrix3x3& basis = transform.getBasis(); - basis.setValue(scale.x, 0, 0, - 0, scale.y, 0, - 0, 0, scale.z); - - // Create a transform from the rotation quaternion - btTransform rotation_transform(bt_rotation); - transform = rotation_transform * transform; - - // Set the position + + // to transform + btTransform transform; + transform.setIdentity(); + transform.setRotation(bt_rotation); transform.setOrigin(bt_position); - + return transform; } @@ -879,64 +871,65 @@ namespace spartan case PhysicsShape::Mesh: { - function recursive_renderable_to_shape = [&](Entity* entity, btCompoundShape* compoundShape) + function recursive_renderable_to_shape = [&](Entity* entity, btCompoundShape* shape_compount, const bool is_root_entity) { // get renderable shared_ptr renderable = entity->GetComponent(); if (renderable) { - // get geometry - vector indices; - vector vertices; - renderable->GetGeometry(&indices, &vertices); - - if (vertices.empty()) - { - SP_LOG_WARNING("PhysicsShape::Mesh requires the renderable component to contain vertices"); - return; - } + // get geometry and save it as well + // geometry is saved because btTriangleIndexVertexArray only points it + PhysicsBodyMeshData& mesh_data = m_mesh_data.emplace_back(); + renderable->GetGeometry(&mesh_data.indices, &mesh_data.vertices); + + // the root/calling entity's position and rotation is control by the motion state, no need to apply it here + Vector3 position = is_root_entity ? Vector3::Zero : entity->GetPosition(); + Quaternion rotation = is_root_entity ? Quaternion::Identity : entity->GetRotation(); // determine how much detail is needed for this shape - const bool is_enterable = can_player_fit(entity, vertices, size); - const bool convex_hull = !is_enterable; + const bool is_enterable = can_player_fit(entity, mesh_data.vertices, size); + const bool is_dynamic = m_mass > 0.0f; + const bool convex_hull = is_dynamic || !is_enterable; if (convex_hull) { // create convex hull shape btConvexHullShape* shape_convex = new btConvexHullShape( - reinterpret_cast(&vertices[0]), - static_cast(vertices.size()), + reinterpret_cast(&mesh_data.vertices[0]), + static_cast(mesh_data.vertices.size()), static_cast(sizeof(RHI_Vertex_PosTexNorTan)) ); + shape_convex->optimizeConvexHull(); + shape_convex->setLocalScaling(vector_to_bt(size)); // add to compound if (renderable->HasInstancing()) { for (uint32_t instance_index = 0; instance_index < renderable->GetInstanceCount(); instance_index++) { - Matrix world_transform = renderable->GetInstanceTransform(instance_index); - compoundShape->addChildShape(compute_transform(world_transform.GetTranslation(), world_transform.GetRotation(), world_transform.GetScale()), shape_convex); + Matrix transform_instance = renderable->GetInstanceTransform(instance_index) * entity->GetMatrix(); + shape_compount->addChildShape(compute_transform(transform_instance.GetTranslation(), transform_instance.GetRotation()), shape_convex); } } else { - compoundShape->addChildShape(compute_transform(Vector3::Zero, Quaternion::Identity, size), shape_convex); + shape_compount->addChildShape(compute_transform(position, rotation), shape_convex); } } else { // simplify the geometry if not convex hull - geometry_processing::simplify(indices, vertices, static_cast((indices.size() / 3) * 0.05f)); + geometry_processing::simplify(mesh_data.indices, mesh_data.vertices, static_cast((mesh_data.indices.size() / 3) * 0.05f)); // create triangle mesh shape btTriangleIndexVertexArray* index_vertex_array = new btTriangleIndexVertexArray( - static_cast(indices.size() / 3), - reinterpret_cast(&indices[0]), + static_cast(mesh_data.indices.size() / 3), + reinterpret_cast(&mesh_data.indices[0]), sizeof(uint32_t) * 3, - static_cast(vertices.size()), - reinterpret_cast(&vertices[0].pos[0]), - sizeof(vertices[0]) + static_cast(mesh_data.vertices.size()), + reinterpret_cast(&mesh_data.vertices[0].pos[0]), + sizeof(mesh_data.vertices[0]) ); btBvhTriangleMeshShape* shape_triangle_mesh = new btBvhTriangleMeshShape( @@ -945,12 +938,10 @@ namespace spartan ); shape_triangle_mesh->setLocalScaling(vector_to_bt(size)); - - // set properties for kinematic static collision + m_is_kinematic = true; - m_mass = 0.0f; - - compoundShape->addChildShape(compute_transform(Vector3::Zero, Quaternion::Identity, size), shape_triangle_mesh); + + shape_compount->addChildShape(compute_transform(Vector3::Zero, Quaternion::Identity), shape_triangle_mesh); } } @@ -958,15 +949,13 @@ namespace spartan vector children = entity->GetChildren(); for (Entity* child : children) { - recursive_renderable_to_shape(child, compoundShape); + recursive_renderable_to_shape(child, shape_compount, false); } }; - // create the compound shape + // recursively create a compound shape that contains the entity's hierarchy btCompoundShape* shape_compound = new btCompoundShape(); - - // start the recursive process for this entity - recursive_renderable_to_shape(GetEntity(), shape_compound); + recursive_renderable_to_shape(GetEntity(), shape_compound, true); m_shape = shape_compound; diff --git a/runtime/World/Components/PhysicsBody.h b/runtime/World/Components/PhysicsBody.h index 1033000b1..e3a5bae20 100644 --- a/runtime/World/Components/PhysicsBody.h +++ b/runtime/World/Components/PhysicsBody.h @@ -60,6 +60,12 @@ namespace spartan Max }; + struct PhysicsBodyMeshData + { + std::vector indices; + std::vector vertices; + }; + class PhysicsBody : public Component { public: @@ -166,7 +172,7 @@ namespace spartan void RemoveBodyFromWorld(); void UpdateShape(); - float m_mass = 1.0f; + float m_mass = 0.0f; float m_friction = 1.0f; float m_friction_rolling = 0.002f; float m_restitution = 0.2f; @@ -184,6 +190,7 @@ namespace spartan void* m_shape = nullptr; void* m_rigid_body = nullptr; std::shared_ptr m_car = nullptr; + std::vector m_mesh_data; std::vector m_constraints; }; }