Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

LODSphereMesh Class Reference

#include <lodspheremesh.h>

Collaboration diagram for LODSphereMesh:

Collaboration graph
List of all members.

Public Types

enum  {
  Normals = 0x01, Tangents = 0x02, Colors = 0x04, TexCoords0 = 0x08,
  TexCoords1 = 0x10, VertexProgParams = 0x1000, Multipass = 0x10000000
}

Public Member Functions

 LODSphereMesh ()
void render (const GLContext &, const Frustum &, float pixWidth, Texture **tex, int nTextures)
void render (const GLContext &, unsigned int attributes, const Frustum &, float pixWidth, Texture *tex0=NULL, Texture *tex1=NULL, Texture *tex2=NULL, Texture *tex3=NULL)
void render (const GLContext &, unsigned int attributes, const Frustum &, float pixWidth, Texture **tex, int nTextures)
 ~LODSphereMesh ()

Private Member Functions

int renderPatches (int phi0, int theta0, int extent, int level, const RenderInfo &)
void renderSection (int phi0, int theta0, int extent, const RenderInfo &)

Private Attributes

int currentVB
unsigned int indexBuffer
unsigned short * indices
int maxVertices
int nIndices
int nTexturesUsed
unsigned int subtextures [MAX_SPHERE_MESH_TEXTURES]
Texturetextures [MAX_SPHERE_MESH_TEXTURES]
bool useVertexBuffers
unsigned int vertexBuffers [NUM_SPHERE_VERTEX_BUFFERS]
bool vertexBuffersInitialized
int vertexSize
float * vertices

Classes

struct  RenderInfo

Member Enumeration Documentation

anonymous enum
 

Enumeration values:
Normals 
Tangents 
Colors 
TexCoords0 
TexCoords1 
VertexProgParams 
Multipass 

Definition at line 40 of file lodspheremesh.h.

00040          {
00041         Normals    = 0x01,
00042         Tangents   = 0x02,
00043         Colors     = 0x04,
00044         TexCoords0 = 0x08,
00045         TexCoords1 = 0x10,
00046         VertexProgParams = 0x1000,
00047         Multipass  = 0x10000000,
00048     };


Constructor & Destructor Documentation

LODSphereMesh::LODSphereMesh  ) 
 

Definition at line 96 of file lodspheremesh.cpp.

References indices, InitTrigArrays(), MaxVertexSize, maxVertices, minStep, nIndices, phiDivisions, thetaDivisions, trigArraysInitialized, and vertices.

00096                              :
00097     vertices(NULL),
00098     vertexBuffersInitialized(false),
00099     useVertexBuffers(false)
00100 {
00101     if (!trigArraysInitialized)
00102         InitTrigArrays();
00103 
00104     int maxThetaSteps = thetaDivisions / minStep;
00105     int maxPhiSteps = phiDivisions / minStep;
00106     maxVertices = (maxPhiSteps + 1) * (maxThetaSteps + 1);
00107     vertices = new float[MaxVertexSize * maxVertices];
00108 
00109     nIndices = maxPhiSteps * 2 * (maxThetaSteps + 1);
00110     indices = new unsigned short[nIndices];
00111 }

LODSphereMesh::~LODSphereMesh  ) 
 

Definition at line 114 of file lodspheremesh.cpp.

References vertices.

00115 {
00116     if (vertices != NULL)
00117         delete[] vertices;
00118 }


Member Function Documentation

void LODSphereMesh::render const GLContext ,
const Frustum ,
float  pixWidth,
Texture **  tex,
int  nTextures
 

Definition at line 129 of file lodspheremesh.cpp.

References Normals, render(), and TexCoords0.

00134 {
00135     render(context,
00136            Normals | TexCoords0, frustum, pixWidth, tex,
00137            nTextures);
00138 }

void LODSphereMesh::render const GLContext ,
unsigned int  attributes,
const Frustum ,
float  pixWidth,
Texture tex0 = NULL,
Texture tex1 = NULL,
Texture tex2 = NULL,
Texture tex3 = NULL
 

Definition at line 141 of file lodspheremesh.cpp.

References MAX_SPHERE_MESH_TEXTURES, render(), and textures.

00149 {
00150     Texture* textures[MAX_SPHERE_MESH_TEXTURES];
00151     int nTextures = 0;
00152 
00153     if (tex0 != NULL)
00154         textures[nTextures++] = tex0;
00155     if (tex1 != NULL)
00156         textures[nTextures++] = tex1;
00157     if (tex2 != NULL)
00158         textures[nTextures++] = tex2;
00159     if (tex3 != NULL)
00160         textures[nTextures++] = tex3;
00161     render(context, attributes, frustum, pixWidth, textures, nTextures);
00162 }

