Problem with Crossproduct for perpendicular using ofxVec3f

Hi,

I am currently working on some ribbon code which is actually pretty simple but I am having some trouble since I really suck when it comes to trigonometry. What I want to do is that the ribbon always faces the direction where its going. So I thought I simply take each element of the ribbon and compute the perpendicular vector with the next element of the ribbon like this:

  
glBegin(GL_QUAD_STRIP);  
for(int i=0; i<LENGTH; i++){  
float xO, yO, zO;  //offset variables  
if ( i < LENGTH - 1 ){   
ofxVec3f perp0 = pos[i]-pos[i+1];  //vector between current element and the next one  
  
//I am not sure about this part but as far as I can tell this should give me the correct perpendicular vector for what I want to do  
ofxVec3f perp1 = perp0.perpendiculared(pos[i]);   
perp0 = perp0.perpendiculared(perp1);  
  
// Compute the offset values  
 xO       = perp1.x * radius;    
 yO       = perp1.y * radius;  
 zO       = perp1.z * radius;  
  
glVertex3f(pos[i].x-xO, pos[i].y-yO, pos[i].z-zO);  
glVertex3f(pos[i].x+xO, pos[i].y+yO, pos[i].z+zO);  
}  
}  
glEnd();  
  

the results I get are kind of what I want to have but with some weird bugs. Does anybody know what could be wrong? here is an image of my result:

http://stuff.mokafolio.de/of/shot.jpg

As you can see most of the vertices look just fine but at some points something goes completely wrong. And I can’t figure out what or why.

Thanks in advance!

I have some code laying around for doing essentially the same:

  
  
        glBegin( GL_TRIANGLE_STRIP );  
        for(int i=0; i<vertices.size(); i++) {  
            ofxVec2f normal;  
            if( i == 0) {  
                normal.set(0, 1);  
            } else {  
                normal = vertices[i].perpendicular(vertices[i-1]);  
            }  
              
            ofxPoint2f normalPoint =   
                vertices[i] + normal*thickVals[i];  
            ofxPoint2f normalPointInv =   
                vertices[i] - normal*thickVals[i];  
              
            glColor3f( vcolors[i].x, vcolors[i].y, vcolors[i].z );  
              
            //glVertex2f(vertices[i].x, vertices[i].y);              
            glVertex2f(normalPoint.x, normalPoint.y);  
            glVertex2f(normalPointInv.x, normalPointInv.y);  
            //glVertex2f(vertices[i].x, vertices[i].y);  
        }  
        glEnd();  
  

This also uses variable thickness but you can just substitute that for a fixed value.

first of all thank you. Anyways my ofxVec2f does not have a function perpendicular(ofVec2f bla); with any parameter. What version do you have?

My code was written against the one that comes with OF v0.05 FAT. In that version you will see two versions of many methods. One (not ending in -ed) works on the vector in place the other one (ending in -ed) returns a new vector with the results.

There is a error in the current version of ofxVec2f.h as far as I can see. It says

  
      
ofxVec2f& perpendicular() {  
        float length = (float)sqrt( x*x + y*y );  
        if( length > 0 ) {  
            x = -(y/length);  
            y = x/length;  
        }  
        return *this;  
    }  
  

but should be

  
  
    ofxVec2f& perpendicular() {  
        float length = (float)sqrt( x*x + y*y );  
        if( length > 0 ) {  
            float _x = x;  
            float _y = y;  
            x = -(_y/length);  
            y = _x/length;  
        }  
        return *this;  
    }  
  

Right, and 1+1 = 3.
Don’t take it personally but may I ask what planet you are coming from?

Huh?

If you take the current code, then you first set x = - y/length, and then take y = x/length… But you just changed x to be something with y, so you actually only use y…

cmon man, simple math… Don’t make this hard on yourself and just go with the flow. Idiot…

You can try to use the code yourself :slight_smile:

Lets say i got
x = 2
y = 4
length = 1

then if i use the current code, i will get

x = -(y/length) = -(4/1) = -4
y = x/length = -4/1 = -4

and thats wrong… it should be

x = -(4/1) = -4
y = 2/1 = 2

But i will admit its the wrong post… it just reminded me that i had seen the bug…

I think I can see it now. You got me confused with the ‘float _y = y’ though. The following should do the trick:

  
  
    ofxVec2f& perpendicular() {   
        float length = (float)sqrt( x*x + y*y );   
        if( length > 0 ) {   
            float _x = x;   
            x = -(y/length);   
            y = _x/length;   
        }   
        return *this;   
    }   
  

You are right that it only needs one of them. I was beginning to think that i really had messed my basic programming math up :stuck_out_tongue:

hi guys,

I just realised that my code works aswell if you want to put the whole thing into 3 dimensions. The problem was that I made the ribbon follow the mouse which kinda resulted in the weird behaviour for some reason. If I make it move to perlin noise or sin / cos everything works just fine.

Thanks for the bug fix in ofxVec2f :slight_smile:

hi. you already got this working, but another way to do this would be something like this

(some code just to calculate the offset)

  
  
  
float angle = atan2(pos[i+1].y - pos[i].y, pos[i+1].x - pos[i].x);  
float offSetY = -cos(angle)*radius; //minus because positive y goes down  
float offSetX = sin(angle)*radius;  
  
  

Yeah I thought about using atan2 too, but I always get confused about the way using it. But I think it’s good to see that there are different ways for the same goal. I think it would be interesting to know which way is faster though!