![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsExtendedOpenGLVolPresPolygonalModel.cpp 00003 00004 Class TAPsExtendedOpenGLVolPresPolygonalModel is for a deformable mesh model with 00005 volume preservation. 00006 It memorizes its original shape -- original vertex positions 00007 00008 SUKITTI PUNAK (04/25/2005) 00009 UPDATE (05/30/2008) 00010 ******************************************************************************/ 00011 #include "TAPsExtendedOpenGLVolPresPolygonalModel.hpp" 00012 // Using Inclusion Model (i.e. definitions are included in declarations) 00013 // (this name.cpp is included in name.hpp) 00014 // Each friend is defined directly inside its declaration. 00015 00016 BEGIN_NAMESPACE_TAPs__OpenGL 00017 //============================================================================= 00018 //----------------------------------------------------------------------------- 00019 // default constructor 00020 template <typename T> 00021 ExtendedOpenGLVolPresPolygonalModel<T>::ExtendedOpenGLVolPresPolygonalModel() 00022 : OpenGLVolPresPolygonalModel<T>(), 00023 m_prOrigVertexPos( NULL ), 00024 m_pbFaceFixed( NULL ), 00025 m_pbVertexFixed( NULL ) 00026 { 00027 #ifdef TAPs_DEBUG_MODE 00028 std::cout << "ExtendedOpenGLVolPresPolygonalModel<" << typeid(T).name() << "> constructor\n"; 00029 #endif//TAPs_DEBUG_MODE 00030 } 00031 //----------------------------------------------------------------------------- 00032 // destructor 00033 template <typename T> 00034 ExtendedOpenGLVolPresPolygonalModel<T>::~ExtendedOpenGLVolPresPolygonalModel() 00035 { 00036 if ( m_prOrigVertexPos != NULL ) { 00037 delete [] m_prOrigVertexPos; 00038 m_prOrigVertexPos = NULL; 00039 } 00040 if ( m_pbFaceFixed != NULL ) { 00041 delete [] m_pbFaceFixed; 00042 m_pbFaceFixed = NULL; 00043 } 00044 if ( m_pbVertexFixed != NULL ) { 00045 delete [] m_pbVertexFixed; 00046 m_pbVertexFixed = NULL; 00047 } 00048 00049 #ifdef TAPs_DEBUG_MODE 00050 std::cout << "ExtendedOpenGLVolPresPolygonalModel<" << typeid(T).name() << "> destructor\n"; 00051 #endif//TAPs_DEBUG_MODE 00052 } 00053 //----------------------------------------------------------------------------- 00054 // Initialize 00055 template <typename T> 00056 void ExtendedOpenGLVolPresPolygonalModel<T>::Initialize () 00057 { 00058 #ifdef TAPs_DEBUG_MODE 00059 std::cout << "A Model Initialization\n"; 00060 #endif//TAPs_DEBUG_MODE 00061 //---------------------------------------------------------------- 00062 // Model Initialization 00063 VolPresPolygonalModel<T>::Initialize(); 00064 SetOrigVertexPositions(); 00065 SetFacesToUnFixed(); 00066 SetVerticesToUnFixed(); 00067 00068 /* 00069 DetermineAndSortRings(); 00070 CalAndSetNormals(); 00071 // DetermineAndSortRings(); 00072 ApplyMaterial(); 00073 DetermineEdgeList(); 00074 CalVolume2(); 00075 00076 m_pcVertexRings = new VertexRings( m_pviVertexRing1List, m_iNoVertices ); 00077 //PreserveVolume( weight ); 00078 00079 //---------------------------------------------------------------- 00080 // Allocate Fix Status and Deform Vector for each Vertex 00081 delete [] m_bFlagFixed; 00082 m_bFlagFixed = new bool[m_iNoVertices]; 00083 for ( int i = 0; i < m_iNoVertices; ++i ) { 00084 m_bFlagFixed[i] = false; 00085 } 00086 //---------------------------------------------------------------- 00087 // Allocate Deform Vector for each Vertex 00088 delete [] m_pvDeformVector; 00089 m_pvDeformVector = new Vector3<T>[m_iNoVertices]; 00090 00091 // For Collision Detection 00092 CalBoundingAABB(); 00093 CalBoundingEllipsoid(); 00094 CalBoundingSphere(); 00095 */ 00096 } 00097 //----------------------------------------------------------------------------- 00098 // Set Original Vertex Positions 00099 template <typename T> 00100 void ExtendedOpenGLVolPresPolygonalModel<T>::SetOrigVertexPositions () 00101 { 00102 if ( !m_prOrigVertexPos ) 00103 m_prOrigVertexPos = new Vector3<T>[ GetNoVertices() ]; 00104 if ( !m_prOrigVertexPos ) { 00105 return; 00106 } 00107 for ( int i = 0; i < GetNoVertices(); ++i ) { 00108 m_prOrigVertexPos[i] = m_prXVertex[i].GetPosition(); 00109 } 00110 } 00111 //----------------------------------------------------------------------------- 00112 // Set Face Fixed/Unfixed Status 00113 template <typename T> 00114 void ExtendedOpenGLVolPresPolygonalModel<T>::SetFacesToUnFixed () 00115 { 00116 if ( !m_pbFaceFixed ) 00117 m_pbFaceFixed = new bool[ GetNoFaces() ]; 00118 if ( !m_pbFaceFixed ) { 00119 std::cerr << "ERROR: Cannot allocate memory for m_pbFaceFixed!" << std::endl; 00120 return; 00121 } 00122 for ( int i = 0; i < GetNoFaces(); ++i ) { 00123 m_pbFaceFixed[i] = false; 00124 } 00125 } 00126 //----------------------------------------------------------------------------- 00127 // Set Vertex Fixed/Unfixed Status 00128 template <typename T> 00129 void ExtendedOpenGLVolPresPolygonalModel<T>::SetVerticesToUnFixed () 00130 { 00131 if ( !m_pbVertexFixed ) 00132 m_pbVertexFixed = new bool[ GetNoVertices() ]; 00133 if ( !m_pbVertexFixed ) { 00134 std::cerr << "ERROR: Cannot allocate memory for m_pbVertexFixed!" << std::endl; 00135 return; 00136 } 00137 for ( int i = 0; i < GetNoVertices(); ++i ) { 00138 m_pbVertexFixed[i] = false; 00139 } 00140 } 00141 //----------------------------------------------------------------------------- 00142 00144 // START: a function for bouncing // 00145 //----------------------------------------------------------------------------- 00146 template <typename T> 00147 T ExtendedOpenGLVolPresPolygonalModel<T>::FlatCollisionDetectionWithElasticity( T groundHeight ) 00148 { 00149 bool isChanged = true; 00150 T volForce = 0; 00151 T centerY = GetTransform().GetTranslation()[1]; 00152 //T distance = Center[1] + m_paBoundingAABB[0][1] - groundHeight; 00153 T distance = centerY + m_paBoundingAABB[0][1] - groundHeight; 00154 //---------------------------------------------------------------- 00155 // No collision 00156 if ( distance >= 0.0 ) { 00157 return 0; 00158 } 00159 //---------------------------------------------------------------- 00160 // Handle Collision 00161 for ( int i = 0; i < GetNoVertices(); ++i ) { 00162 m_bFlagFixed[i] = m_pbVertexFixed[i]; 00163 T newHeight = groundHeight - centerY; 00164 if ( groundHeight > centerY + m_prOrigVertexPos[i][1] ) { 00165 isChanged = true; 00166 m_prXVertex[i][1] = newHeight; 00167 m_bFlagFixed[i] = true; 00168 } 00169 else if ( m_prXVertex[i][1] != m_prOrigVertexPos[i][1] ) { 00170 isChanged = true; 00171 m_prXVertex[i][0] = m_prOrigVertexPos[i][0]; 00172 m_prXVertex[i][1] = m_prOrigVertexPos[i][1]; 00173 m_prXVertex[i][2] = m_prOrigVertexPos[i][2]; 00174 } 00175 else { 00176 00177 } 00178 } 00179 //---------------------------------------------------------------- 00180 if ( m_bFlagVolPresMode && isChanged ) { 00181 //PreserveVolume( weight ); 00182 PreserveVolumeByVertexNormals( m_weight ); 00183 //--------------------------------------- 00184 // Recalculate Normals (Already included in PreserveVolumeByVertexNormals() ) 00185 //CalAndSetFaceNormalsNotNormalized(); 00186 //CalAndSetVertexNormals(); 00187 //NormalizeFaceNormals(); 00188 //--------------------------------------- 00189 //volForce = m_tVolume - totalVolume; 00190 } 00191 return volForce; 00192 } 00193 //----------------------------------------------------------------------------- 00194 // END: a function for bouncing // 00196 00197 //----------------------------------------------------------------------------- 00198 // Reset Fn inherited from Model class 00199 template <typename T> 00200 void ExtendedOpenGLVolPresPolygonalModel<T>::Reset () 00201 { 00202 for ( int i = 0; i < GetNoVertices(); ++i ) { 00203 m_prXVertex[i].SetPosition( m_prOrigVertexPos[i] ); 00204 } 00205 GetTransform().SetTranslation( 0, 0, 0 ); 00206 CalAndSetNormals(); 00207 //Center[0] = Center[1] = Center[2] = 0; 00208 //Initialize(); 00209 } 00210 /* 00211 //----------------------------------------------------------------------------- 00212 //void DisplayGL() 00213 template <typename T> 00214 void ExtendedOpenGLVolPresPolygonalModel<T>::DisplayGL( OpenGL::Enum::DrawMode DM ) 00215 { 00216 switch (DM) { 00217 case OpenGL::Enum::POLYGON: 00218 DrawGL( GL_POLYGON ); 00219 break; 00220 case OpenGL::Enum::WIRE_FRAME: 00221 DrawGL( GL_LINE_LOOP ); 00222 break; 00223 case OpenGL::Enum::POINT: 00224 DrawGL( GL_POINTS ); 00225 break; 00226 case OpenGL::Enum:: POLYGON_WITH_WIRE_FRAME: 00227 // Draw the object with GL_POLYGON_OFFSET enabled 00228 glEnable( GL_POLYGON_OFFSET_FILL ); 00229 glPolygonOffset( 1.0, 1.0 ); 00230 DrawGL( GL_POLYGON ); 00231 glDisable( GL_POLYGON_OFFSET_FILL ); 00232 // Draw the wire frame of the object 00233 glDisable( GL_LIGHTING ); 00234 glColor3ub( 255, 200, 0 ); 00235 DrawGL( GL_LINE_LOOP ); 00236 glEnable( GL_LIGHTING ); 00237 break; 00238 } 00239 } 00240 //*/ 00241 //----------------------------------------------------------------------------- 00242 //void DisplayGLText() 00243 template <typename T> 00244 void ExtendedOpenGLVolPresPolygonalModel<T>::DisplayGLText( T x, T y, T z ) 00245 { 00246 char str[128] = ""; 00247 int count = 0; 00248 T volume = CalVolume(); // for calculating centroid 00249 sprintf( str, "Centroid: (%10.4f, %10.4f, %10.4f)", m_vtCentroid[0], m_vtCentroid[1], m_vtCentroid[2] ); 00250 DrawText( str, x, y-count++, z ); 00251 sprintf( str, "New Volume: %g", volume ); 00252 DrawText( str, x, y-count++, z ); 00253 sprintf( str, "Orig Volume: %g", m_tVolume ); 00254 DrawText( str, x, y-count++, z ); 00255 00256 // sprintf( str, "weight0: %g", weight[0] ); 00257 // DrawText( str, x, y-count++, z ); 00258 00259 // sprintf( str, "weight1: %g", weight[1] ); 00260 // DrawText( str, x, y-2*count++, z ); 00261 // sprintf( str, "weight2: %g", weight[2] ); 00262 // DrawText( str, x, y-2*count++, z ); 00263 // sprintf( str, "weight3: %g", weight[3] ); 00264 // DrawText( str, x, y-2*count++, z ); 00265 00266 /* 00267 if ( m_bFlagSpringForceMode ) { 00268 sprintf( str, "Spring Force: ON" ); 00269 } 00270 else { 00271 sprintf( str, "Spring Force: OFF" ); 00272 } 00273 DrawText( str, x, y-count++, z ); 00274 if ( m_bFlagVolPresMode ) { 00275 sprintf( str, "VolPres: ON" ); 00276 } 00277 else { 00278 sprintf( str, "VolPres: OFF" ); 00279 } 00280 DrawText( str, x, y-count++, z ); 00281 //*/ 00282 } 00283 //----------------------------------------------------------------------------- 00284 // Helper Fn 00285 // void DrawGL() 00286 template <typename T> 00287 void ExtendedOpenGLVolPresPolygonalModel<T>::DrawGL ( GLenum drawMode ) 00288 { 00289 glPushMatrix(); 00290 00291 00292 glTranslatef( static_cast<float>( GetTransform().GetTranslation()[0] ), 00293 static_cast<float>( GetTransform().GetTranslation()[1] ), 00294 static_cast<float>( GetTransform().GetTranslation()[2] ) ); 00295 /*glRotatef( static_cast<float>( Rotation[0] ), 00296 static_cast<float>( 1 ), 00297 static_cast<float>( 0 ), 00298 static_cast<float>( 0 ) ); 00299 glRotatef( static_cast<float>( Rotation[1] ), 00300 static_cast<float>( 0 ), 00301 static_cast<float>( 1 ), 00302 static_cast<float>( 0 ) ); 00303 glRotatef( static_cast<float>( Rotation[2] ), 00304 static_cast<float>( 0 ), 00305 static_cast<float>( 0 ), 00306 static_cast<float>( 1 ) ); 00307 glScalef( static_cast<float>( Scale[0]/2 ), 00308 static_cast<float>( Scale[1]/2 ), 00309 static_cast<float>( Scale[2] ) ); 00310 */ 00311 //ModelTransformationByTranslationRatationAndScale(); 00312 00313 //------------------------------------------------------------------------- 00314 // StepSimulation 00315 int count; 00316 if ( bRunSimulation ) { 00318 for ( count = 0; count < 5; count++ ) { 00319 StepSimulation( 0.01 ); 00320 } 00321 //*/ 00322 00323 /* 00324 for ( int i = 0; i < 5; ++i ) { 00325 for ( int j = 0; j < m_prFace[i].GetNoVertices(); ++j ) { 00326 m_prXVertex[ m_prFace[i].GetVertexNo(j) ].SetPosition( 00327 m_prXVertex[ m_prFace[i].GetVertexNo(j) ].GetPosition() * 1.001 00328 ); 00329 //m_prXVertex[ 0].SetPosition( m_prXVertex[ 0].GetPosition() * 1.001 ); 00330 //m_prXVertex[12].SetPosition( m_prXVertex[12].GetPosition() * 1.001 ); 00331 //m_prXVertex[13].SetPosition( m_prXVertex[13].GetPosition() * 1.001 ); 00332 } 00333 } 00334 */ 00335 } 00336 00337 if ( isFacetShading ) { 00338 // Draw the object 00339 //glEnable( GL_TEXTURE_2D ); 00340 for ( int i = 0; i < m_iNoFaces; i++ ) 00341 { 00342 glBegin( drawMode ); 00343 for ( int j = 0; j < m_prFace[i].GetNoVertices(); ++j ) 00344 { 00345 // Draw texture 00346 if ( m_prFace[i].GetNoTexCoords() != 0 ) { 00347 glTexCoord2f( static_cast<float>( m_prFace[i].GetTexCoordHalfNo( j*2 ) ), 00348 static_cast<float>( m_prFace[i].GetTexCoordHalfNo( j*2+1 ) ) ); 00349 } 00350 // Normal of the face 00351 glNormal3f ( static_cast<float>( m_prFace[i].GetNormal()[0] ), 00352 static_cast<float>( m_prFace[i].GetNormal()[1] ), 00353 static_cast<float>( m_prFace[i].GetNormal()[2] ) ); 00354 // Draw the vertex 00355 glVertex3f ( 00356 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][0] ), 00357 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][1] ), 00358 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][2] ) ); 00359 } 00360 glEnd(); 00361 } 00362 //glDisable( GL_TEXTURE_2D ); 00363 } 00364 else { 00365 // Draw the object 00366 //glEnable( GL_TEXTURE_2D ); 00367 for ( int i = 0; i < m_iNoFaces; i++ ) 00368 { 00369 GLfloat ambient[4]; 00370 // Change ambient color 00371 if ( m_pbFaceFixed[i] ) { 00372 bool isFixed = true; 00373 for ( int k = 0; k < m_prFace[i].GetNoVertices(); ++k ) { 00374 if ( m_pbVertexFixed[ m_prFace[i].GetVertexNo(k) ] == false ) { 00375 isFixed = false; 00376 break; 00377 } 00378 } 00379 if ( isFixed ) { 00380 material.GetAmbient( ambient ); 00381 material.SetAmbient( 0, ambient[0]+0.5 ); 00382 material.ApplyAmbient(); 00383 } 00384 } 00385 00386 // Draw all faces 00387 glBegin( drawMode ); 00388 for ( int j = 0; j < m_prFace[i].GetNoVertices(); ++j ) 00389 { 00390 // Draw texture 00391 if ( m_prFace[i].GetNoTexCoords() != 0 ) { 00392 glTexCoord2f( static_cast<float>( m_prFace[i].GetTexCoordHalfNo( j*2 ) ), 00393 static_cast<float>( m_prFace[i].GetTexCoordHalfNo( j*2+1 ) ) ); 00394 } 00395 // Normal of the vertex 00396 glNormal3f ( static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ].GetNormal()[0] ), 00397 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ].GetNormal()[1] ), 00398 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ].GetNormal()[2] ) ); 00399 // Draw the vertex 00400 glVertex3f ( 00401 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][0] ), 00402 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][1] ), 00403 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][2] ) ); 00404 } 00405 glEnd(); 00406 00407 // Restore ambient color 00408 if ( m_pbFaceFixed[i] ) { 00409 material.SetAmbient( ambient ); 00410 material.ApplyAmbient(); 00411 } 00412 00413 } 00414 //glDisable( GL_TEXTURE_2D ); 00415 } 00416 00417 // Display vertex normals 00418 if ( bFlagShowVertexNormals ) { 00419 DisplayGL_ParticleNormals(); 00420 } 00421 // Display vertex rings 00422 if ( bFlagShowVertexRings ) { 00423 DisplayGL_VertexRings(); 00424 } 00425 // Display the deformed face 00426 if ( bFlagShowDeformedFace ) { 00427 DisplayGL_DeformedFaceNo(); 00428 } 00429 00430 // Display Volume and Centroid 00431 glDisable( GL_LIGHTING ); 00432 glPushAttrib(GL_ALL_ATTRIB_BITS); 00433 glColor3ub( 200, 185, 0 ); 00434 00435 // Draw Bounding Volume(s) 00436 //DrawBoundingAABB(); 00437 //DrawBoundingSphere(); 00438 00439 glPopAttrib(); 00440 glEnable( GL_LIGHTING ); 00441 00442 glPopMatrix(); 00443 } 00444 //----------------------------------------------------------------------------- 00445 // Picking Fns 00446 template <typename T> 00447 void ExtendedOpenGLVolPresPolygonalModel<T>::SelectATriangle ( 00448 bool isSelect, // true --> select; false --> deselect the hit triangle 00449 GLuint BUFSIZE, GLuint selectBuf[], GLint &hits, 00450 GLdouble x, GLdouble y, 00451 GLdouble dLeft, GLdouble dRight, 00452 GLdouble dBottom, GLdouble dTop, 00453 GLdouble dNear, GLdouble dFar, 00454 GLdouble pickSize, 00455 const GLdouble * const worldRotation, 00456 const GLdouble * const modelRotation 00457 ) 00458 { 00459 // GLuint BUFSIZE = 512; 00460 // GLint selectBuf[ BUFSIZE ]; 00461 // GLint hits; 00462 GLint viewport[4]; 00463 glGetIntegerv( GL_VIEWPORT, viewport ); 00464 glSelectBuffer( BUFSIZE, selectBuf ); 00465 (void) glRenderMode( GL_SELECT ); 00466 glInitNames(); 00467 glPushName( 0 ); 00468 glMatrixMode( GL_PROJECTION ); 00469 glPushMatrix(); 00470 glLoadIdentity(); 00471 // Create 5x5 pixel picking region near cursor location 00472 gluPickMatrix( x, viewport[3] - y, pickSize, pickSize, viewport ); 00473 glOrtho( dLeft, dRight, dBottom, dTop, dNear, dFar ); 00474 glMatrixMode( GL_MODELVIEW ); 00475 glPushMatrix(); 00476 glLoadIdentity(); 00477 if ( worldRotation != NULL ) { 00478 glMultMatrixd( worldRotation ); 00479 } 00480 if ( modelRotation != NULL ) { 00481 glMultMatrixd( modelRotation ); 00482 } 00483 // Draw All Faces 00484 for ( int i = 0; i < m_iNoFaces; i++ ) 00485 { 00486 glLoadName(i); 00487 glBegin( OpenGL::Enum::POLYGON ); 00488 for ( int j = 0; j < m_prFace[i].GetNoVertices(); ++j ) 00489 { 00490 // Draw the vertex 00491 glVertex3f ( 00492 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][0] ), 00493 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][1] ), 00494 static_cast<float>( m_prXVertex[ m_prFace[i].GetVertexNo( j ) ][2] ) ); 00495 } 00496 glEnd(); 00497 } 00498 glPopMatrix(); 00499 glMatrixMode( GL_PROJECTION ); 00500 glPopMatrix(); 00501 glMatrixMode( GL_MODELVIEW ); 00502 00503 hits = glRenderMode( GL_RENDER ); 00504 ProcessHits( hits, selectBuf, isSelect ); 00505 glutPostRedisplay(); 00506 } 00507 //----------------------------------------------------------------------------- 00508 // Process Hits 00509 template <typename T> 00510 void ExtendedOpenGLVolPresPolygonalModel<T>::ProcessHits ( 00511 GLint hits, GLuint buffer[], bool isSelect ) 00512 { 00513 GLuint names, *ptr; 00514 ptr = (GLuint *) buffer; 00515 for ( int i = 0; i < hits; ++i ) { 00516 names = *ptr; 00517 ++ptr; 00518 ++ptr; 00519 ++ptr; 00520 for ( int j = 0; j < static_cast<int>(names); ++j ) { 00521 m_pbFaceFixed[*ptr] = isSelect; 00522 for ( int k = 0; k < m_prFace[*ptr].GetNoVertices(); ++k ) { 00523 m_pbVertexFixed[ m_prFace[*ptr].GetVertexNo(k) ] = isSelect; 00524 } 00525 ++ptr; 00526 } 00527 } 00528 } 00529 //----------------------------------------------------------------------------- 00530 // Fix of Unfix vertices contained in a box 00531 template <typename T> 00532 void ExtendedOpenGLVolPresPolygonalModel<T>::FixUnFixVerticesInABox ( 00533 bool isToFix, T minX, T maxX, T minY, T maxY, T minZ, T maxZ ) 00534 { 00535 for ( int i = 0; i < GetNoVertices(); ++i ) { 00536 if ( minX <= m_prXVertex[i][0] && m_prXVertex[i][0] <= maxX ) { 00537 if ( minY <= m_prXVertex[i][1] && m_prXVertex[i][1] <= maxY ) { 00538 if ( minZ <= m_prXVertex[i][2] && m_prXVertex[i][2] <= maxZ ) { 00539 m_pbVertexFixed[i] = isToFix; 00540 } 00541 } 00542 } 00543 } 00544 for ( int j = 0; j < GetNoFaces(); ++j ) { 00545 m_pbFaceFixed[j] = isToFix; 00546 for ( int k = 0; k < m_prFace[j].GetNoVertices(); ++k ) { 00547 if ( m_pbVertexFixed[ m_prFace[j].GetVertexNo(k) ] != isToFix ) { 00548 m_pbFaceFixed[j] = !isToFix; 00549 } 00550 } 00551 } 00552 } 00553 //----------------------------------------------------------------------------- 00554 //============================================================================= 00555 END_NAMESPACE_TAPs__OpenGL 00556 //----------------------------------------------------------------------------- 00557 //345678901234567890123456789012345678901234567890123456789012345678901234567890 00558 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8