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

• 08-22-2013, 05:49 AM
wall-e
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!)"
```// 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; }```