Sign in to follow this  

Parallel transport frame trouble

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Following http://www.gamedev.net/community/forums/topic.asp?topic_id=388483 about the parallel transport frame I've been struggling with my project for 3 consecutive nights now getting my rotations right. As far as I can tell I'm doing exactly what drawberj3 is doing however my rotations just won't get right.

It's in JAVA and mSpineIndices is an array of floats that in groups of 3 hold the [x,y,z] for the ring positions. Looping through that from 0 .. mSpineIndices.length/3 I am calling addRing. The rings are positioned perfectly on the spline, but the rotations are all wrong.. see this image showing the tube-to-be in different angles.

http://img43.imageshack.us/img43/9492/rotationx.jpg


private void addRing( float[] ringVertices, int pos, float radius, int segments) {

if(pos == 0 || pos == mSpineIndices.length - 1) return;

float[] V1 = getVector( mSpineVertices[pos*3], mSpineVertices[pos*3+1], mSpineVertices[pos*3+2],
mSpineVertices[pos*3-3], mSpineVertices[pos*3-2], mSpineVertices[pos*3-1]);

float[] V2 = getVector( mSpineVertices[pos*3+3], mSpineVertices[pos*3+4], mSpineVertices[pos*3+5],
mSpineVertices[pos*3], mSpineVertices[pos*3+1], mSpineVertices[pos*3+2]);

float[] V3 = getCrossProduct(V1, V2);

float angle = (float) Math.atan2(getVectorMagnitude(V3), getDotProduct(V1, V2));
normalizeVector(V3);

float[] matrix = createRotationMatrix(angle, V3[0], V3[1], V3[2]);
if(mPrevMatrix != null) matrix = multiplyMatrix(matrix, mPrevMatrix);

matrix[12] = mSpineVertices[pos*3];
matrix[13] = mSpineVertices[pos*3+1];
matrix[14] = mSpineVertices[pos*3+2];

float fX;
float fY;
float fZ;
float deg;

pos = pos * segments * 3;

for(int i = 0; i<segments; i++){

deg = i * (360/segments);

fX = radius * (float) Math.cos(Math.toRadians(deg));
fY = radius * (float) Math.sin(Math.toRadians(deg));
fZ = 0;

ringVertices[pos + i*3] = (float) (matrix[0]*fX + matrix[4]*fY + matrix[8]*fZ + matrix[12]);
ringVertices[pos + i*3 + 1] = (float) (matrix[1]*fX + matrix[5]*fY + matrix[9]*fZ + matrix[13]);
ringVertices[pos + i*3 + 2] = (float) (matrix[2]*fX + matrix[6]*fY + matrix[10]*fZ + matrix[14]);
}

mPrevMatrix = matrix;
}

private float[] createRotationMatrix(float angle, float x, float y, float z){

float[] matrix = new float[16];
float sinSave, cosSave, oneMinusCos;
float xx, yy, zz, xy, yz, zx, xs, ys, zs;

if(x == 0.0f && y == 0.0f && z == 0.0f) return matrix;

sinSave = (float) Math.sin(angle);
cosSave = (float) Math.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;

matrix[0] = (oneMinusCos * xx) + cosSave;
matrix[4] = (oneMinusCos * xy) - zs;
matrix[8] = (oneMinusCos * zx) + ys;
matrix[12] = 0.0f;

matrix[1] = (oneMinusCos * xy) + zs;
matrix[5] = (oneMinusCos * yy) + cosSave;
matrix[9] = (oneMinusCos * yz) - xs;
matrix[13] = 0.0f;

matrix[2] = (oneMinusCos * zx) - ys;
matrix[6] = (oneMinusCos * yz) + xs;
matrix[10] = (oneMinusCos * zz) + cosSave;
matrix[14] = 0.0f;

matrix[3] = 0.0f;
matrix[7] = 0.0f;
matrix[11] = 0.0f;
matrix[15] = 1.0f;

return matrix;
}

private float[] multiplyMatrix(float[] m1, float[] m2) {

float[] newMatrix = new float[16];

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];

return newMatrix;
}


private float getVectorMagnitude(float[] v){

return (float) Math.sqrt((v[0]*v[0]) + (v[1]*v[1]) + (v[2]*v[2]));
}

private void normalizeVector(float[] v) {

float len = getVectorMagnitude(v);
v[0] /= len;
v[1] /= len;
v[2] /= len;
}

private float getDotProduct(float[] v1, float[] v2) {

return (v1[0]*v2[0]) + (v1[1]*v2[1]) + (v1[2]*v2[2]);
}

private float[] getAverageVector(float[] v1, float[] v2) {

return new float[] {(v1[0] + v2[0])/2, (v1[1] + v2[1])/2, (v1[2] + v2[2])/2};
}

private float[] getCrossProduct(float[] v1, float[] v2) {

return new float[] {v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]};
}

private float[] getVector(float x1, float y1, float z1, float x2, float y2, float z2) {

return new float[] {x2-x1, y2-y1, z2-z1};
}



[Edited by - m6246 on December 23, 2010 9:23:00 PM]

Share this post


Link to post
Share on other sites
Obviously I had to switch the row/column order on my matrix. This results in the following

http://img838.imageshack.us/img838/4315/rotation.jpg

so the rings seem to follow the spline just fine, however it looks like they need a 90 degrees rotation on them. How would I achieve that?

Share this post


Link to post
Share on other sites
Not sure why the rings are 90 degrees off, unless maybe you've built them incorrectly in local space.

If you're still having trouble with this, perhaps you could repost your code using 'source' tags.

Share this post


Link to post
Share on other sites
oops, didn't know of those tags. *Updated*

BTW, i find it really special to have -of all people- the very same expert answering after nearly 6 years the original topic was posted ;)

Share this post


Link to post
Share on other sites
Thanks for pointing that out, I went from this


fX = radius * (float) Math.cos(Math.toRadians(deg));
fY = radius * (float) Math.sin(Math.toRadians(deg));
fZ = 0;




to this


fX = radius * (float) Math.cos(Math.toRadians(deg));
fZ = radius * (float) Math.sin(Math.toRadians(deg));
fY = 0;




and now the rings have the correct rotation
http://img189.imageshack.us/img189/7461/rotationm.jpg

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this