# Parallel transport frame trouble

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

## 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&lt;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 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 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 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 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

1. 1
Rutin
26
2. 2
3. 3
4. 4
5. 5

• 11
• 10
• 13
• 20
• 14
• ### Forum Statistics

• Total Topics
632950
• Total Posts
3009384
• ### Who's Online (See full list)

There are no registered users currently online

×