Set direction for physic entity

Post Reply
123iamking
Posts: 10
Joined: Wed Oct 11, 2017 4:45 am

Set direction for physic entity

Post by 123iamking » Mon Nov 27, 2017 2:24 am

Currently, here is my steps to set direction for physic entity:
1. Entity A go to point B, thus the direction vector is vector AB.
2. Convert direction (vector AB) to angle to rotate rigid body of Entity A.
3. Rotate rigid body of Entity A.

And here is how I rotate rigid body

Code: Select all

		btRigidBody* body;
		btQuaternion rot;
		btTransform trans = body->getWorldTransform();
		rot = trans.getRotation();
		btScalar curAng = rot.getAngle();
		rot.setRotation(btVector3(0, 1, 0), curAng + 90);
		trans.setRotation(rot);
		// apply new rotation
		body->setWorldTransform(trans);
I got 2 questions:
1. How can I convert direction (vector AB) to angle to rotate rigid body of Entity A?
2. Is there a way I can directly set the direction of physic entity A?

User avatar
drleviathan
Posts: 372
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Set direction for physic entity

Post by drleviathan » Sun Dec 03, 2017 6:14 pm

Here is a general way to do it that works in 3D:

Code: Select all

    // This is a way to rotate a RigidBody to re-orient it's "forward" axis
    // to be along a particular direction in the world frame.  In order for
    // this to work you need to know localForward in the object's frame.
    //
    // For this example we assume localForward is Z-axis

    btVector3 AB = pointB - pointA; // world-frame
    btScalar distance = AB.length();
    const btScalar MIN_DISTANCE(0.0001f);
    
    if (distance > MIN_DISTANCE) {
        // compute normalized newForward
        btVector3 newForward = AB / distance;
    
        // compute forward in world-frame
        const btVector3 LOCAL_FORWARD(0.0f, 0.0f, 1.0f);
        btTransform trans = body->getWorldTransform();
        btVector3 forward = trans * LOCAL_FORWARD; 
    
        // compute the angle
        btVector3 axis = forward.cross(newForward);
        btScalar sinAngle = axis.length();
        if (sinAngle > btScalar(1.0f)) {
            // just in case numerical error provides length > 1.0
            sinAngle = btScalar(1.0f);
        }
        btScalar angle = btAsin(sinAngle);
        if (forward.dot(newForward) < btScalar(0.0f)) {
            // directions oppose so we actually want the supplementary angle
            angle = SIMD_PI - angle;
        }         

        // rotate if necessary
        const btScalar MIN_ANGLE(0.001f);
        if (angle > MIN_ANGLE) {
            btQuaternion dQ(axis/sinAngle, angle); 
            trans = btTransform(dQ) * trans;
            body->setWorldTransform(trans);
        }   
    }
Edited to fix errors: (a) in logic deciding whether to rotate or not and (b) in axis normalization when computing dQ.

Post Reply