Here's some background: I'm working on a game engine and I've recently added a physics engine (physx in this case ). problem is that my transform class uses euler angles for rotation and the physics engine's transform class uses euler angles. so I just implemented a method to change my transform class to the physics engine transform and back. It's working well but I've discovered a weird bug.
Behavior I get:
When the Yaw(second element of the euler vector) of the rotation is above 90 degrees it doesn't make the object rotate anymore on the y axis and start's messing around with the pitch and the roll (weird shaking skip from 0 to 180 and back a lot). The debugging tools shows that the rotation doesn't go above 91 but does go to about 90.0003 max I do transfer the degrees to radians. Example: To show this bug I have a cube with a python script rotating it :
from TOEngine import *
class rotate:
direction = vec3(0,10,0)
def Start(self):
pass
def Update(self,deltaTime):
transform.Rotate(self.direction*deltaTime*5)
pass
Engine itself written in cpp but I got a scripting system working with embedded python. TOEngine is just my module and the script itself is just rotating the cube every frame. The cube start at 0 , 0 , 0 rotation and rotating fine but stops and 90 degress yaw and starts shaking.
This only happens when the physics system is enabled so I know that the bug must be in the method transferring the rotation from euler to quat and back every frame using glm.
Here's the actual problematic code :
void RigidBody::SetTransform(Transform transform)
{
glm::vec3 axis = transform.rotation;
rigidbody->setGlobalPose(PxTransform(*(PxVec3*)&transform.position,*(PxQuat*)&glm::quat(glm::radians(transform.rotation))));//Attention Over Here
}
Transform RigidBody::GetTransform()
{
auto t = rigidbody->getGlobalPose();
return Transform(*(glm::vec3*)&t.p, glm::degrees(glm::eulerAngles(*(glm::quat*)&t.q)), entity->transform.scale);
}
Avoid the weird type punning PxQuat is basically the same as glm::quat and PxVec3 is basically the same as glm::vec3. I expect this code to transfer between the physics's engine transform class and my transform class by changing the rotation from euler angles degress to a quat with radians(the hard part).
And the inside the physics system:
void PreUpdate(float deltaTime)override { //Set Physics simulation changes to the scene
mScene->fetchResults(true);
for (auto entity : Events::scene->entities)
for (auto component : entity->components)
if (component->GetName() == "RigidBody")
entity->transform = ((RigidBody*)component)->GetTransform(); //This is running on the cube entity
}
void PostUpdate(float deltaTime)override { //Set Scene changes To Physics simulation
for (auto entity : Events::scene->entities)
for (auto component : entity->components)
if (component->GetName() == "RigidBody")
((RigidBody*)component)->SetTransform(entity->transform);//This is running on the cube entity
mScene->simulate(deltaTime);
}
PreUpdate runs before the update every frame PostUpdate runs after the update every frame. the method Update(showed in the script above) as the name suggests runs on the update...(in between PreUpdate and PostUpdate). The cube has a rigidbody component. What I expect getting: a rotating cube that doesn't stop rotating when it reaches yaw 90 degrees.
I know this one is a bit complex. I tried my best to explain the bug I believe the problem is in changing Euler angles to a quat.
Transform
? On an unrelated note, your casting of types fromglm::quat
tophyx::PxQuat
is not standards compliant and could result in undefined behavior. – cplusplusrat