#include <lodspheremesh.h>
Collaboration diagram for LODSphereMesh:

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] |
| Texture * | textures [MAX_SPHERE_MESH_TEXTURES] |
| bool | useVertexBuffers |
| unsigned int | vertexBuffers [NUM_SPHERE_VERTEX_BUFFERS] |
| bool | vertexBuffersInitialized |
| int | vertexSize |
| float * | vertices |
Classes | |
| struct | RenderInfo |
|
|
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 };
|
|
|
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 }
|
|
|
Definition at line 114 of file lodspheremesh.cpp. References vertices. 00115 {
00116 if (vertices != NULL)
00117 delete[] vertices;
00118 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
Definition at line 92 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 94 of file lodspheremesh.h. Referenced by render(). |
|
|
Definition at line 84 of file lodspheremesh.h. Referenced by LODSphereMesh(), render(), and renderSection(). |
|
|
Definition at line 80 of file lodspheremesh.h. Referenced by LODSphereMesh(), and render(). |
|
|
Definition at line 83 of file lodspheremesh.h. Referenced by LODSphereMesh(), and render(). |
|
|
Definition at line 86 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 88 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 87 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 91 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 93 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 90 of file lodspheremesh.h. Referenced by render(). |
|
|
Definition at line 81 of file lodspheremesh.h. Referenced by render(), and renderSection(). |
|
|
Definition at line 78 of file lodspheremesh.h. Referenced by LODSphereMesh(), render(), renderSection(), and ~LODSphereMesh(). |
1.4.1