void LODSphereMesh::render const GLContext ,
unsigned int  attributes,
const Frustum ,
float  pixWidth,
Texture **  tex,
int  nTextures
 

Definition at line 165 of file lodspheremesh.cpp.

References currentVB, VertexProcessor::disableAttribArray(), VertexProcessor::enableAttribArray(), LODSphereMesh::RenderInfo::fp, getSphereLOD(), GL_ARRAY_BUFFER_ARB, GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB, GL_STREAM_DRAW_ARB, GL_TEXTURE0_ARB, glx::glActiveTextureARB, glx::glBindBufferARB, glx::glBufferDataARB, glx::glClientActiveTextureARB, glx::glGenBuffersARB, glVertex(), indexBuffer, indices, Plane< float >::intersection(), log(), max, maxDivisions, MaxVertexSize, maxVertices, min, minStep, nIndices, Normals, nTexturesUsed, NUM_SPHERE_VERTEX_BUFFERS, renderPatches(), renderSection(), LODSphereMesh::RenderInfo::step, subtextures, Tangents, LODSphereMesh::RenderInfo::texLOD, textures, useVertexBuffers, vertexBuffers, vertexBuffersInitialized, vertexSize, and vertices.

Referenced by render(), renderBumpMappedMesh(), renderClouds_GLSL(), renderEclipseShadows_Shaders(), Renderer::renderObject(), renderRingShadowsVS(), renderShadowedModelDefault(), renderShadowedModelVertexShader(), renderSmoothMesh(), renderSphere_Combiners(), renderSphere_Combiners_VP(), renderSphere_DOT3_VP(), renderSphere_FP_VP(), renderSphere_GLSL(), and renderSphereDefault().

