jayfield1979
jayfield1979

Reputation: 355

THREE.js: Why is my object flipping whilst travelling along a spline?

Following up from my original post Three.JS Object following a spline path - rotation / tangent issues & constant speed issue, I am still having the issue that the object flips at certain points along the path.

View this happening on this fiddle: http://jsfiddle.net/jayfield1979/T2t59/7/

function moveBox() {
if (counter <= 1) {

    box.position.x = spline.getPointAt(counter).x;
    box.position.y = spline.getPointAt(counter).y;

    tangent = spline.getTangentAt(counter).normalize();

    axis.cross(up, tangent).normalize();

    var radians = Math.acos(up.dot(tangent));

    box.quaternion.setFromAxisAngle(axis, radians);

    counter += 0.005
} else {
    counter = 0;
}

}

The above code is what moves my objects along the defined spline path (an oval in this instance). It was mentioned by @WestLangley that: "Warning: cross product is not well-defined if the two vectors are parallel.".

As you can see, from the shape of the path, I am going to encounter a number of parallel vectors. Is there anything I can do to prevent this flipping from happening?

Upvotes: 1

Views: 1347

Answers (1)

Salix alba
Salix alba

Reputation: 7824

To answer the why question in the title. The reason its happening is that at some points on the curve the vector up (1,0,0) and the tangent are parallel. This means their cross product is zero and the construction of the quaternion fails.

You could follow WestLangley suggestion. You really want the up direction to be the normal to the plane the track is in.

Quaternion rotation is tricky to understand the setFromAxisAngle function rotates around the axis by a given angle.

If the track lies in the X-Y plane then we will want to rotate around the Z-axis. To find the angle use Math.atan2 to find the angle of the tangent

var angle = Math.atan2(tangent.y,tangent.x);

putting this together set

var ZZ = new THREE.Vector3( 0, 0, 1 );

and

tangent = spline.getTangentAt(counter).normalize();
var angle = Math.atan2(tangent.y,tangent.x);    
box.quaternion.setFromAxisAngle(ZZ, angle);

If the track leaves the X-Y plane things will get trickier.

Upvotes: 3

Related Questions