random_racer/src/Nurbs.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdarg.h>
00003 #include <assert.h>
00004 
00005 #include "Nurbs.h"
00006 
00007 
00008 namespace random_racer
00009 {
00010     
00011 Nurbs::Nurbs(unsigned int p_dimension,float p_spacing,unsigned int p_bufferZone)
00012 {
00013     // p_dimension have to be even
00014     assert( p_dimension % 2 == 0 );
00015     
00016     m_dimension     = p_dimension;
00017     m_spacing       = p_spacing;
00018     m_bufferZone    = p_bufferZone;
00019     
00020     m_controlPoints = new float[(m_dimension + 2*m_bufferZone) * 
00021                                 (m_dimension + 2*m_bufferZone)];
00022     
00023     m_degree = 2;
00024     m_order  = m_degree + 1;
00025     m_numCvs = m_dimension + (2*m_bufferZone);
00026 
00027     m_numKnots = m_order + m_dimension + (2*m_bufferZone);
00028     m_knots    = new float[ m_numKnots ];
00029     fillKnotsVector( m_order, (m_dimension + (2*m_bufferZone)), m_knots ); 
00030 
00031     // uses the evaluate method
00032     m_tempPoints = new Point[ m_numCvs ];
00033 
00034     m_correctX   = m_correctY = 0.0;
00035 
00036     // intialize the controlpoints with 0.0
00037     clear();
00038 }
00039 
00040 Nurbs::~Nurbs()
00041 {
00042     delete [] m_controlPoints;
00043     delete [] m_knots;
00044     delete [] m_tempPoints;
00045 }
00046 
00047 void
00048 Nurbs::fillKnotsVector(unsigned int p_order, unsigned int p_numPoints, 
00049                        float* p_knots)
00050 {
00051     unsigned int i;
00052     float j = 1.0;
00053     
00054     for (i = 0; i < p_order; i++)
00055     {
00056         p_knots[i] = 0.0;
00057     }
00058     for (;i < p_numPoints; i++, j += 1.0)
00059     {
00060         p_knots[i] = j;
00061     }
00062     for (;i < p_numPoints + p_order; i++)
00063     {
00064         p_knots[i] = j;
00065     }
00066 }
00067 
00068 void 
00069 Nurbs::clear()
00070 {
00071     for( unsigned int i = 0; i < ((m_dimension + (2*m_bufferZone)) * 
00072                                   (m_dimension + (2*m_bufferZone))); i++ )
00073     {
00074         m_controlPoints[i] = 0.0;
00075     }
00076 }
00077 
00078 void 
00079 Nurbs::evaluate(unsigned int p_levelOfDetail,std::vector<VRS::Vector>* p_target)
00080 {
00081     // p_levelOfDetail has to be even
00082     assert( p_levelOfDetail % 2 == 0 );
00083     
00084     VRS::Vector tempVector;
00085     Point p;
00086     
00087     unsigned int levelOfDetail = p_levelOfDetail + (2*m_bufferZone);
00088     
00089     bool firstTime = true;
00090     
00091     // Variables to move the final points to 0,0 and so on
00092     float x = 0.0;
00093     float y = 0.0;
00094     
00095     // store the maximal possible point, necessary to map the coordinates 
00096     // between 0 and (m_dimension * m_spacing)
00097     Point pMax;
00098     
00099     float uMax = (( max() - min() ) * (float)(levelOfDetail - m_bufferZone - 1) 
00100         / (float)(levelOfDetail-1)) + min();
00101     float vMax = (( max() - min() ) * (float)(levelOfDetail - m_bufferZone - 1) 
00102         / (float)(levelOfDetail-1)) + min();
00103     
00104     pMax = calculate( uMax, vMax, m_tempPoints );
00105             
00106     for( unsigned int i = 0; i != levelOfDetail; ++i ) 
00107     {
00108         // calculate the parametric u value
00109         float u = (( max() - min() ) * (float)i / (float)( levelOfDetail-1)) 
00110                   + min();
00111 
00112         for( unsigned int j = 0; j != levelOfDetail; ++j ) 
00113         {
00114             // calculate the parametric v value
00115             float v = (( max() - min() ) * (float)j / (float)( levelOfDetail-1)) 
00116                       + min();
00117             
00118             if( u > ( ((max() - min()) * (float)(m_bufferZone-1) / 
00119                   (float)(levelOfDetail-1)) + min() ) &&
00120                 v > ( ((max() - min()) * (float)(m_bufferZone-1) / 
00121                   (float)(levelOfDetail-1)) + min()) &&
00122                 u < ( ((max() - min()) * (float)(levelOfDetail-m_bufferZone) / 
00123                   (float)(levelOfDetail-1)) + min()) &&
00124                 v < ( ((max() - min()) * (float)(levelOfDetail-m_bufferZone) / 
00125                   (float)(levelOfDetail-1)) + min()))
00126             {    
00127                 // calculate the point on the surface
00128                 p = calculate( u, v, m_tempPoints );
00129     
00130                 // stores the first Point X- and Y-Value to move the point to 
00131                 // 0,0 and so on
00132                 if(firstTime)
00133                 {
00134                     x = p.x;
00135                     y = p.y;
00136                 }    
00137             
00138                 firstTime = false;
00139 
00140                 tempVector[0] = (p.x - x) / (pMax.x - x)  * 
00141                     ((float)m_dimension * m_spacing) - m_correctX;
00142 
00143                 tempVector[2] = (p.y - y) / (pMax.y - y) * 
00144                     ((float)m_dimension * m_spacing) - m_correctY;
00145 
00146                 tempVector[1] = p.z;
00147     
00148                 p_target->push_back( tempVector );
00149             }
00150         }
00151     } 
00152 }
00153 
00154 //
00155 // The following functions are based on the example written by Rob Bateman
00156 //
00157  
00158 float
00159 Nurbs::min() 
00160 {
00161     return m_knots[ m_degree ];
00162 }
00163 
00164 float 
00165 Nurbs::max() 
00166 {
00167     return m_knots[ m_numKnots - m_degree ];
00168 }
00169 
00170 float 
00171 Nurbs::coxDeBoor(float p_u, int p_i, int p_k, const float* p_knots)
00172 {
00173     if( p_k == 1 )
00174     {
00175         if( p_knots[ p_i ] <= p_u && p_u <= p_knots[ p_i + 1 ] ) 
00176             return 1.0;
00177             
00178         return 0.0;
00179     }
00180     
00181     float den1 = p_knots[ p_i + p_k-1 ] - p_knots[ p_i ];
00182     float den2 = p_knots[ p_i + p_k ] - p_knots[ p_i + 1 ];
00183 
00184     float eq1=0.0, eq2=0.0;
00185     
00186     if( den1 > 0 )
00187         eq1 = ( ( p_u - p_knots[ p_i ] ) / den1 ) *
00188                             coxDeBoor( p_u, p_i, p_k-1, p_knots );
00189     
00190     if( den2 > 0 )
00191         eq2 = ( p_knots[ p_i + p_k ] - p_u ) / den2 *           
00192                             coxDeBoor( p_u, p_i+1, p_k-1, p_knots );
00193     
00194     return eq1+eq2;
00195 }
00196 
00197 Nurbs::Point 
00198 Nurbs::calculateU(float p_t, int p_row)
00199 {
00200     Point p = {0,0,0};
00201 
00202     // sum the effect of all CV's on the curve at this point to 
00203     // get the evaluated curve point 
00204     for( unsigned int i = 0; i != m_numCvs; ++i ) 
00205     {
00206         // calculate the effect of this point on the curve
00207         float val = coxDeBoor( p_t, i, m_order, m_knots );
00208 
00209         if( val > 0.001f ) 
00210         {
00211             // sum effect of CV on this part of the curve
00212             p.x += val * ( p_row * m_spacing );
00213             p.y += val * ( i * m_spacing ); 
00214             p.z += val * m_controlPoints[ mapsIndex( p_row, i ) ];
00215         }
00216     }
00217 
00218     return p;
00219 }
00220 
00221 Nurbs::Point 
00222 Nurbs::calculateV(float p_t, Point* p_pnts)
00223 {
00224     Point p = {0,0,0};
00225 
00226     // sum the effect of all CV's on the curve at this point to 
00227     // get the evaluated curve point 
00228     for( unsigned int i = 0; i != m_numCvs; ++i ) 
00229     {
00230         // calculate the effect of this point on the curve
00231         float val = coxDeBoor( p_t, i, m_order, m_knots );
00232 
00233         if( val > 0.001f ) 
00234         {
00235             // sum effect of CV on this part of the curve
00236             p.x += val * p_pnts[i].x;
00237             p.y += val * p_pnts[i].y;
00238             p.z += val * p_pnts[i].z;
00239         }
00240     }
00241 
00242     return p;
00243 }
00244 
00245 Nurbs::Point
00246 Nurbs::calculate(float p_u, float p_v, Point* p_tempPoints)
00247 {
00248     for( unsigned int i = 0; i != m_numCvs; ++i ) 
00249     {
00250         // Calculate a point on each of the curves and store the result.
00251         p_tempPoints[i] = calculateU( p_u, i );
00252     }
00253 
00254     // to calculate the v direction
00255     Point p = calculateV( p_v, p_tempPoints );
00256 
00257     return p;
00258 }
00259 
00260 }

Generated on Fri May 11 21:01:58 2007 for Random Racer by  doxygen 1.5.1