00171 {
00172     int lod = 64;
00173     float lodBias = getSphereLOD(pixWidth);
00174 
00175     if (lodBias < 0.0f)
00176     {
00177         if (lodBias < -30)
00178             lodBias = -30;
00179         lod = lod / (1 << (int) (-lodBias));
00180         if (lod < 2)
00181             lod = 2;
00182     }
00183     else if (lodBias > 0.0f)
00184     {
00185         if (lodBias > 30)
00186             lodBias = 30;
00187         lod = lod * (1 << (int) lodBias);
00188         if (lod > maxDivisions)
00189             lod = maxDivisions;
00190     }
00191 
00192     int step = maxDivisions / lod;
00193     int thetaExtent = maxDivisions;
00194     int phiExtent = thetaExtent / 2;
00195 
00196     int split = 1;
00197     if (step < minStep)
00198     {
00199         split = minStep / step;
00200         thetaExtent /= split;
00201         phiExtent /= split;
00202     }
00203 
00204     if (tex == NULL)
00205         nTextures = 0;
00206 
00207 
00208     // Need to have vertex programs enabled in order to make
00209     // use of surface tangents.
00210     if (!context.getVertexProcessor())
00211         attributes &= ~Tangents;
00212 
00213     RenderInfo ri(step, attributes, frustum, context);
00214 
00215     // If one of the textures is split into subtextures, we may have to
00216     // use extra patches, since there can be at most one subtexture per patch.
00217     int i;
00218     int minSplit = 1;
00219     for (i = 0; i < nTextures; i++)
00220     {
00221         float pixelsPerTexel = pixWidth * 2.0f / 
00222             ((float) tex[i]->getWidth() / 2.0f);
00223         double l = log(pixelsPerTexel) / log(2.0);
00224         
00225         ri.texLOD[i] = max(min(tex[i]->getLODCount() - 1, (int) l), 0);
00226         if (tex[i]->getUTileCount(ri.texLOD[i]) > minSplit)
00227             minSplit = tex[i]->getUTileCount(ri.texLOD[i]);
00228         if (tex[i]->getVTileCount(ri.texLOD[i]) > minSplit)
00229             minSplit = tex[i]->getVTileCount(ri.texLOD[i]);
00230     }
00231 
00232     if (split < minSplit)
00233     {
00234         thetaExtent /= (minSplit / split);
00235         phiExtent /= (minSplit / split);
00236         split = minSplit;
00237         if (phiExtent <= ri.step)
00238             ri.step /= ri.step / phiExtent;
00239     }
00240 
00241     // Set the current textures
00242     nTexturesUsed = nTextures;
00243     for (i = 0; i < nTextures; i++)
00244     {
00245         tex[i]->beginUsage();
00246         textures[i] = tex[i];
00247         subtextures[i] = 0;
00248         if (nTextures > 1)
00249             glx::glActiveTextureARB(GL_TEXTURE0_ARB + i);
00250         glEnable(GL_TEXTURE_2D);
00251     }
00252 
00253 #ifdef VERTEX_BUFFER_OBJECTS_ENABLED
00254     if (!vertexBuffersInitialized)
00255     {
00256         // TODO: assumes that the same context is used every time we
00257         // render.  Valid now, but not necessarily in the future.  Still,
00258         // would only cause problems if we rendered in two different contexts
00259         // and only one had vertex buffer objects.
00260         vertexBuffersInitialized = true;
00261         if (context.extensionSupported("GL_ARB_vertex_buffer_object"))
00262         {
00263             for (int i = 0; i < NUM_SPHERE_VERTEX_BUFFERS; i++)
00264             {
00265                 GLuint vbname = 0;
00266                 glx::glGenBuffersARB(1, &vbname);
00267                 vertexBuffers[i] = (unsigned int) vbname;
00268                 glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffers[i]);
00269                 glx::glBufferDataARB(GL_ARRAY_BUFFER_ARB,
00270                                      maxVertices * MaxVertexSize * sizeof(float),
00271                                      NULL,
00272                                      GL_STREAM_DRAW_ARB);
00273             }
00274             glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00275 
00276             glx::glGenBuffersARB(1, &indexBuffer);
00277             
00278             useVertexBuffers = true;
00279 
00280             // HACK: delete the user arrays--we shouldn't need to allocate
00281             // these at all if we're using vertex buffer objects.
00282             delete[] vertices;
00283         }
00284     }
00285 #endif
00286 
00287     if (useVertexBuffers)
00288     {
00289         currentVB = 0;
00290         glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffers[currentVB]);
00291     }
00292 
00293     // Set up the mesh vertices 
00294     int nRings = phiExtent / ri.step;
00295     int nSlices = thetaExtent / ri.step;
00296 
00297     int n2 = 0;
00298     for (i = 0; i < nRings; i++)
00299     {
00300         for (int j = 0; j <= nSlices; j++)
00301         {
00302             indices[n2 + 0] = i * (nSlices + 1) + j;
00303             indices[n2 + 1] = (i + 1) * (nSlices + 1) + j;
00304             n2 += 2;
00305         }
00306     }
00307 
00308     if (useVertexBuffers)
00309     {
00310         glx::glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer);
00311         glx::glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
00312                              nIndices * sizeof(indices[0]),
00313                              indices,
00314                              GL_DYNAMIC_DRAW_ARB);
00315     }
00316 
00317     // Compute the size of a vertex
00318     vertexSize = 3;
00319     if ((attributes & Tangents) != 0)
00320         vertexSize += 3;
00321     for (i = 0; i < nTextures; i++)
00322         vertexSize += 2;
00323 
00324     glEnableClientState(GL_VERTEX_ARRAY);
00325     if ((attributes & Normals) != 0)
00326         glEnableClientState(GL_NORMAL_ARRAY);
00327 
00328     for (i = 0; i < nTextures; i++)
00329     {
00330         if (nTextures > 1)
00331             glx::glClientActiveTextureARB(GL_TEXTURE0_ARB + i);
00332         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00333     }
00334 
00335     glDisableClientState(GL_COLOR_ARRAY);
00336 
00337     if ((attributes & Tangents) != 0)
00338     {
00339         VertexProcessor* vproc = context.getVertexProcessor();
00340         vproc->enableAttribArray(6);
00341     }
00342 
00343     if (split == 1)
00344     {
00345         renderSection(0, 0, thetaExtent, ri);
00346     }
00347     else
00348     {
00349         // Render the sphere section by section.
00350         int reject = 0;
00351 
00352         // Compute the vertices of the view frustum.  These will be used for
00353         // culling patches.
00354         ri.fp[0] = Planef::intersection(frustum.getPlane(Frustum::Near),
00355                                         frustum.getPlane(Frustum::Top),
00356                                         frustum.getPlane(Frustum::Left));
00357         ri.fp[1] = Planef::intersection(frustum.getPlane(Frustum::Near),
00358                                         frustum.getPlane(Frustum::Top),
00359                                         frustum.getPlane(Frustum::Right));
00360         ri.fp[2] = Planef::intersection(frustum.getPlane(Frustum::Near),
00361                                         frustum.getPlane(Frustum::Bottom),
00362                                         frustum.getPlane(Frustum::Left));
00363         ri.fp[3] = Planef::intersection(frustum.getPlane(Frustum::Near),
00364                                         frustum.getPlane(Frustum::Bottom),
00365                                         frustum.getPlane(Frustum::Right));
00366         ri.fp[4] = Planef::intersection(frustum.getPlane(Frustum::Far),
00367                                         frustum.getPlane(Frustum::Top),
00368                                         frustum.getPlane(Frustum::Left));
00369         ri.fp[5] = Planef::intersection(frustum.getPlane(Frustum::Far),
00370                                         frustum.getPlane(Frustum::Top),
00371                                         frustum.getPlane(Frustum::Right));
00372         ri.fp[6] = Planef::intersection(frustum.getPlane(Frustum::Far),
00373                                         frustum.getPlane(Frustum::Bottom),
00374                                         frustum.getPlane(Frustum::Left));
00375         ri.fp[7] = Planef::intersection(frustum.getPlane(Frustum::Far),
00376                                         frustum.getPlane(Frustum::Bottom),
00377                                         frustum.getPlane(Frustum::Right));
00378 
00379 
00380 
00381 #ifdef SHOW_PATCH_VISIBILITY
00382         {
00383             for (int i = 0; i < MaxPatchesShown; i++)
00384                 visiblePatches[i] = 0;
00385         }
00386 #endif // SHOW_PATCH_VISIBILITY
00387 
00388         int nPatches = 0;
00389         {
00390             int extent = maxDivisions / 2;
00391 
00392             for (int i = 0; i < 2; i++)
00393             {
00394                 for (int j = 0; j < 2; j++)
00395                 {
00396                     nPatches += renderPatches(i * extent / 2, j * extent,
00397                                               extent, split / 2, ri);
00398                 }
00399             }
00400         }
00401         // cout << "Rendered " << nPatches << " of " << square(split) << " patches\n";
00402     }
00403 
00404     glDisableClientState(GL_VERTEX_ARRAY);
00405     if ((attributes & Normals) != 0)
00406         glDisableClientState(GL_NORMAL_ARRAY);
00407 
00408     if ((attributes & Tangents) != 0)
00409     {
00410         VertexProcessor* vproc = context.getVertexProcessor();
00411         vproc->disableAttribArray(6);
00412     }
00413 
00414     for (i = 0; i < nTextures; i++)
00415     {
00416         tex[i]->endUsage();
00417 
00418         if (nTextures > 1)
00419         {
00420             glx::glClientActiveTextureARB(GL_TEXTURE0_ARB + i);
00421             glx::glActiveTextureARB(GL_TEXTURE0_ARB + i);
00422         }
00423         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00424         if (i > 0)
00425             glDisable(GL_TEXTURE_2D);
00426     }
00427 
00428     if (nTextures > 1)
00429     {
00430         glx::glClientActiveTextureARB(GL_TEXTURE0_ARB);
00431         glx::glActiveTextureARB(GL_TEXTURE0_ARB);
00432     }
00433 
00434     if (useVertexBuffers)
00435     {
00436         glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00437         glx::glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00438         vertices = NULL;
00439     }
00440 
00441 #ifdef SHOW_FRUSTUM
00442     // Debugging code for visualizing the frustum.
00443     glMatrixMode(GL_PROJECTION);
00444     glPushMatrix();
00445     glLoadIdentity();
00446     gluPerspective(45.0, 1.3333f, 1.0f, 100.0f);
00447     glMatrixMode(GL_MODELVIEW);
00448     glPushMatrix();
00449     glLoadIdentity();
00450     glDisable(GL_TEXTURE_2D);
00451     glDisable(GL_LIGHTING);
00452     glColor4f(1, 0, 0, 1);
00453     glTranslatef(0, 0, -20);
00454     glBegin(GL_LINES);
00455     glVertex(ri.fp[0]); glVertex(ri.fp[1]);
00456     glVertex(ri.fp[0]); glVertex(ri.fp[2]);
00457     glVertex(ri.fp[3]); glVertex(ri.fp[1]);
00458     glVertex(ri.fp[3]); glVertex(ri.fp[2]);
00459     glVertex(ri.fp[4]); glVertex(ri.fp[5]);
00460     glVertex(ri.fp[4]); glVertex(ri.fp[6]);
00461     glVertex(ri.fp[7]); glVertex(ri.fp[5]);
00462     glVertex(ri.fp[7]); glVertex(ri.fp[6]);
00463     glVertex(ri.fp[0]); glVertex(ri.fp[4]);
00464     glVertex(ri.fp[1]); glVertex(ri.fp[5]);
00465     glVertex(ri.fp[2]); glVertex(ri.fp[6]);
00466     glVertex(ri.fp[3]); glVertex(ri.fp[7]);
00467     glEnd();
00468 
00469     // Render axes representing the unit sphere.
00470     glColor4f(0, 1, 0, 1);
00471     glBegin(GL_LINES);
00472     glVertex3f(-1, 0, 0); glVertex3f(1, 0, 0);
00473     glVertex3f(0, -1, 0); glVertex3f(0, 1, 0);
00474     glVertex3f(0, 0, -1); glVertex3f(1, 0, 1);
00475     glEnd();
00476     glMatrixMode(GL_PROJECTION);
00477     glPopMatrix();
00478     glMatrixMode(GL_MODELVIEW);
00479     glPopMatrix();
00480 #endif
00481 
00482 #ifdef SHOW_PATCH_VISIBILITY
00483     // Debugging code for visualizing the frustum.
00484     glMatrixMode(GL_PROJECTION);
00485     glPushMatrix();
00486     glLoadIdentity();
00487     glMatrixMode(GL_MODELVIEW);
00488     glPushMatrix();
00489     glLoadIdentity();
00490     glDisable(GL_TEXTURE_2D);
00491     glDisable(GL_LIGHTING);
00492     glColor4f(1, 0, 1, 1);
00493 
00494     {
00495         int width = split;
00496         int height = width / 2;
00497         float patchWidth = 1.0f / (float) width;
00498         float patchHeight = 1.0f / (float) height;
00499         if (width * height <= MaxPatchesShown)
00500         {
00501             for (int i = 0; i < height; i++)
00502             {
00503                 for (int j = 0; j < width; j++)
00504                 {
00505                     glPushMatrix();
00506                     glTranslatef(-0.5f + j * patchWidth,
00507                                  1.0f - i * patchHeight,
00508                                  0.0f);
00509                     if (visiblePatches[i * width + j])
00510                         glBegin(GL_QUADS);
00511                     else
00512                         glBegin(GL_LINE_LOOP);
00513                     glVertex3f(0.0f, 0.0f, 0.0f);
00514                     glVertex3f(0.0f, -patchHeight, 0.0f);
00515                     glVertex3f(patchWidth, -patchHeight, 0.0f);
00516                     glVertex3f(patchWidth, 0.0f, 0.0f);
00517                     glEnd();
00518                     glPopMatrix();
00519                 }
00520             }
00521         }
00522     }
00523 
00524     glMatrixMode(GL_PROJECTION);
00525     glPopMatrix();
00526     glMatrixMode(GL_MODELVIEW);
00527     glPopMatrix();
00528 #endif // SHOW_PATCH_VISIBILITY
00529 }

