diff --git a/src/Engine.cpp b/src/Engine.cpp index ea4a801..62a8db7 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -321,15 +321,15 @@ void Engine::run() { } } + if (isPlaying) { + updatePlayerController(deltaTime); + } + bool simulatePhysics = physics.isReady() && ((isPlaying && !isPaused) || (!isPlaying && specMode)); if (simulatePhysics) { physics.simulate(deltaTime, sceneObjects); } - if (isPlaying) { - updatePlayerController(deltaTime); - } - bool audioShouldPlay = isPlaying || specMode || testMode; Camera listenerCamera = camera; for (const auto& obj : sceneObjects) { @@ -875,10 +875,12 @@ void Engine::updatePlayerController(float delta) { if (grounded) { pc.verticalVelocity = 0.0f; - if (hitGround) { - player->position.y = std::max(player->position.y, hitPos.y + capsuleHalf); - } else { - player->position.y = capsuleHalf; + if (!havePhysVel) { + if (hitGround) { + player->position.y = std::max(player->position.y, hitPos.y + capsuleHalf); + } else { + player->position.y = capsuleHalf; + } } if (key(GLFW_KEY_SPACE)) { pc.verticalVelocity = pc.jumpStrength; diff --git a/src/EnginePanels.cpp b/src/EnginePanels.cpp index 4471dc8..5e73a2c 100644 --- a/src/EnginePanels.cpp +++ b/src/EnginePanels.cpp @@ -2331,6 +2331,16 @@ void Engine::renderInspectorPanel() { obj.rigidbody.angularDamping = std::clamp(obj.rigidbody.angularDamping, 0.0f, 10.0f); changed = true; } + ImGui::TextDisabled("Rotation Constraints"); + if (ImGui::Checkbox("Lock Rotation X", &obj.rigidbody.lockRotationX)) { + changed = true; + } + if (ImGui::Checkbox("Lock Rotation Y", &obj.rigidbody.lockRotationY)) { + changed = true; + } + if (ImGui::Checkbox("Lock Rotation Z", &obj.rigidbody.lockRotationZ)) { + changed = true; + } ImGui::Unindent(10.0f); ImGui::PopID(); } diff --git a/src/PhysicsSystem.cpp b/src/PhysicsSystem.cpp index 3b6453c..4a5a6e1 100644 --- a/src/PhysicsSystem.cpp +++ b/src/PhysicsSystem.cpp @@ -332,7 +332,11 @@ PhysicsSystem::ActorRecord PhysicsSystem::createActorFor(const SceneObject& obj) dyn->setLinearDamping(obj.rigidbody.linearDamping); dyn->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, obj.rigidbody.isKinematic); dyn->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, !obj.rigidbody.useGravity); - dyn->setRigidDynamicLockFlags(PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z); + PxRigidDynamicLockFlags lockFlags; + if (obj.rigidbody.lockRotationX) lockFlags |= PxRigidDynamicLockFlag::eLOCK_ANGULAR_X; + if (obj.rigidbody.lockRotationY) lockFlags |= PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y; + if (obj.rigidbody.lockRotationZ) lockFlags |= PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z; + dyn->setRigidDynamicLockFlags(lockFlags); if (obj.hasPlayerController) { dyn->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true); dyn->setMaxDepenetrationVelocity(1.5f); @@ -404,9 +408,6 @@ bool PhysicsSystem::setActorYaw(int id, float yawDegrees) { PxQuat yawQuat(static_cast(glm::radians(yawDegrees)), PxVec3(0, 1, 0)); pose.q = yawQuat; rec.actor->setGlobalPose(pose); - if (PxRigidDynamic* dyn = rec.actor->is()) { - dyn->setRigidDynamicLockFlags(PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z); - } return true; #endif return false; @@ -507,7 +508,23 @@ void PhysicsSystem::simulate(float deltaTime, std::vector& objects) if (it == objects.end() || !it->enabled) continue; it->position = ToGlmVec3(pose.p); - it->rotation.y = ToGlmEulerDeg(pose.q).y; + if (it->hasPlayerController && it->playerController.enabled) { + continue; + } + glm::vec3 euler = ToGlmEulerDeg(pose.q); + if (PxRigidDynamic* dyn = rec.actor->is()) { + PxRigidDynamicLockFlags lockFlags = dyn->getRigidDynamicLockFlags(); + bool lockX = lockFlags.isSet(PxRigidDynamicLockFlag::eLOCK_ANGULAR_X); + bool lockY = lockFlags.isSet(PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y); + bool lockZ = lockFlags.isSet(PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z); + if (lockX && lockZ && !lockY) { + it->rotation.y = euler.y; + } else { + it->rotation = euler; + } + } else { + it->rotation.y = euler.y; + } } } diff --git a/src/ProjectManager.cpp b/src/ProjectManager.cpp index 50d0520..4a92603 100644 --- a/src/ProjectManager.cpp +++ b/src/ProjectManager.cpp @@ -283,6 +283,9 @@ bool SceneSerializer::saveScene(const fs::path& filePath, file << "rbKinematic=" << (obj.rigidbody.isKinematic ? 1 : 0) << "\n"; file << "rbLinearDamping=" << obj.rigidbody.linearDamping << "\n"; file << "rbAngularDamping=" << obj.rigidbody.angularDamping << "\n"; + file << "rbLockRotX=" << (obj.rigidbody.lockRotationX ? 1 : 0) << "\n"; + file << "rbLockRotY=" << (obj.rigidbody.lockRotationY ? 1 : 0) << "\n"; + file << "rbLockRotZ=" << (obj.rigidbody.lockRotationZ ? 1 : 0) << "\n"; } file << "hasCollider=" << (obj.hasCollider ? 1 : 0) << "\n"; if (obj.hasCollider) { @@ -495,6 +498,12 @@ bool SceneSerializer::loadScene(const fs::path& filePath, currentObj->rigidbody.linearDamping = std::stof(value); } else if (key == "rbAngularDamping") { currentObj->rigidbody.angularDamping = std::stof(value); + } else if (key == "rbLockRotX") { + currentObj->rigidbody.lockRotationX = std::stoi(value) != 0; + } else if (key == "rbLockRotY") { + currentObj->rigidbody.lockRotationY = std::stoi(value) != 0; + } else if (key == "rbLockRotZ") { + currentObj->rigidbody.lockRotationZ = std::stoi(value) != 0; } else if (key == "hasCollider") { currentObj->hasCollider = std::stoi(value) != 0; } else if (key == "colliderEnabled") { diff --git a/src/SceneObject.h b/src/SceneObject.h index 61d041f..8088cf5 100644 --- a/src/SceneObject.h +++ b/src/SceneObject.h @@ -107,6 +107,9 @@ struct RigidbodyComponent { bool isKinematic = false; float linearDamping = 0.05f; float angularDamping = 0.05f; + bool lockRotationX = true; + bool lockRotationY = false; + bool lockRotationZ = true; }; enum class ColliderType { diff --git a/src/ScriptRuntime.cpp b/src/ScriptRuntime.cpp index eb6a883..921b9b8 100644 --- a/src/ScriptRuntime.cpp +++ b/src/ScriptRuntime.cpp @@ -76,6 +76,9 @@ void ScriptContext::SetRotation(const glm::vec3& rot) { if (object) { object->rotation = NormalizeEulerDegrees(rot); MarkDirty(); + if (engine && HasRigidbody()) { + engine->teleportPhysicsActorFromScript(object->id, object->position, object->rotation); + } } }