From f7625194f5fc93597124c3dc7d602faab81c659b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Davy=20H=C3=A9lard?= Date: Wed, 11 Dec 2024 22:37:39 +0100 Subject: [PATCH] Fix the character rotation on moving platforms. --- .../Physics3DRuntimeBehavior.ts | 29 ++++++++------- .../PhysicsCharacter3DRuntimeBehavior.ts | 35 ++++++++++--------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts b/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts index 1271fac95f..cbf5220094 100644 --- a/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts +++ b/Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts @@ -957,6 +957,20 @@ namespace gdjs { ); } + moveObjectToPhysicsRotation(physicsRotation: Jolt.Quat): void { + const threeObject = this.owner3D.get3DRendererObject(); + threeObject.quaternion.x = physicsRotation.GetX(); + threeObject.quaternion.y = physicsRotation.GetY(); + threeObject.quaternion.z = physicsRotation.GetZ(); + threeObject.quaternion.w = physicsRotation.GetW(); + // TODO Avoid this instantiation + const euler = new THREE.Euler(0, 0, 0, 'ZYX'); + euler.setFromQuaternion(threeObject.quaternion); + this.owner3D.setRotationX(gdjs.toDegrees(euler.x)); + this.owner3D.setRotationY(gdjs.toDegrees(euler.y)); + this.owner3D.setAngle(gdjs.toDegrees(euler.z)); + } + getWorldScale(): float { return this._sharedData.worldScale; } @@ -1810,7 +1824,7 @@ namespace gdjs { updateObjectFromBody() { const { behavior } = this; - const { owner3D, _body } = behavior; + const { _body } = behavior; // Copy transform from body to the GD object. // It's possible the behavior was either deactivated or the object deleted // just before this doStepPreEvents (for example, another behavior deleted @@ -1818,18 +1832,7 @@ namespace gdjs { // don't do anything (but still run the physics simulation - this is independent). if (_body !== null) { behavior.moveObjectToPhysicsPosition(_body.GetPosition()); - - const quaternion = _body.GetRotation(); - const threeObject = owner3D.get3DRendererObject(); - threeObject.quaternion.x = quaternion.GetX(); - threeObject.quaternion.y = quaternion.GetY(); - threeObject.quaternion.z = quaternion.GetZ(); - threeObject.quaternion.w = quaternion.GetW(); - const euler = new THREE.Euler(0, 0, 0, 'ZYX'); - euler.setFromQuaternion(threeObject.quaternion); - owner3D.setRotationX(gdjs.toDegrees(euler.x)); - owner3D.setRotationY(gdjs.toDegrees(euler.y)); - owner3D.setAngle(gdjs.toDegrees(euler.z)); + behavior.moveObjectToPhysicsRotation(_body.GetRotation()); } } diff --git a/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts b/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts index 584e1db5cd..f441fcdade 100644 --- a/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts +++ b/Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts @@ -701,23 +701,21 @@ namespace gdjs { const groundAngularVelocityZ = groundBody.GetAngularVelocity().GetZ(); if (groundAngularVelocityZ !== 0) { // Make the character rotate with the platform on Z axis. - const rotation = Jolt.Quat.prototype.sEulerAngles( - this.getVec3( - 0, - 0, - characterBody - .GetRotation() - .GetRotationAngle(Jolt.Vec3.prototype.sAxisZ()) + - groundAngularVelocityZ * timeDelta + const angleDelta = groundAngularVelocityZ * timeDelta; + this.character.SetRotation( + Jolt.Quat.prototype.sEulerAngles( + this.getVec3( + 0, + 0, + this.character + .GetRotation() + .GetRotationAngle(Jolt.Vec3.prototype.sAxisZ()) + angleDelta + ) ) ); - // TODO Should the character be used instead of the body directly? - this._sharedData.bodyInterface.SetPositionAndRotation( - characterBody.GetID(), - this.getPhysicsPosition(this.getRVec3(0, 0, 0)), - rotation, - Jolt.EActivation_Activate - ); + // Also update the forward angle to make sure it stays the same + // relatively to the object angle. + this._forwardAngle += gdjs.toDegrees(angleDelta); } if (stillKinematicPlatform) { groundBody.SetLinearVelocity(Jolt.Vec3.prototype.sZero()); @@ -1345,6 +1343,7 @@ namespace gdjs { } updateObjectFromBody() { + const { behavior } = this.characterBehavior.getPhysics3D(); const { character } = this.characterBehavior; if (!character) { return; @@ -1353,7 +1352,8 @@ namespace gdjs { this.characterBehavior.moveObjectToPhysicsPosition( character.GetPosition() ); - // No need to update the rotation as CharacterVirtual doesn't change it. + // TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it. + behavior.moveObjectToPhysicsRotation(character.GetRotation()); } updateBodyFromObject() { @@ -1374,7 +1374,8 @@ namespace gdjs { behavior._objectOldRotationY !== owner3D.getRotationY() || behavior._objectOldRotationZ !== owner3D.getAngle() ) { - behavior.getPhysicsRotation( + // TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it. + character.SetRotation( behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1)) ); }