int LODSphereMesh::renderPatches int  phi0,
int  theta0,
int  extent,
int  level,
const RenderInfo
[private]
 

Definition at line 532 of file lodspheremesh.cpp.

References Point3< T >::distanceTo(), Plane< T >::distanceTo(), Vector3< T >::length(), Vector3< T >::lengthSquared(), max, Vector3< T >::normalize(), renderSection(), spherePoint(), Point3< T >::x, Point3< T >::y, and Point3< T >::z.

Referenced by render().

00536 {
00537     int thetaExtent = extent;
00538     int phiExtent = extent / 2;
00539 
00540     // Compute the plane separating this section of the sphere from
00541     // the rest of the sphere.  If the view frustum lies entirely
00542     // on the side of the plane that does not contain the sphere
00543     // patch, we cull the patch.
00544     Point3f p0 = spherePoint(theta0, phi0);
00545     Point3f p1 = spherePoint(theta0 + thetaExtent, phi0);
00546     Point3f p2 = spherePoint(theta0 + thetaExtent,
00547                              phi0 + phiExtent);
00548     Point3f p3 = spherePoint(theta0, phi0 + phiExtent);
00549     Vec3f v0 = p1 - p0;
00550     Vec3f v2 = p3 - p2;
00551     Vec3f normal;
00552     if (v0.lengthSquared() > v2.lengthSquared())
00553         normal = (p0 - p3) ^ v0;
00554     else
00555         normal = (p2 - p1) ^ v2;
00556 
00557     // If the normal is near zero length, something's going wrong
00558     assert(normal.length() > 1.0e-6);
00559     normal.normalize();
00560     Planef separatingPlane(normal, p0);
00561 
00562     bool outside = true;
00563 #if 1
00564     for (int k = 0; k < 8; k++)
00565     {
00566         if (separatingPlane.distanceTo(ri.fp[k]) > 0.0f)
00567         {
00568             outside = false;
00569             break;
00570         }
00571     }
00572 
00573     // If this patch is outside the view frustum, so are all of its subpatches
00574     if (outside)
00575         return 0;
00576 #else
00577     outside = false;
00578 #endif
00579 
00580     // Second cull test uses the bounding sphere of the patch
00581 #if 0
00582     // Is this a better choice for the patch center?
00583     Point3f patchCenter = spherePoint(theta0 + thetaExtent / 2,
00584                                       phi0 + phiExtent / 2);
00585 #else
00586     // . . . or is the average of the points better?
00587     Point3f patchCenter = Point3f(p0.x + p1.x + p2.x + p3.x,
00588                                   p0.y + p1.y + p2.y + p3.y,
00589                                   p0.z + p1.z + p2.z + p3.z) * 0.25f;
00590 #endif
00591     float boundingRadius = 0.0f;
00592     boundingRadius = max(boundingRadius, patchCenter.distanceTo(p0));
00593     boundingRadius = max(boundingRadius, patchCenter.distanceTo(p1));
00594     boundingRadius = max(boundingRadius, patchCenter.distanceTo(p2));
00595     boundingRadius = max(boundingRadius, patchCenter.distanceTo(p3));
00596     if (ri.frustum.testSphere(patchCenter, boundingRadius) == Frustum::Outside)
00597         outside = true;
00598 
00599     if (outside)
00600     {
00601         return 0;
00602     }
00603     else if (level == 1)
00604     {
00605         renderSection(phi0, theta0, thetaExtent, ri);
00606         return 1;
00607     }
00608     else
00609     {
00610         int nRendered = 0;
00611         for (int i = 0; i < 2; i++)
00612         {
00613             for (int j = 0; j < 2; j++)
00614             {
00615                 nRendered += renderPatches(phi0 + phiExtent / 2 * i,
00616                                            theta0 + thetaExtent / 2 * j,
00617                                            extent / 2,
00618                                            level / 2,
00619                                            ri);
00620             }
00621         }
00622         return nRendered;
00623     }
00624 }

