World of Rigid Bodies (WoRB)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Utilities.cpp
Go to the documentation of this file.
00001 /**
00002  *  @file      Utilities.cpp
00003  *  @brief     Implementation of the various GLUT utilites used
00004  *             by the rigid body test-bed application.
00005  *  @author    Mikica Kocic
00006  *  @version   0.5
00007  *  @date      2012-05-08
00008  *  @copyright GNU Public License.
00009  */
00010 
00011 #include "Utilities.h"
00012 
00013 #include <cstdlib>      // rand
00014 #include <cstdio>       // vsprintf
00015 #include <cstdarg>      // va_list
00016 #include <algorithm>    // min/max
00017 
00018 using namespace WoRB;
00019 
00020 /////////////////////////////////////////////////////////////////////////////////////////
00021 
00022 // Gets a uniform real number in range [0,1)
00023 //
00024 double WoRB::RandomReal () 
00025 { 
00026     return double( rand() ) / RAND_MAX;
00027 };
00028 
00029 // Gets a quaternion with the given length but with random orientation.
00030 //
00031 Quaternion WoRB::RandomQuaternion( double length )
00032 {
00033     return Quaternion( RandomReal (), RandomReal (), RandomReal (), RandomReal () )
00034            .Normalize( length );
00035 }
00036 
00037 // Gets a random quaternion uniformly distributed in a 4D box
00038 //
00039 Quaternion WoRB::RandomQuaternion( const Quaternion& min, const Quaternion& max )
00040 {
00041     return Quaternion(
00042         min.w + ( max.w - min.w ) * RandomReal (),
00043         min.x + ( max.x - min.x ) * RandomReal (),
00044         min.y + ( max.y - min.y ) * RandomReal (),
00045         min.z + ( max.z - min.z ) * RandomReal ()
00046     );
00047 }
00048 
00049 /////////////////////////////////////////////////////////////////////////////////////////
00050 
00051 // Renders the given text to the given location in body-fixed space.
00052 //
00053 void WoRB::RenderText( double x, double y, double z, const char* text )
00054 {
00055     void* font = GLUT_BITMAP_TIMES_ROMAN_10;
00056 
00057     // Loop through characters displaying them.
00058     //
00059     glRasterPos3d( x, y, z );
00060     for( const char* ch = text; *ch; ++ch ) 
00061     {
00062         if ( *ch == '\n' ) {
00063             // If we meet a newline, then move down by the line-height
00064             y -= glutBitmapHeight( font ) * 1.2;
00065             glRasterPos3d( x, y, z );
00066         }
00067         glutBitmapCharacter( font, *ch );
00068     }
00069 }
00070 
00071 /////////////////////////////////////////////////////////////////////////////////////////
00072 
00073 // Draws the geometry axes, angular velocity and angular momentum
00074 //
00075 void WoRB::RenderStateVariables( const RigidBody& body, const Quaternion& extent )
00076 {
00077     double maxExtent = std::max( extent.x, std::max( extent.y, extent.z ) ) * 1.2;
00078 
00079     Quaternion pos = body.Position;
00080     Quaternion w = body.AngularVelocity;
00081     Quaternion L = body.AngularMomentum;
00082 
00083     glLineWidth( 2 );
00084 
00085     /////////////////////////////////////////////////////////////////////////////////////
00086     // Display angular velocity
00087 
00088     if ( w.ImSquaredNorm () > 1e-3 ) {
00089         w.Normalize( maxExtent );
00090         glColor3d( 0, 0, 0 );
00091         glBegin( GL_LINES );
00092         glVertex3d( pos.x, pos.y, pos.z );
00093         glVertex3d( pos.x + w.x, pos.y + w.y, pos.z + w.z );
00094         glEnd ();
00095 
00096         RenderText( pos.x + w.x, pos.y + w.y * 1.08, pos.z + w.z, "w" );
00097     }
00098 
00099     /////////////////////////////////////////////////////////////////////////////////////
00100     // Display angular momentum
00101 
00102     if ( L.ImSquaredNorm () > 1e-3 ) {
00103         L.Normalize( maxExtent );
00104         glColor3d( 0.5, 0.5, 0.5 );
00105         glBegin( GL_LINES );
00106         glVertex3d( pos.x, pos.y, pos.z );
00107         glVertex3d( pos.x + L.x, pos.y + L.y, pos.z + L.z );
00108         glEnd ();
00109 
00110         RenderText( pos.x + L.x, pos.y + L.y * 1.08, pos.z + L.z, "L" );
00111     }
00112 
00113     glLineWidth( 1 );
00114 
00115     GLTransform bodySpace( body );
00116 
00117     /////////////////////////////////////////////////////////////////////////////////////
00118     // Display body's X-axis
00119 
00120     glColor3d( 0.8, 0, 0 );
00121     glBegin( GL_LINES );
00122     glVertex3d( 0, 0, 0 );
00123     glVertex3d( extent.x, 0, 0 );
00124     glEnd ();
00125     RenderText( extent.x * 1.07, 0, 0, "X" );
00126 
00127     /////////////////////////////////////////////////////////////////////////////////////
00128     // Display body's Y-axis
00129 
00130     glColor3d( 0, 0.6, 0 );
00131     glBegin( GL_LINES );
00132     glVertex3d( 0, 0, 0 );
00133     glVertex3d( 0, extent.y, 0 );
00134     glEnd ();
00135     RenderText( 0, extent.y * 1.07, 0, "Y" );
00136 
00137     /////////////////////////////////////////////////////////////////////////////////////
00138     // Display body's Z-axis
00139 
00140     glColor3d( 0, 0, 0.8 );
00141     glBegin( GL_LINES );
00142     glVertex3d( 0, 0, 0 );
00143     glVertex3d( 0, 0, extent.z );
00144     glEnd ();
00145     RenderText( 0, 0, extent.z * 1.07, "Z" );
00146 }
00147 
00148 /////////////////////////////////////////////////////////////////////////////////////////
00149 
00150 // Draws the world axes
00151 //
00152 void WoRB::RenderAxes( double length )
00153 {
00154     glLineWidth( 2 );
00155 
00156     /////////////////////////////////////////////////////////////////////////////////////
00157     // Display X-axis for the world
00158 
00159     glColor3d( 1, 0, 0 );
00160     glBegin( GL_LINES );
00161     glVertex3d( 0, 0, 0 );
00162     glVertex3d( length, 0, 0 );
00163     glEnd ();
00164     RenderText( length + 0.3, 0, 0, "X" );
00165 
00166     /////////////////////////////////////////////////////////////////////////////////////
00167     // Display Y-axis for the world
00168 
00169     glColor3d( 0, 0.8, 0 );
00170     glBegin( GL_LINES );
00171     glVertex3d( 0, 0, 0 );
00172     glVertex3d( 0, length, 0 );
00173     glEnd ();
00174     RenderText( 0, length + 0.3, 0, "Y" );
00175 
00176     /////////////////////////////////////////////////////////////////////////////////////
00177     // Display Z-axis for the world
00178 
00179     glColor3d( 0, 0, 1 );
00180     glBegin( GL_LINES );
00181     glVertex3d( 0, 0, 0 );
00182     glVertex3d( 0, 0, length );
00183     glEnd ();
00184     RenderText( 0, 0, length + 0.3, "Z" );
00185 
00186     glLineWidth( 1 );
00187 }
00188 
00189 /////////////////////////////////////////////////////////////////////////////////////////
00190 
00191 // Renders the given text to the given location in screen space on the window.
00192 //
00193 int WoRB::RenderPrintf( int x, int y, const char* format, ... )
00194 {
00195     char buffer[ 2048 ];
00196     va_list args;
00197     va_start( args, format );
00198 
00199     #ifdef _WIN32
00200     #pragma warning(disable:4996)
00201     #endif
00202     vsprintf( buffer, format, args );
00203 
00204     va_end( args );
00205 
00206     // Loop through characters displaying them.
00207     //
00208     void* font = GLUT_BITMAP_8_BY_13; // GLUT_BITMAP_HELVETICA_10
00209     glRasterPos2d( x, y );
00210     for( const char* ch = buffer; *ch; ++ch ) 
00211     {
00212         if ( *ch == '\n' ) {
00213             // Move down by the line-height on new-line
00214             y -= int( glutBitmapHeight( font ) * 1.2 );
00215             glRasterPos2d( x, y );
00216         } 
00217         else {
00218             glutBitmapCharacter( font, *ch );
00219         }
00220     }
00221 
00222     return y -= int( glutBitmapHeight( font ) * 1.2 );
00223 }