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 1 of 1

Thread: FYI: C code for drawing a line & 3D arrow head

Hybrid View

  1. #1
    Newbie Newbie
    Join Date
    Aug 2013
    Posts
    1

    Lightbulb FYI: C code for drawing a line & 3D arrow head

    Hi all,
    This is my first post. I must say this forum is very un-friendly to new users. Users seem to have Private Messages disabled by default, and my Control Panel says "access denied" when I try to re-enable them for my account.
    And of course no links or images allowed, which prevents spam, but makes it difficult to post an image showing the problem/solution!
    Then when I wrote this post, I clicked "preview" and got an error message about "too many links", then all my text was deleted. Well done Admins.


    For reference purposes, here is some C code for drawing a line and 3D arrow head.
    The result: www.postimg.org/image/sz13ngmq7/

    This is a continuation of this thread:
    "drawing an arrow: A line + a cone (problems with the cone, rotation!)"
    Link: http://www.opengl.org/discussion_boa...e-rotation!%29
    which gives only correct Python code for drawing an arrow, but the thread is now closed.


    Here is the complete C code:

    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)
    {
     
            // Co-ordinates of the line are
            // start: xyz_1
            // end: xyz_2
     
    	glPushMatrix();
    	glPushAttrib( GL_POLYGON_BIT ); // includes GL_CULL_FACE
    	glDisable(GL_CULL_FACE); // draw from all sides
     
    	// Calculate vector along direction of line
    	float v[3];
    	v[0] = x2-x1;
    	v[1] = y2-y1;
    	v[2] = z2-z1;
     
    	// Line thickness
    	glLineWidth(2);
     
    	// Draw single line:
    	glBegin(GL_LINES);
     
    	//glVertex3f(x1, y1, z1); // Starting point for line (arrow head end)
    	glVertex3f( x1+0.05*v[0], y1+0.05*v[1], z1+0.05*v[2] ); // Make the line a bit shorter,
    	glVertex3f(x2, y2, z2);        // so the arrowhead is not blunted by the line thickness
    	glEnd(); // GL_LINES
     
            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.025; // radius at thickest part
            float coneFractionRadially = 0.12; // length of arrow
     
            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;
     
            // Set location of arrowhead to be at the startpoint of the line
            float vConeLocation[3];
            //vConeLocation[0] = (1.0-coneFractionAxially) * v[0]; // <---- ORIGINAL CODE
            //vConeLocation[1] = (1.0-coneFractionAxially) * v[1];
            //vConeLocation[2] = (1.0-coneFractionAxially) * v[2];
            vConeLocation[0] = x1;
            vConeLocation[1] = y1;
            vConeLocation[2] = z1;
     
            // Initialize transformation matrix
            float mat44[16] =
                {1,0,0,0,
                 0,1,0,0,
                 0,0,1,0,
                 0,0,0,1};
     
            // The direction of the arrowhead is the line vector
            float dVec[3];
            dVec[0] = v[0]; // 0.5;
            dVec[1] = v[1]; // 0.5;
            dVec[2] = v[2]; // 0.5;
     
            // Normalize dVec to get Unit Vector norm_startVec
            float norm_startVec[3];
            Unit( dVec, norm_startVec );
     
            // Normalize zaxis to get Unit Vector norm_endVec
            float zaxis[3] = { 0.0, 0.0, 1.0 };
            float norm_endVec[3];
            Unit( zaxis, norm_endVec );
     
            if ( isnan(norm_endVec[0]) || isnan(norm_endVec[1]) || isnan(norm_endVec[2]) )
            {
                norm_endVec[0] = 0.0;
                norm_endVec[1] = 0.0;
                norm_endVec[2] = 0.0;
            }
     
            // If vectors are identical, set transformation matrix to identity
            if ( ((norm_startVec[0] - norm_endVec[0]) > 1e-14) && ((norm_startVec[1] - norm_endVec[1]) > 1e-14) && ((norm_startVec[2] - norm_endVec[2]) > 1e-14) )
            {
                mat44[0] = 1.0;
                mat44[5] = 1.0;
                mat44[10] = 1.0;
                mat44[15] = 1.0;
            }
            // otherwise create the matrix
            else
            {
     
                // Vector cross-product, result = axb
                float axb[3];
                Cross(norm_startVec, norm_endVec, axb);
     
                // Normalize axb to get Unit Vector norm_axb
                float norm_axb[3];
                Unit( axb, norm_axb );
     
                if ( isnan(norm_axb[0]) || isnan(norm_axb[1]) || isnan(norm_axb[2]) )
                {
                    norm_axb[0] = 0.0;
                    norm_axb[1] = 0.0;
                    norm_axb[2] = 0.0;
                }
     
                // Build the rotation matrix
                float ac = acos( Dot(norm_startVec, norm_endVec) );
     
                float s = sin( ac );
                float c = cos( ac );
                float t = 1 - c;
     
                float x = norm_axb[0];
                float y = norm_axb[1];
                float z = norm_axb[2];
     
                // Fill top-left 3x3
                mat44[0] = t*x*x + c;
                mat44[1] = t*x*y - s*z;
                mat44[2] = t*x*z + s*y;
     
                mat44[4] = t*x*y + s*z;
                mat44[5] = t*y*y + c;
                mat44[6] = t*y*z - s*x;
     
                mat44[8] = t*x*z - s*y;
                mat44[9] = t*y*z + s*x;
                mat44[10] = t*z*z + c;
     
                mat44[15] = 1.0;
    	    }
     
            // Translate and rotate arrowhead to correct position
            glTranslatef( vConeLocation[0], vConeLocation[1], vConeLocation[2] );
            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;
    }
    Last edited by wall-e; 08-22-2013 at 05:52 AM. Reason: link

Posting Permissions

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