#include #include #include #include // size of wings as fraction of length: #define WINGS 0.10 // axes: #define X 1 #define Y 2 #define Z 3 // x, y, z, axes: static float axx[3] = { 1., 0., 0. }; static float ayy[3] = { 0., 1., 0. }; static float azz[3] = { 0., 0., 1. }; // function declarations: void Arrow( float [3], float [3] ); void Cross( float [3], float [3], float [3] ); float Dot( float [3], float [3] ); float Unit( float [3], float [3] ); void Arrow( float tail[3], float head[3] ) { float u[3], v[3], w[3]; // arrow coordinate system // set w direction in u-v-w coordinate system: w[0] = head[0] - tail[0]; w[1] = head[1] - tail[1]; w[2] = head[2] - tail[2]; // determine major direction: int axis = X; float mag = fabs( w[0] ); float f = fabs( w[1] ); if( f > mag ) { axis = Y; mag = f; } f = fabs( w[2] ); if( f > mag ) { axis = Z; mag = f; } // set size of wings and turn w into a unit vector: float d = WINGS * Unit( w, w ); // draw the shaft of the arrow: glBegin( GL_LINE_STRIP ); glVertex3fv( tail ); glVertex3fv( head ); glEnd( ); // draw two sets of wings in the non-major directions: float x, y, z; // points to plot to if( axis != X ) { Cross( w, axx, v ); (void) Unit( v, v ); Cross( v, w, u ); x = head[0] + d * ( u[0] - w[0] ); y = head[1] + d * ( u[1] - w[1] ); z = head[2] + d * ( u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); x = head[0] + d * ( -u[0] - w[0] ); y = head[1] + d * ( -u[1] - w[1] ); z = head[2] + d * ( -u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); } if( axis != Y ) { Cross( w, ayy, v ); (void) Unit( v, v ); Cross( v, w, u ); x = head[0] + d * ( u[0] - w[0] ); y = head[1] + d * ( u[1] - w[1] ); z = head[2] + d * ( u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); x = head[0] + d * ( -u[0] - w[0] ); y = head[1] + d * ( -u[1] - w[1] ); z = head[2] + d * ( -u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); } if( axis != Z ) { Cross( w, azz, v ); (void) Unit( v, v ); Cross( v, w, u ); x = head[0] + d * ( u[0] - w[0] ); y = head[1] + d * ( u[1] - w[1] ); z = head[2] + d * ( u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); x = head[0] + d * ( -u[0] - w[0] ); y = head[1] + d * ( -u[1] - w[1] ); z = head[2] + d * ( -u[2] - w[2] ); glBegin( GL_LINE_STRIP ); glVertex3fv( head ); glVertex3f( x, y, z ); glEnd( ); } } float Dot( float va[3], float vb[3] ) { return( va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2] ); } void Cross( float va[3], float vb[3], float vout[3] ) { float tmp[3]; tmp[0] = va[1]*vb[2] - vb[1]*va[2]; tmp[1] = vb[0]*va[2] - va[0]*vb[2]; tmp[2] = va[0]*vb[1] - vb[0]*va[1]; vout[0] = tmp[0]; vout[1] = tmp[1]; vout[2] = tmp[2]; } float Unit( float vin[3], float vout[3] ) { float dist = vin[0]*vin[0] + vin[1]*vin[1] + vin[2]*vin[2]; if( dist > 0.0 ) { dist = sqrt( dist ); vout[0] = vin[0] / dist; vout[1] = vin[1] / dist; vout[2] = vin[2] / dist; } else { vout[0] = vin[0]; vout[1] = vin[1]; vout[2] = vin[2]; } return dist; }