Rotate ofVec3f with forward and up vectors

Hey All

I have a spline with forward and up vectors that’s looking very nice thanks to the techniques laid out in Nick Hardeman’s post here:

http://forum.openframeworks.cc/t/render-worm-body-tube/3383/0

I’m trying to make a series of ofPolyLine rings with the aim of building a 3D tube. Each ring points in the direction of the next spline point using ofMatrix4x4 objects. My only problem is that I can’t seem to get the rings to align with the up vector. If you look at the screenshots below, the yellow lines are the up vecs, the green line are the forward vecs and the purple spheres occupy the positions of the first vec in each ring. These spheres should align with the up vector but I can’t find the solution.

I saw the LookAt methods of the ofMatrix4x4 class (newLookAtMatrix, makeLookAtMatrix etc). These methods accept an up vector but don’t help in this situation.

My current update function is below. Any help would be greatly appreciated.

  
  
void Tube::generate(vector <ofPoint> pts, float width)  
{  
    for (int i = 0; i < pts.size() - 1; i++)  
    {  
        ofPolyline pLine;  
        SplinePoint splinePt;  
        ofVec3f forwardVec;  
        ofVec3f sideVec;  
        ofVec3f upVec = ofVec3f(0, 1, 0);  
          
        splinePt.position = pts[i];  
        if (i == 0)  
        {  
            forwardVec = (pts[1] - pts[0]).getNormalized();  
            sideVec = forwardVec.crossed(upVec).getNormalized();  
            upVec = forwardVec.crossed(sideVec).getNormalized();  
        }  
        else if (i > 0 && i < pts.size() - 1)  
        {  
              
            ofVec3f T1 = splinePoints[i-1].position;  
            ofVec3f T2 = splinePoints[i].position;  
            ofVec3f A = T1.crossed(T2);  
            float alpha = T1.angleRad(T2);  
              
            forwardVec = (pts[i+1] - pts[i]).getNormalized();  
              
            upVec = splinePoints[i-1].upVec * -1;  
            upVec.normalize();  
            upVec.rotateRad(alpha, A);  
            sideVec = forwardVec.crossed(upVec);  
            upVec = forwardVec.crossed(sideVec);  
        }  
        else  
        {  
            forwardVec = (pts[i] - pts[i-1]).getNormalized();  
        }  
          
        splinePt.forwardVec = forwardVec;  
        splinePt.sideVec = sideVec;  
        splinePt.upVec = upVec;  
          
        ofMatrix4x4 matRotation;  
        // make rotation matrix. the first vec3 is the starting reference of the ring before rotation.  
        // Basically it will be facing forward  
        matRotation.makeRotationMatrix(ofVec3f(0,0,1), forwardVec);  
          
		// I've tried all these without success  
        //matRotation.getLookAt(position, pts[i+1], upVec);  
        //matRotation.makeLookAtMatrix(position, pts[i+1], upVec);  
        //matRotation.makeLookAtViewMatrix(position, pts[i+1], upVec);  
        //matRotation.newLookAtMatrix(position, pts[i+1], upVec);  
          
        ofMatrix4x4 matTranslation;  
        matTranslation.makeTranslationMatrix(splinePt.position); //translate from origin  
          
		//combine the rotation and position matrices  
        ofMatrix4x4 mat;   
        mat = matRotation * matTranslation;  
          
        int ringSegments = 12;  
        for (int j = 0; j < ringSegments; j++)  
        {  
            float angle = (TWO_PI / ringSegments) * j;  
            ofPoint pt = pts[i];  
            ofPoint ringPoint;// = pt;  
              
            //ring facing forward  
            ringPoint.x = sin(angle) * width;  
            ringPoint.y = cos(angle) * width;  
              
            ofVec3f ringPointTransformed = ringPoint * mat;  
              
            pLine.addVertex(ringPointTransformed);  
        }  
        splinePoints.push_back(splinePt);  
        rings.push_back(pLine);  
    }  
}  
  
  

Hey there fellow James :wink:

I’m in a rush so didn’t have a chance to look at your code, but I had a non-optimized PTF implementation to create vboMesh tubes along a polyline lying around. The PTF implementation I used is a combo of how Nick H implemented his and tips I got from Roxlu’s PTF implementation.

You’re welcome to use this code in any way - hopefully it gives a hint to what’s happening. Always a pain to debug this stuff!

https://gist.github.com/jacres/5007633


Thanks very James that’s really useful. I’ll take a proper look later.

I’m still a little perplexed as to how to use the lookAt functions in the ofMatrix4x4 class. Can anyone shine some light on this? I feel like I’m just 1 or 2 lines of code away from achieving the proper rotation.

Hi James,

I have rotated the up vector around the forward to achieve a ring. Since you already have the up vector and want the sphere aligned with it. Why not just use that as the starting point. Here is some pseudo code

  
  
int ringSegments = 12;    
float angleInc = TWO_PI / (float)ringSegments;  
// use the upVec from the splinePt as the starting point  
ofVec3f crossVec = upVec; // per splinePt;  
crossVec.normalize();  
crossVec *= radius;  
for (int j = 0; j < ringSegments; j++)    
{      
    ofPoint pt = pts[i];            
    // at the location to the rotated vector //    
    ofVec3f ringPointTransformed = crossVec + pts[i];    
    pLine.addVertex(ringPointTransformed);   
    // incrementally rotate around the forward vector //  
    crossVec.rotate(angleInc, forwardVec);  
}  
  

Simple and effective solution Nick. Can’t believe I didn’t think of that. Thanks man I owe you one.

Here’s my PTF addon - https://github.com/neilmendoza/ofxPtf - although maybe not relevant if you want the up vectors to align…