void LODSphereMesh::renderSection int  phi0,
int  theta0,
int  extent,
const RenderInfo
[private]
 

Definition at line 627 of file lodspheremesh.cpp.

References VertexProcessor::attribArray(), cosPhi, cosTheta, currentVB, TextureTile::du, TextureTile::dv, Texture::getTile(), Texture::getUTileCount(), Texture::getVTileCount(), GL_ARRAY_BUFFER_ARB, GL_TEXTURE0_ARB, GL_WRITE_ONLY_ARB, glx::glActiveTextureARB, glx::glBindBufferARB, glx::glClientActiveTextureARB, glx::glMapBufferARB, indices, MAX_SPHERE_MESH_TEXTURES, maxDivisions, Normals, nTexturesUsed, NUM_SPHERE_VERTEX_BUFFERS, phiDivisions, sinPhi, sinTheta, subtextures, Tangents, TextureTile::texID, textures, thetaDivisions, TextureTile::u, useVertexBuffers, TextureTile::v, vertexBuffers, vertexSize, and vertices.

Referenced by render(), and renderPatches().

00630 {
00631 #ifdef SHOW_PATCH_VISIBILITY
00632     {
00633         int width = thetaDivisions / extent;
00634         int height = phiDivisions / extent;
00635         int x = theta0 / extent;
00636         int y = phi0 / extent;
00637         if (width * height <= MaxPatchesShown)
00638             visiblePatches[y * width + x] = 1;
00639     }
00640 #endif // SHOW_PATCH_VISIBILITY
00641 
00642     GLsizei stride = (GLsizei) (vertexSize * sizeof(float));
00643     int tangentOffset = 3;
00644     int texCoordOffset = ((ri.attributes & Tangents) != 0) ? 6 : 3;
00645     float* vertexBase = useVertexBuffers ? (float*) NULL : vertices;
00646 
00647     glVertexPointer(3, GL_FLOAT, stride, vertexBase + 0);
00648     if ((ri.attributes & Normals) != 0)
00649         glNormalPointer(GL_FLOAT, stride, vertexBase);
00650 
00651     for (int tc = 0; tc < nTexturesUsed; tc++)
00652     {
00653         if (nTexturesUsed > 1)
00654             glx::glClientActiveTextureARB(GL_TEXTURE0_ARB + tc);
00655         glTexCoordPointer(2, GL_FLOAT, stride,  vertexBase + (tc * 2) + texCoordOffset);
00656     }
00657 
00658     if ((ri.attributes & Tangents) != 0)
00659     {
00660         VertexProcessor* vproc = ri.context.getVertexProcessor();
00661         vproc->attribArray(6, 3, GL_FLOAT, stride, vertexBase + tangentOffset);
00662     }
00663 
00664     // assert(ri.step >= minStep);
00665     // assert(phi0 + extent <= maxDivisions);
00666     // assert(theta0 + extent / 2 < maxDivisions);
00667     // assert(isPow2(extent));
00668     int thetaExtent = extent;
00669     int phiExtent = extent / 2;
00670     int theta1 = theta0 + thetaExtent;
00671     int phi1 = phi0 + phiExtent;
00672     int n3 = 0;
00673     int n2 = 0;
00674 
00675     float du[MAX_SPHERE_MESH_TEXTURES];
00676     float dv[MAX_SPHERE_MESH_TEXTURES];
00677     float u0[MAX_SPHERE_MESH_TEXTURES];
00678     float v0[MAX_SPHERE_MESH_TEXTURES];
00679 
00680 
00681     if (useVertexBuffers)
00682     {
00683         vertices = reinterpret_cast<float*>(glx::glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
00684         if (vertices == NULL)
00685             return;
00686     }
00687 
00688     // Set the current texture.  This is necessary because the texture
00689     // may be split into subtextures.
00690     for (int tex = 0; tex < nTexturesUsed; tex++)
00691     {
00692         du[tex] = (float) 1.0f / thetaDivisions;;
00693         dv[tex] = (float) 1.0f / phiDivisions;;
00694         u0[tex] = 1.0f;
00695         v0[tex] = 1.0f;
00696 
00697         if (textures[tex] != NULL)
00698         {
00699             int uTexSplit = textures[tex]->getUTileCount(ri.texLOD[tex]);
00700             int vTexSplit = textures[tex]->getVTileCount(ri.texLOD[tex]);
00701             int patchSplit = maxDivisions / extent;
00702             assert(patchSplit >= uTexSplit && patchSplit >= vTexSplit);
00703 
00704             int u = theta0 / thetaExtent;
00705             int v = phi0 / phiExtent;
00706             int patchesPerUSubtex = patchSplit / uTexSplit;
00707             int patchesPerVSubtex = patchSplit / vTexSplit;
00708 
00709             du[tex] *= uTexSplit;
00710             dv[tex] *= vTexSplit;
00711             u0[tex] = 1.0f - ((float) (u % patchesPerUSubtex) /
00712                               (float) patchesPerUSubtex);
00713             v0[tex] = 1.0f - ((float) (v % patchesPerVSubtex) /
00714                               (float) patchesPerVSubtex);
00715             u0[tex] += theta0 * du[tex];
00716             v0[tex] += phi0 * dv[tex];
00717 
00718             u /= patchesPerUSubtex;
00719             v /= patchesPerVSubtex;
00720 
00721             if (nTexturesUsed > 1)
00722                 glx::glActiveTextureARB(GL_TEXTURE0_ARB + tex);
00723             TextureTile tile = textures[tex]->getTile(ri.texLOD[tex],
00724                                                       uTexSplit - u - 1,
00725                                                       vTexSplit - v - 1);
00726             du[tex] *= tile.du;
00727             dv[tex] *= tile.dv;
00728             u0[tex] = u0[tex] * tile.du + tile.u;
00729             v0[tex] = v0[tex] * tile.dv + tile.v;
00730 
00731             // We track the current texture to avoid unnecessary and costly
00732             // texture state changes.
00733             if (tile.texID != subtextures[tex])
00734             {
00735                 glBindTexture(GL_TEXTURE_2D, tile.texID);
00736                 subtextures[tex] = tile.texID;
00737             }
00738         }
00739     }
00740 
00741     int vindex = 0;
00742     for (int phi = phi0; phi <= phi1; phi += ri.step)
00743     {
00744         float cphi = cosPhi[phi];
00745         float sphi = sinPhi[phi];
00746 
00747         if ((ri.attributes & Tangents) != 0)
00748         {
00749             for (int theta = theta0; theta <= theta1; theta += ri.step)
00750             {
00751                 float ctheta = cosTheta[theta];
00752                 float stheta = sinTheta[theta];
00753 
00754                 vertices[vindex]      = cphi * ctheta;
00755                 vertices[vindex + 1]  = sphi;
00756                 vertices[vindex + 2]  = cphi * stheta;
00757 
00758                 // Compute the tangent--required for bump mapping
00759                 vertices[vindex + 3] = stheta;
00760                 vertices[vindex + 4] = 0.0f;
00761                 vertices[vindex + 5] = -ctheta;
00762 
00763                 vindex += 6;
00764 
00765                 for (int tex = 0; tex < nTexturesUsed; tex++)
00766                 {
00767                     vertices[vindex]     = u0[tex] - theta * du[tex];
00768                     vertices[vindex + 1] = v0[tex] - phi * dv[tex];
00769                     vindex += 2;
00770                 }
00771             }
00772         }
00773         else
00774         {
00775             for (int theta = theta0; theta <= theta1; theta += ri.step)
00776             {
00777                 float ctheta = cosTheta[theta];
00778                 float stheta = sinTheta[theta];
00779 
00780                 vertices[vindex]      = cphi * ctheta;
00781                 vertices[vindex + 1]  = sphi;
00782                 vertices[vindex + 2]  = cphi * stheta;
00783 
00784                 vindex += 3;
00785 
00786                 for (int tex = 0; tex < nTexturesUsed; tex++)
00787                 {
00788                     vertices[vindex]     = u0[tex] - theta * du[tex];
00789                     vertices[vindex + 1] = v0[tex] - phi * dv[tex];
00790                     vindex += 2;
00791                 }
00792             }
00793         }
00794     }
00795 
00796     if (useVertexBuffers)
00797     {
00798         vertices = NULL;
00799         if (!glx::glUnmapBufferARB(GL_ARRAY_BUFFER_ARB))
00800             return;
00801     }
00802 
00803     // TODO: Fix this--number of rings can reach zero and cause dropout
00804     // int nRings = max(phiExtent / ri.step, 1); // buggy
00805     int nRings = phiExtent / ri.step;
00806     int nSlices = thetaExtent / ri.step;
00807     unsigned short* indexBase = useVertexBuffers ? (unsigned short*) NULL : indices;
00808     for (int i = 0; i < nRings; i++)
00809     {
00810         glDrawElements(GL_QUAD_STRIP,
00811                        (nSlices + 1) * 2,
00812                        GL_UNSIGNED_SHORT,
00813                        indexBase + (nSlices + 1) * 2 * i);
00814     }
00815 
00816     // Cycle through the vertex buffers
00817     if (useVertexBuffers)
00818     {
00819         currentVB++;
00820         if (currentVB == NUM_SPHERE_VERTEX_BUFFERS)
00821             currentVB = 0;
00822         glx::glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffers[currentVB]);
00823     }
00824 }


