-1
\$\begingroup\$

My chaser object will not face the player object. It simply keeps spinning around and won't face the player.

void chaser::Move() {
    vec3 plannedFacingDirection = normalize(p->GetPosition() - GetPosition());

    vec3 currentFacingDirection = normalize(vec3(0.0f, 0.0f, -1.0f)); //yes i know it's already normalized

    vec3 axisOfRotation = normalize(cross(currentFacingDirection, plannedFacingDirection));

    float dotProductOfVectors = dot(currentFacingDirection, plannedFacingDirection);

    clamp(dotProductOfVectors, -1.0f, 1.0f);

    float angle = acos(dotProductOfVectors);
    if (plannedFacingDirection != currentFacingDirection) {
        if (dotProductOfVectors != -1.0f && dotProductOfVectors != 1.0f) {
            transform = rotate(transform, angle, axisOfRotation);
        }
    }

    transform = translate(transform, normalize(currentFacingDirection) * speed);
}

Move() is called in the render() function. pis the player object. transformis a mat4 object. I will be eyeing this question like a hawk. It's really bugging me that I can't figure this out. Please comment with any questions of your own and I will answer them ASAP.

\$\endgroup\$
  • \$\begingroup\$ You don't compute the sign of the angle: you always rotate counter clockwise, never clockwise. acos() returns a value 0 .. π \$\endgroup\$ – Bram Dec 6 '17 at 20:33
  • \$\begingroup\$ Sometimes adding an animated gif helps illustrate the issue at hand. \$\endgroup\$ – Alexandre Vaillancourt Dec 7 '17 at 1:47
  • \$\begingroup\$ I managed to fix this by setting a new variable, originalTransform, where the chaser is spawned, and setting the current transform to be equal to rotate(originalTransform, angle, axisOfRotation) and then applying the translation- which is why I didn't get back until now! The result was satisfactory for what I needed, as the chasers orientation didn't really matter, as long as it moved and faced toward the player. \$\endgroup\$ – DCON Dec 8 '17 at 3:40
0
\$\begingroup\$

To face a certain direction, I find that a much better approach is to built a new matrix, instead of transforming an old one with a rotation.

Let's say you want the chaser X axis to point at the target, and world Z is up:

vec3 x = ( tgt - chaserpos );
x.normalize();
// y is z cross x.
vec3 y = vec3(0,0,1).crossProd( x );
y.normalize();
// z is x cross y.
z = x.crossProd( y );

mat44 chasermat;
chasermat.setRow( 0, x );
chasermat.setRow( 1, y );
chasermat.setRow( 2, z );
chasermat.setRow( 3, chaserpos );

This code creates three axes that are perpendicular to each other. The x points to the target, the y points to the left, the z points up.

The resulting matrix will have pan, tilt, but no roll (horizon stays horizontal.)

NOTE: This code does not work if the chaser needs to look perfectly straight up or perfectly straight down.

NOTE: Your matrix library may have a LookAt() function that does just this. But described here is how to do this manually. After the LookAt() don't forget to set the translation.

PS: Your original code does not work because you determine an angle, but not the sign of the angle: do you need to turn clock wise or counter clockwise?

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.