# Parallel Transport Frame

This topic is 4322 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This is related to my "Bezier Curve Evaluation" Thread I posted a while ago, now I have more understanding ive decided to come back to it. I initially have a bezier curve that I need an object to follow and need to know which way is up, forward, side etc, i used the frenet frame but I had torsion effects so I had to move to the Parallel Transport Frame instead. Now the code below follows the curve corectly but the rotation isnt correct. Maybe its the way Im storing the previous frame or the order im doing things in. Heres what I have
void draw(void)
{

// NOTE: the tangent is calculated before this function is called and works fine

// Calculate the axis angle rotation matrix
Vector rotation = crossProduct(oldTangent, newTangent);
float angleOfRotation = atan2(rotation.magnitude(), dotProduct(oldTangent, newTangent));

// Create the rotation matrix, puts matrix in rotationMatrix[]
createRotationMatrix(angleOfRotation, rotation.x, rotation.y, rotation.z);

// Multiply old frame by the new frame, puts the result in newMatrix[]
multiplyMatrix(previousMatrix, rotationMatrix);

// Update position of the new frame
newMatrix[12] = newPosition.x;
newMatrix[13] = newPosition.y;
newMatrix[14] = newPosition.z;

// Now Draw it
glPushMatrix();

// Translate
glMultMatrixf(newMatrix);

// Draw the object
drawObject();

glPopMatrix();

// Store previous values for next pass
previousMatrix = newMatrix;

oldTangent = newTangent;

}


Can anyone see what Im doing wrong? If there is any bits of code that needs further explanation ill post it here. Thx

##### Share on other sites
Still having problems with this huh? Well, since I got you into the whole 'parallel transport frame' mess, I should try to help you fix it :-) The basic idea looks correct; maybe you could post createRotationMatrix() and multiplyMatrix() so I can take a look at them.

##### Share on other sites
I'm not sure how your data is stored, so this is just a shot in the dark...

It looks like you're creating a rotation matrix from euler angles, then multiplying that matrix by the previous frame's matrix. This is fine, but since the previous frame contained the previous rotations as well, you are accumulating rotations.

Since you're overwriting the translation component directly every frame anyway, I'm not sure why you even have a need to multiply with the previous frame's matrix at all.

Edit: Idled on a reply for too long, I guess... listen to jyk. :)

##### Share on other sites
Quote:
 Original post by bpointIt looks like you're creating a rotation matrix from euler angles, then multiplying that matrix by the previous frame's matrix. This is fine, but since the previous frame contained the previous rotations as well, you are accumulating rotations.
It's an axis-angle rotation, not Euler angles (it kind of looks like the latter due to the 'x, y, z' arguments though).
Quote:
 Since you're overwriting the translation component directly every frame anyway, I'm not sure why you even have a need to multiply with the previous frame's matrix at all.
The PTF uses incremental rotations, so the multiplication is in fact correct.

It looks like he's got the concept right, but as they say, the devil is in the details :)

##### Share on other sites
Ok heres my functions, again they are taken from a book and working examples so they should work fine.

void createRotationMatrix(float angle, float x, float y, float z){	float sinSave, cosSave, oneMinusCos;	float xx, yy, zz, xy, yz, zx, xs, ys, zs;	// If NULL vector passed in, this will blow up...	if(x == 0.0f && y == 0.0f && z == 0.0f)		return;	sinSave = (float)sin(angle);	cosSave = (float)cos(angle);	oneMinusCos = 1.0f - cosSave;	xx = x * x;	yy = y * y;	zz = z * z;	xy = x * y;	yz = y * z;	zx = z * x;	xs = x * sinSave;	ys = y * sinSave;	zs = z * sinSave;	this->rotationMatrix[0] = (oneMinusCos * xx) + cosSave;	this->rotationMatrix[4] = (oneMinusCos * xy) - zs;	this->rotationMatrix[8] = (oneMinusCos * zx) + ys;	this->rotationMatrix[12] = 0.0f;	this->rotationMatrix[1] = (oneMinusCos * xy) + zs;	this->rotationMatrix[5] = (oneMinusCos * yy) + cosSave;	this->rotationMatrix[9] = (oneMinusCos * yz) - xs;	this->rotationMatrix[13] = 0.0f;		this->rotationMatrix[2] = (oneMinusCos * zx) - ys;	this->rotationMatrix[6] = (oneMinusCos * yz) + xs;	this->rotationMatrix[10] = (oneMinusCos * zz) + cosSave;	this->rotationMatrix[14] = 0.0f;	this->rotationMatrix[3] = 0.0f;	this->rotationMatrix[7] = 0.0f;	this->rotationMatrix[11] = 0.0f;	this->rotationMatrix[15] = 1.0f;}void multiplyMatrix(Matrix m1, Matrix m2){	newMatrix[0]     = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];	newMatrix[4]     = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];	newMatrix[8]     = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];	newMatrix[12]    = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];	newMatrix[1]     = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];	newMatrix[5]     = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];	newMatrix[9]     = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];	newMatrix[13]    = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];	newMatrix[2]     = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];	newMatrix[6]     = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];	newMatrix[10]    = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];	newMatrix[14]    = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];	newMatrix[3]     = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];	newMatrix[7]     = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];	newMatrix[11]    = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];	newMatrix[15]    = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];     }

[Edited by - dawberj3 on April 20, 2006 12:19:30 PM]

##### Share on other sites
I would next try changing:
multiplyMatrix(previousMatrix, rotationMatrix);
To:
multiplyMatrix(rotationMatrix, previousMatrix);
It would also be a good idea to orthogonalize the rotation matrix at the end of each update (if your object is orienting more or less correctly but is slowly becoming stretched or distorted, this is probably the problem).

##### Share on other sites
ive tried that and the same happens. :(

The rotations are no where near close, they are either too small to notice or just wrong, (rotations are happening but in the wrong direction and very small)

This is annoying coz im following evryones instructions but they just dont work!!! grrr

What else could make it fail?

Thx

##### Share on other sites
Oop, one more thing: you're not normalizing the axis of rotation. You need to do it after you compute the angle, but before you construct the rotation matrix.

##### Share on other sites
WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!

That seemed to do the trick! Just a few little details that need tidying up to make it perfect.

but before I get too excited it has produced a problem that is probably easily fixable, when the object is moving around the curve, then I move the camera, the object vanishes! Any ideas?

Also can you explain how to orthonormalise the frame? I cant find anything that is useful on the net.

Thx Alot