Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: drawing an arrow: A line + a cone (problems with the cone, rotation!)

  1. #1
    Intern Contributor
    Join Date
    Aug 2011
    Posts
    76

    drawing an arrow: A line + a cone (problems with the cone, rotation!)

    What seems to be the problem with this rotation here (python-code) ?

    I'm drawing an arrow from (x1,y1,z2) to (x2,y2,z2). Please see this and I hope you can explain what is going on...
    Code :
    def coordSysArrow(x1, y1, z1, x2, y2, z2):
        glPushMatrix()
        glPushAttrib( GL_POLYGON_BIT ) # includes GL_CULL_FACE
        glDisable(GL_CULL_FACE) # draw from all sides
     
        # Size of cone in arrow:
        coneFractionAxially = 0.2
        coneFractionRadially = 0.1
     
        # Calculate cone parameters:
        v = numpy.array((x2-x1, y2-y1, z2-z1))
        norm_of_v = numpy.sqrt( numpy.dot(v,v) )
        coneHgt = coneFractionAxially * norm_of_v
        coneRadius = coneFractionRadially * norm_of_v
        vConeLocation = (1.0-coneFractionAxially) * v
     
        # Construct transformation matrix
        mat44 = numpy.eye(4)
        normalized_v = v/norm_of_v
     
        mat44[0,0] = normalized_v[0]
        mat44[1,1] = normalized_v[1]
        mat44[2,2] = normalized_v[2]
     
        # -----------------------
        #   Draw line + cone
        # -----------------------
        # Draw single line:
        glBegin(GL_LINES)
        glVertex3f(x1, y1, z1) # from
        glVertex3f(x2, y2, z2) # to
        glEnd() # GL_LINES
     
        # Move and rotate in position:
        glTranslate( *vConeLocation )
        if 0: # turn on/off here
            #glLoadIdentity()
            glMultMatrixf( mat44 ) #  <===== PROBLEM HERE?!?! WHAT?
     
        # Make a cone!
        cone_obj = gluNewQuadric();
        # gluCylinder(gluNewQuadr, Radius_base, Radius_top,
        #               height, slices, stacks)
        gluCylinder(cone_obj, 0, coneRadius,\
            coneHgt, 8, 1);
     
        glPopAttrib() # GL_CULL_FACE
        glPopMatrix()
    As you can see I've made an option to disable using the mat44-matrix. When I disable it, the cone gets drawn but the rotation is wrong. When I enable it, the cone is NOT drawn... Am I multiplying with a wrong rotation matrix and does that explain why nothing gets drawn?

    There are no errors/warnings or anything... I don't understand this...

  2. #2
    Intern Contributor
    Join Date
    Aug 2011
    Posts
    76
    Quote Originally Posted by newsb View Post
    There are no errors/warnings or anything... I don't understand this...
    Ok, to help myself and some of you, I've tried to make a complete program in C which you can compile and run:

    Code :
    // gcc arrowTest.c -lglut -lGLU && ./a.out//-------------------------
    #include <GL/glut.h>
    #include <math.h>
    #include <stdio.h>
     
    void coordSysArrow(float x1, float y1_, float z1, float x2, float y2, float z2)
    {
      glPushMatrix();
      glPushAttrib( GL_POLYGON_BIT ); // includes GL_CULL_FACE
      glDisable(GL_CULL_FACE); // draw from all sides
     
      float v[3];
      // Calculate arrow parameters:
      v[0] = x2-x1;
      v[1] = y2-y1_;
      v[2] = z2-z1;
     
      // Draw single line:
      glBegin(GL_LINES);
      glVertex3f(x1, y1_, z1); // from
      glVertex3f(x2, y2, z2); // to
      glEnd(); // GL_LINES
     
      // Easy enough - now let's make the cone in the arrow!
      if (1 == 1) // Make a cone! Change test to "0 == 1" to disable this part...
        {
          float norm_of_v = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
     
          // Size of cone in arrow:
          float coneFractionAxially = 0.2;
          float coneFractionRadially = 0.1;
     
          float coneHgt = coneFractionAxially * norm_of_v;
          float coneRadius = coneFractionRadially * norm_of_v;
     
          float normalized_v[3];
          normalized_v[0] = v[0] / norm_of_v;
          normalized_v[1] = v[1] / norm_of_v;
          normalized_v[2] = v[2] / norm_of_v;
     
          // Construct transformation matrix
          float mat44[16] =
            {1,0,0,0,
             0,1,0,0,
             0,0,1,0,
             0,0,0,1};
     
          mat44[0] = normalized_v[0]; // [0,0]
          mat44[5] = normalized_v[1]; // [1,1]
          mat44[10] = normalized_v[2]; // [2,2]
          mat44[15] = 1.0;
     
          if (0==1)
            {
              int i;
              for (i=0; i<16; i++)
                {
                  printf ("[%i]: %f\n", i, mat44[i]);
                }
              exit(EXIT_FAILURE);
            }
     
          float vConeLocation[3];
          vConeLocation[0] = (1.0-coneFractionAxially) * v[0];
          vConeLocation[1] = (1.0-coneFractionAxially) * v[1];
          vConeLocation[2] = (1.0-coneFractionAxially) * v[2];
     
          // Move and rotate in position:
          glTranslatef( vConeLocation[0], vConeLocation[1], vConeLocation[2] );
          if (0 == 1) //  <===== PROBLEM HERE?!?! WHAT?
            {
              //glLoadIdentity()
              glMultMatrixf( mat44 );
            }
          GLUquadric* cone_obj = gluNewQuadric();
          gluCylinder(cone_obj, 0, coneHgt, coneRadius, 8, 1);
        }
      glPopAttrib(); // GL_CULL_FACE
      glPopMatrix();
    }
     
    float x1 = 0.0; float y1_ = 0.0; float z1 = 0.0;
    float x2 = 1.0; float y2 = 1.0; float z2 = 0.0;
     
    void display()
    {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(0, 0, -5);
     
      glColor4ub(255,128,128,255); // red, green, blue, alpha
     
      int drawArrow = 1; // turn on/off here
      if (drawArrow == 1)
        coordSysArrow(x1, y1_, z1, x2, y2, z2);
      else {
        glBegin(GL_LINES);
        glVertex3f(x1, y1_, z1); // from
        glVertex3f(x2, y2, z2); // to
        glEnd(); // GL_LINES
      }
      glFlush();
      glutSwapBuffers();
    }
     
    void reshape(int w, int h)
    {
      glViewport(0, 0, w, h);
     
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective( 60, (double)w / (double)h, 0.01, 100 );
    }
     
    int main(int argc, char **argv)
    {
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
     
      glutInitWindowSize(800,600);
      glutCreateWindow("Arrowing");
     
      glutDisplayFunc(display);
      glutReshapeFunc(reshape);
      glutMainLoop();
      return EXIT_SUCCESS;
    }

    I don't understand why the cone doesn't get displayed correctly... I would REALLY appreciate some feedback, thank you... And now you should be able to copy/paste the code and run it (test on linux with gcc - I think windows would work out of the box too). You can then disable/enable the cone stuff (which I don't understand why is not working)...

    I hope to hear from someone soon. Thanks.

  3. #3
    Junior Member Regular Contributor
    Join Date
    Apr 2012
    Location
    Los Angeles
    Posts
    186
    I've run your code and had slightly better results than you.
    The cone does show up when I do glMultMatrixf (mat44).
    But it is not oriented or positioned properly.
    Make sure you're not calling glLoadIdentity before MultMatrix.
    That will definitely mess things up.

    I noticed that you have the ability to print out the contents of mat44.
    It's a good idea. When you do that do you get what you expected?
    Do you know what the contents of a rotation transformation matrix should look like?
    This can be Googled. Trig functions are involved.
    Do you know what axis you should be rotating the cone around to put it in the proper orientation?

    Did you know that you can use the glRotate command to accomplish what you
    are trying to do without ever messing around with matrices?

  4. #4
    Intern Contributor
    Join Date
    Aug 2011
    Posts
    76

    Cool

    Quote Originally Posted by Carmine View Post
    I've run your code and had slightly better results than you.
    The cone does show up when I do glMultMatrixf (mat44).
    But it is not oriented or positioned properly.
    Oh, sorry... After many hours and after having read and thought about what you wrote, I realized that my way of getting the mat44-matrix is completely nonsense... I had it mixed up with something else in my head... Sorry...
    Make sure you're not calling glLoadIdentity before MultMatrix.
    That will definitely mess things up.
    Ok, thank you - you're right - I understand...
    I noticed that you have the ability to print out the contents of mat44.
    It's a good idea. When you do that do you get what you expected?
    Do you know what the contents of a rotation transformation matrix should look like?
    This can be Googled. Trig functions are involved.
    Do you know what axis you should be rotating the cone around to put it in the proper orientation?
    I think I can do it without using trig functions, but by using cross products... I've done something similar another time before, let me look into my old code and get back within 1-2 days...
    Did you know that you can use the glRotate command to accomplish what you
    are trying to do without ever messing around with matrices?
    As I wrote - I found out that I cannot construct mat44 like I do it now. I typically/usually get an invalid rotation matrix by using the method I've shown here. That explains why python didn't show anything. However, it doesn't explain why the C-code shows something... hmmmmmm. Strange C-code.... I don't understand why it shows anything at all because that transformation/rotation matrix I've made is simply nonsense with invalid directions - for instance, here is something from my python program:

    (1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)
    (1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)

    NONSENSE - invalid directions!

    I'm very happy that you took the time to write a few things - just these small things made me think a lot and spend hours remembering how I one solved a similar problem... I'll go to bed now and go to work tomorrow, but within 1-2 days I'll get back and write how I think this can be solved in an elegant way...

    Thank you very much - I appreciate your help - I think I'm on the right track again now, after having been stuck for some days with this now !

    I'll get back with a solution - for the record - now people are helping me, so I want to give something back too, that others can/might use...

  5. #5
    Junior Member Regular Contributor
    Join Date
    Apr 2012
    Location
    Los Angeles
    Posts
    186
    Yes. You could do this with some vector cross products, normalization, etc.

  6. #6
    Newbie Newbie
    Join Date
    Dec 2012
    Posts
    2
    Chuc mung nam moi
    Chuc vui ve va hanh phuc
    Tiep tuc xay dung dien dan cua chung toi nhe
    Best regards.

  7. #7
    Intern Contributor
    Join Date
    Aug 2011
    Posts
    76
    Quote Originally Posted by gvtheogioC View Post
    Chuc mung nam moi
    Chuc vui ve va hanh phuc
    Tiep tuc xay dung dien dan cua chung toi nhe
    Best regards.
    Please write in english...

  8. #8
    Intern Contributor
    Join Date
    Aug 2011
    Posts
    76
    Quote Originally Posted by Carmine View Post
    Yes. You could do this with some vector cross products, normalization, etc.
    Thanks a lot for your help, Carmine. Just for the record, here's my python solution so other people can use if they like. If anyone modifies my original C-program to work with this, please post the code. It should be a VERY small task for anyone to rewrite this python-code into the equivalent C-code.

    Code :
    def constructRotMatrixFromDirection(dVec):
        norm_startVec = dVec / norm(dVec)
        zaxis = [0, 0, 1]
        norm_endVec = zaxis / norm(zaxis)
        if numpy.isnan(norm_endVec).any():
            norm_endVec = numpy.zeros( numpy.shape(norm_endVec) )
            ipdb.set_trace()
     
        # Check if trying to match identital vectors:
        if not ( any(norm_startVec - norm_endVec) > 1e-14 ):
            return numpy.eye(4)
     
        axb = cross(norm_startVec, norm_endVec) # cross-product of a and b
        norm_axb = axb / norm(axb)
        if numpy.isnan(norm_axb).any():
            norm_axb = numpy.zeros( numpy.shape(norm_axb) )
            ipdb.set_trace()
     
        ac = math.acos(numpy.dot(norm_startVec, norm_endVec))
        # build the rotation matrix
        s = math.sin( ac )
        c = math.cos( ac )
        t = 1 - c
     
        x = norm_axb[0]
        y = norm_axb[1]
        z = norm_axb[2]
     
        mat33 = [ \
           [t*x*x + c,    t*x*y - s*z,  t*x*z + s*y], \
           [t*x*y + s*z,  t*y*y + c,    t*y*z - s*x], \
           [t*x*z - s*y,  t*y*z + s*x,  t*z*z + c], \
           ]
        return expand33to44(mat33)
    Anyway, thanks all - use the transformation matrix as described above, and it'll work. I'll continue with my other problems now - problem is solved now :-)

    If you have any questions to the above, feel free to ask...

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •