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
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
00032 m_tempPoints = new Point[ m_numCvs ];
00033
00034 m_correctX = m_correctY = 0.0;
00035
00036
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
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
00092 float x = 0.0;
00093 float y = 0.0;
00094
00095
00096
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
00109 float u = (( max() - min() ) * (float)i / (float)( levelOfDetail-1))
00110 + min();
00111
00112 for( unsigned int j = 0; j != levelOfDetail; ++j )
00113 {
00114
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
00128 p = calculate( u, v, m_tempPoints );
00129
00130
00131
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
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
00203
00204 for( unsigned int i = 0; i != m_numCvs; ++i )
00205 {
00206
00207 float val = coxDeBoor( p_t, i, m_order, m_knots );
00208
00209 if( val > 0.001f )
00210 {
00211
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
00227
00228 for( unsigned int i = 0; i != m_numCvs; ++i )
00229 {
00230
00231 float val = coxDeBoor( p_t, i, m_order, m_knots );
00232
00233 if( val > 0.001f )
00234 {
00235
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
00251 p_tempPoints[i] = calculateU( p_u, i );
00252 }
00253
00254
00255 Point p = calculateV( p_v, p_tempPoints );
00256
00257 return p;
00258 }
00259
00260 }