Member Data Documentation

int LODSphereMesh::currentVB [private]
 

Definition at line 92 of file lodspheremesh.h.

Referenced by render(), and renderSection().

unsigned int LODSphereMesh::indexBuffer [private]
 

Definition at line 94 of file lodspheremesh.h.

Referenced by render().

unsigned short* LODSphereMesh::indices [private]
 

Definition at line 84 of file lodspheremesh.h.

Referenced by LODSphereMesh(), render(), and renderSection().

int LODSphereMesh::maxVertices [private]
 

Definition at line 80 of file lodspheremesh.h.

Referenced by LODSphereMesh(), and render().

int LODSphereMesh::nIndices [private]
 

Definition at line 83 of file lodspheremesh.h.

Referenced by LODSphereMesh(), and render().

int LODSphereMesh::nTexturesUsed [private]
 

Definition at line 86 of file lodspheremesh.h.

Referenced by render(), and renderSection().

unsigned int LODSphereMesh::subtextures[MAX_SPHERE_MESH_TEXTURES] [private]
 

Definition at line 88 of file lodspheremesh.h.

Referenced by render(), and renderSection().

Texture* LODSphereMesh::textures[MAX_SPHERE_MESH_TEXTURES] [private]
 

Definition at line 87 of file lodspheremesh.h.

Referenced by render(), and renderSection().

bool LODSphereMesh::useVertexBuffers [private]
 

Definition at line 91 of file lodspheremesh.h.

Referenced by render(), and renderSection().

unsigned int LODSphereMesh::vertexBuffers[NUM_SPHERE_VERTEX_BUFFERS] [private]
 

Definition at line 93 of file lodspheremesh.h.

Referenced by render(), and renderSection().

bool LODSphereMesh::vertexBuffersInitialized [private]
 

Definition at line 90 of file lodspheremesh.h.

Referenced by render().

int LODSphereMesh::vertexSize [private]
 

Definition at line 81 of file lodspheremesh.h.

Referenced by render(), and renderSection().

float* LODSphereMesh::vertices [private]
 

Definition at line 78 of file lodspheremesh.h.

Referenced by LODSphereMesh(), render(), renderSection(), and ~LODSphereMesh().


The documentation for this class was generated from the following files:
Generated on Sat Jan 14 22:33:26 2006 for Celestia by  doxygen 1.4.1