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: drawing an arrow: A line + a cone (problems with the cone, rotation!) - OpenGL: Basic Coding - Khronos Forums
which gives only correct Python code for drawing an arrow, but the thread is now closed.

Here is the complete C 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;
}