00001
00015 #include "../common/standard.h"
00016 #include "VoxelCube.h"
00017 #include "GLBitmapBuffer.h"
00018 #include "MarchingCubesTables.h"
00019 #include "GLutils.h"
00020
00021 #include <GL/glu.h>
00022
00023 #include <map>
00024
00025
00030 std::vector< Vertex > VoxelCube::calculateVoxelCorners (int xpos, int ypos, int zpos) const
00031 {
00032 double halfVoxelSize = voxelSize / 2.;
00033 double halfCubeSize = voxelsPerSide * halfVoxelSize;
00034
00035 Vertex origin = Vertex (-halfCubeSize + center[0], -halfCubeSize + center[1], -halfCubeSize + center[2]);
00036
00037 origin[0] += voxelSize * xpos;
00038 origin[1] += voxelSize * ypos;
00039 origin[2] += voxelSize * zpos;
00040
00041 std::vector< Vertex > rtn;
00042 for (int z = 0; z < 2; z++)
00043 {
00044 for (int y = 0; y < 2; y++)
00045 {
00046 for (int x = 0; x < 2; x++)
00047 {
00048 Vertex pt = origin;
00049 pt[0] += voxelSize*x;
00050 pt[1] += voxelSize*y;
00051 pt[2] += voxelSize*z;
00052
00053 rtn.push_back (pt);
00054 }
00055 }
00056 }
00057
00058 return rtn;
00059 }
00060
00061
00067 void VoxelCube::setTransparent(SurfaceVoxelList::iterator i)
00068 {
00069 VoxelPos &p = *i;
00070 int index = PosToIndex (p[0], p[1], p[2]);
00071 solids[index] = false;
00072 }
00073
00074
00080 void VoxelCube::exposeSurroundingVoxels (SurfaceVoxelList::iterator i)
00081 {
00082 VoxelPos &p = *i;
00083
00084 unsigned int x = p[0];
00085 unsigned int y = p[1];
00086 unsigned int z = p[2];
00087
00088
00089
00090
00091 VoxelPos x1(x-1, y, z);
00092 VoxelPos y1(x, y-1, z);
00093 VoxelPos z1(x, y, z-1);
00094 VoxelPos x2(x+1, y, z);
00095 VoxelPos y2(x, y+1, z);
00096 VoxelPos z2(x, y, z+1);
00097
00098
00099
00100
00101 unsigned int maxVoxel = voxelsPerSide - 1;
00102
00103 if (x > 0 && !isTransparent(x1)) svl.push_back (x1);
00104 if (y > 0 && !isTransparent(y1)) svl.push_back (y1);
00105 if (z > 0 && !isTransparent(z1)) svl.push_back (z1);
00106
00107 if (x < maxVoxel && !isTransparent(x2)) svl.push_back (x2);
00108 if (y < maxVoxel && !isTransparent(y2)) svl.push_back (y2);
00109 if (z < maxVoxel && !isTransparent(z2)) svl.push_back (z2);
00110 }
00111
00112
00113
00122 void VoxelCube::setFinalColor (SurfaceVoxelList::iterator i, RgbByte &color)
00123 {
00124 VoxelPos &pos = *i;
00125
00126 ColoredVoxelPos cvp(pos, color);
00127
00128 svlColored.push_back (cvp);
00129 }
00130
00131
00132
00136 void VoxelCube::fillItemBufferArray (Viewpoint &image)
00137 {
00138 GLBitmapBuffer bitbuff;
00139 int width = image.getWidth();
00140 int height = image.getHeight();
00141
00142
00143
00144
00145 bitbuff.create(width, height);
00146 bitbuff.select();
00147
00148
00149 glMatrixMode(GL_PROJECTION);
00150 glLoadMatrixd(image.getProjectionMatrix());
00151
00152
00153 glMatrixMode(GL_MODELVIEW);
00154 glLoadMatrixd(image.getModelviewMatrix());
00155
00156
00157 glViewport (0, 0, width, height);
00158 glEnable (GL_DEPTH_TEST);
00159 glEnable (GL_CULL_FACE);
00160
00161
00162
00163 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00164
00165 double halfVoxelSize = voxelSize / 2.;
00166 double halfCubeSize = voxelsPerSide * halfVoxelSize;
00167
00168 glMatrixMode (GL_MODELVIEW);
00169 glPushMatrix();
00170 glTranslated(center[0], center[1], center[2]);
00171 glTranslated (-halfCubeSize, -halfCubeSize, -halfCubeSize);
00172 glTranslated (halfVoxelSize, halfVoxelSize, halfVoxelSize);
00173
00174 SurfaceVoxelList::iterator i;
00175 unsigned int id;
00176 for (i = svl.begin(); i != svl.end(); i++)
00177 {
00178 VoxelPos &pos = *i;
00179 glPushMatrix();
00180 glTranslated (pos[0]*voxelSize, pos[1]*voxelSize, pos[2]*voxelSize);
00181
00182 id = PosToIdentifier(pos[0], pos[1], pos[2]);
00183 glColor3ubv ((GLubyte*)&id);
00184
00185 drawCube (voxelSize, GL_QUADS);
00186 glPopMatrix();
00187 }
00188
00189 glPopMatrix();
00190
00191 glFinish();
00192
00193
00194 glReadPixels (
00195 0, 0,
00196 width, height,
00197 GL_RGBA, GL_UNSIGNED_BYTE,
00198 &image.imageBuffer[0]);
00199
00200 bitbuff.unselect();
00201 }
00202
00203
00204
00211 ColorVertex Interpolate(Vertex &v1, Vertex &v2, double tVal1, double tVal2, float isoLevel)
00212 {
00213 ColorVertex interpolation;
00214 float mu;
00215
00216 mu = float((isoLevel - tVal1))/(tVal2 - tVal1);
00217 interpolation.pos[0] = v1[0] + mu*(v2[0] - v1[0]);
00218 interpolation.pos[1] = v1[1] + mu*(v2[1] - v1[1]);
00219 interpolation.pos[2] = v1[2] + mu*(v2[2] - v1[2]);
00220
00221 return interpolation;
00222 }
00223
00224
00225
00232 ColorVertex VoxelCube::calculateIntersection(ColVector< 3, unsigned int> &curOrigin, unsigned int nEdgeNo, float isoLevel, ColorMap &colorMap)
00233 {
00234 float x1, y1, z1, x2, y2, z2;
00235 unsigned int v1x = curOrigin[0], v1y = curOrigin[1], v1z = curOrigin[2];
00236 unsigned int v2x = curOrigin[0], v2y = curOrigin[1], v2z = curOrigin[2];
00237
00238 switch (nEdgeNo)
00239 {
00240 case 0:
00241 v2y += 1;
00242 break;
00243 case 1:
00244 v1y += 1;
00245 v2x += 1;
00246 v2y += 1;
00247 break;
00248 case 2:
00249 v1x += 1;
00250 v1y += 1;
00251 v2x += 1;
00252 break;
00253 case 3:
00254 v1x += 1;
00255 break;
00256 case 4:
00257 v1z += 1;
00258 v2y += 1;
00259 v2z += 1;
00260 break;
00261 case 5:
00262 v1y += 1;
00263 v1z += 1;
00264 v2x += 1;
00265 v2y += 1;
00266 v2z += 1;
00267 break;
00268 case 6:
00269 v1x += 1;
00270 v1y += 1;
00271 v1z += 1;
00272 v2x += 1;
00273 v2z += 1;
00274 break;
00275 case 7:
00276 v1x += 1;
00277 v1z += 1;
00278 v2z += 1;
00279 break;
00280 case 8:
00281 v2z += 1;
00282 break;
00283 case 9:
00284 v1y += 1;
00285 v2y += 1;
00286 v2z += 1;
00287 break;
00288 case 10:
00289 v1x += 1;
00290 v1y += 1;
00291 v2x += 1;
00292 v2y += 1;
00293 v2z += 1;
00294 break;
00295 case 11:
00296 v1x += 1;
00297 v2x += 1;
00298 v2z += 1;
00299 break;
00300 }
00301
00302 x1 = v1x*voxelSize;
00303 y1 = v1y*voxelSize;
00304 z1 = v1z*voxelSize;
00305 x2 = v2x*voxelSize;
00306 y2 = v2y*voxelSize;
00307 z2 = v2z*voxelSize;
00308
00309 unsigned int nPointsInXDirection = (voxelsPerSide);
00310 unsigned int nPointsInSlice = nPointsInXDirection*(voxelsPerSide);
00311 int val1 = !isTransparent(v1x, v1y, v1z);
00312 int val2 = !isTransparent(v2x, v2y, v2z);
00313
00314 ColorVertex intersection = Interpolate(
00315 Vertex(x1, y1, z1),
00316 Vertex(x2, y2, z2),
00317 val1, val2, isoLevel);
00318
00319 VoxelPos va(v1x, v1y, v1z);
00320 VoxelPos vb(v2x, v2y, v2z);
00321
00322 RgbByte color1 (0,0,0);
00323 RgbByte color2 (0,0,0);
00324
00325 ColorMap::iterator i;
00326 #if 0
00327 i = colorMap.find(va);
00328 if (i != colorMap.end()) color1 = (*i).second;
00329
00330 i = colorMap.find(vb);
00331 if (i != colorMap.end()) color2 = (*i).second;
00332
00333 intersection.color = LERP(0.5,
00334 color1,
00335 color2);
00336 #else
00337 ColorMap::iterator i_first = colorMap.find(va);
00338 ColorMap::iterator i_second = colorMap.find(vb);
00339
00340 if (i_first != colorMap.end())
00341 {
00342 if (i_second != colorMap.end())
00343 intersection.color = LERP(0.5, (*i_first).second, (*i_second).second);
00344 else
00345 intersection.color = (*i_first).second;
00346 }
00347 else
00348 {
00349 if (i_second != colorMap.end())
00350 intersection.color = (*i_second).second;
00351 else
00352 intersection.color = RgbByte(1,0,0);
00353 }
00354 #endif
00355
00356
00357
00358 return intersection;
00359 }
00360
00361
00362
00363
00364
00371 unsigned int VoxelCube::GetEdgeID(unsigned int nX, unsigned int nY, unsigned int nZ, unsigned int nEdgeNo)
00372 {
00373 switch (nEdgeNo) {
00374 case 0:
00375 return PosToIndex(nX, nY, nZ) + 1;
00376 case 1:
00377 return PosToIndex(nX, nY + 1, nZ);
00378 case 2:
00379 return PosToIndex(nX + 1, nY, nZ) + 1;
00380 case 3:
00381 return PosToIndex(nX, nY, nZ);
00382 case 4:
00383 return PosToIndex(nX, nY, nZ + 1) + 1;
00384 case 5:
00385 return PosToIndex(nX, nY + 1, nZ + 1);
00386 case 6:
00387 return PosToIndex(nX + 1, nY, nZ + 1) + 1;
00388 case 7:
00389 return PosToIndex(nX, nY, nZ + 1);
00390 case 8:
00391 return PosToIndex(nX, nY, nZ) + 2;
00392 case 9:
00393 return PosToIndex(nX, nY + 1, nZ) + 2;
00394 case 10:
00395 return PosToIndex(nX + 1, nY + 1, nZ) + 2;
00396 case 11:
00397 return PosToIndex(nX + 1, nY, nZ) + 2;
00398 default:
00399
00400 throw ArgError("GetEdgeID(): invalid edge number");
00401 }
00402 }
00403
00404 struct TRIANGLE {
00405 unsigned int pointID[3];
00406 };
00407
00408 typedef std::map< unsigned int, ColorVertex > IdToVertexMap;
00409 typedef std::vector< TRIANGLE > TriangleArray;
00410
00411
00412
00413 void VoxelCube::constructColorMap (ColorMap &colorMap)
00414 {
00415 if (!svlColored.size())
00416 return;
00417
00418 ColoredSurfaceVoxelList::iterator i;
00419 for (i = svlColored.begin(); i != svlColored.end(); i++)
00420 {
00421 ColoredVoxelPos pos = (*i);
00422
00423 VoxelPos p;
00424 p[0] = pos[0]; p[1] = pos[1]; p[2] = pos[2];
00425 colorMap[p] = pos.color;
00426 }
00427 }
00428
00429
00430
00437 void VoxelCube::makeMesh(float isoLevel, QEM::ProgMesh &mesh)
00438 {
00439 ColorMap colorMap;
00440 constructColorMap (colorMap);
00441
00442 unsigned int nCells = voxelsPerSide - 1;
00443
00444 IdToVertexMap idVertexMap;
00445 TriangleArray tris;
00446
00447 for (int z = 0; z < nCells; z++)
00448 {
00449 for (int y = 0; y < nCells; y++)
00450 {
00451 for (int x = 0; x < nCells; x++)
00452 {
00453 unsigned int tableIndex = 0;
00454 ColVector<3, unsigned int> curOrigin (x,y,z);
00455
00456 if (isTransparent (x, y , z)) tableIndex |= 1;
00457 if (isTransparent (x, y+1, z)) tableIndex |= 2;
00458 if (isTransparent (x+1, y+1, z)) tableIndex |= 4;
00459 if (isTransparent (x+1, y, z)) tableIndex |= 8;
00460 if (isTransparent (x, y, z+1)) tableIndex |= 16;
00461 if (isTransparent (x, y+1, z+1)) tableIndex |= 32;
00462 if (isTransparent (x+1, y+1, z+1)) tableIndex |= 64;
00463 if (isTransparent (x+1, y, z+1)) tableIndex |= 128;
00464
00465 if (edgeTable[tableIndex] == 0)
00466 continue;
00467
00468 #define EDGETABLE_HAS(n) edgeTable[tableIndex] & (1 << n)
00469
00470
00471
00472 if (EDGETABLE_HAS (3)) {
00473 ColorVertex pt = calculateIntersection (curOrigin, 3, isoLevel, colorMap);
00474 unsigned int id = GetEdgeID(x, y, z, 3);
00475 idVertexMap[id] = pt;
00476 }
00477 if (EDGETABLE_HAS(0)) {
00478 ColorVertex pt = calculateIntersection (curOrigin, 0, isoLevel, colorMap);
00479 unsigned int id = GetEdgeID(x, y, z, 0);
00480 idVertexMap[id] = pt;
00481 }
00482 if (EDGETABLE_HAS(8)) {
00483 ColorVertex pt = calculateIntersection (curOrigin, 8, isoLevel, colorMap);
00484 unsigned int id = GetEdgeID(x, y, z, 8);
00485 idVertexMap[id] = pt;
00486 }
00487
00488 if (x == nCells - 1) {
00489 if (EDGETABLE_HAS(2)) {
00490 ColorVertex pt = calculateIntersection (curOrigin, 2, isoLevel, colorMap);
00491 unsigned int id = GetEdgeID(x, y, z, 2);
00492 idVertexMap[id] = pt;
00493 }
00494 if (EDGETABLE_HAS(11)) {
00495 ColorVertex pt = calculateIntersection (curOrigin, 11, isoLevel, colorMap);
00496 unsigned int id = GetEdgeID(x, y, z, 11);
00497 idVertexMap[id] = pt;
00498 }
00499 }
00500 if (y == nCells - 1) {
00501 if (EDGETABLE_HAS(1)) {
00502 ColorVertex pt = calculateIntersection (curOrigin, 1, isoLevel, colorMap);
00503 unsigned int id = GetEdgeID(x, y, z, 1);
00504 idVertexMap[id] = pt;
00505 }
00506 if (EDGETABLE_HAS(9)) {
00507 ColorVertex pt = calculateIntersection (curOrigin, 9, isoLevel, colorMap);
00508 unsigned int id = GetEdgeID(x, y, z, 9);
00509 idVertexMap[id] = pt;
00510 }
00511 }
00512 if (z == nCells - 1) {
00513 if (EDGETABLE_HAS(4)) {
00514 ColorVertex pt = calculateIntersection (curOrigin, 4, isoLevel, colorMap);
00515 unsigned int id = GetEdgeID(x, y, z, 4);
00516 idVertexMap[id] = pt;
00517 }
00518 if (EDGETABLE_HAS(7)) {
00519 ColorVertex pt = calculateIntersection (curOrigin, 7, isoLevel, colorMap);
00520 unsigned int id = GetEdgeID(x, y, z, 7);
00521 idVertexMap[id] = pt;
00522 }
00523 }
00524 if ((x==nCells - 1) && (y==nCells - 1))
00525 {
00526 if (EDGETABLE_HAS(10))
00527 {
00528 ColorVertex pt = calculateIntersection (curOrigin, 10, isoLevel, colorMap);
00529 unsigned int id = GetEdgeID(x, y, z, 10);
00530 idVertexMap[id] = pt;
00531 }
00532 }
00533 if ((x==nCells - 1) && (z==nCells - 1))
00534 {
00535 if (EDGETABLE_HAS(6))
00536 {
00537 ColorVertex pt = calculateIntersection (curOrigin, 6, isoLevel, colorMap);
00538 unsigned int id = GetEdgeID(x, y, z, 6);
00539 idVertexMap[id] = pt;
00540 }
00541 }
00542 if ((y==nCells - 1) && (z==nCells - 1))
00543 {
00544 if (EDGETABLE_HAS(5)) {
00545 ColorVertex pt = calculateIntersection (curOrigin, 5, isoLevel, colorMap);
00546 unsigned int id = GetEdgeID(x, y, z, 5);
00547 idVertexMap[id] = pt;
00548 }
00549 }
00550
00551 for (unsigned int i = 0; triTable[tableIndex][i] != -1; i += 3) {
00552
00553 TRIANGLE triangle;
00554 unsigned int pointID0, pointID1, pointID2;
00555 pointID0 = GetEdgeID(x, y, z, triTable[tableIndex][i]);
00556 pointID1 = GetEdgeID(x, y, z, triTable[tableIndex][i+1]);
00557 pointID2 = GetEdgeID(x, y, z, triTable[tableIndex][i+2]);
00558
00559 triangle.pointID[0] = pointID0;
00560 triangle.pointID[1] = pointID1;
00561 triangle.pointID[2] = pointID2;
00562
00563 tris.push_back(triangle);
00564 }
00565
00566 }
00567
00568 }
00569
00570 }
00571
00572 IdToVertexMap::iterator vertex_iter;
00573
00574 std::map< unsigned int, unsigned int> oursToTheirs;
00575
00576 float halfWidth = (float)(voxelsPerSide * voxelSize) / 2;
00577
00578 for (vertex_iter = idVertexMap.begin(); vertex_iter != idVertexMap.end(); vertex_iter++)
00579 {
00580 ColorVertex &v = (*vertex_iter).second;
00581
00582 unsigned int id = mesh.addVertexWithColor (v.pos[0], v.pos[1], v.pos[2], v.color);
00583 oursToTheirs[(*vertex_iter).first] = id;
00584 MTRACE ("added vertex %.3d: %.2lf %.2lf %.2lf\n",
00585 id, v.pos[0], v.pos[1], v.pos[2]);
00586 }
00587
00588 for (int i = 0; i < tris.size(); i++)
00589 {
00590 unsigned int a = tris[i].pointID[0];
00591 unsigned int b = tris[i].pointID[1];
00592 unsigned int c = tris[i].pointID[2];
00593
00594 MTRACE("Trying to add face ids (%.3d -> %3d) (%.3d -> %3d) (%.3d -> %3d)\n",
00595 a, oursToTheirs[a],
00596 b, oursToTheirs[b],
00597 c, oursToTheirs[c]);
00598
00599 if (a != b && b != c && a != c)
00600 {
00601 try {
00602 mesh.addFace(
00603 oursToTheirs[a],
00604 oursToTheirs[b],
00605 oursToTheirs[c]);
00606 }
00607 catch (...)
00608 {
00609 MTRACE("caught\n");
00610 }
00611 }
00612 }
00613
00614 }
00615
00616
00622 void VoxelCube::draw(bool bTranslateToCenter)
00623 {
00624 double halfVoxelSize = voxelSize / 2.;
00625 double halfCubeSize = voxelsPerSide * halfVoxelSize;
00626
00627 glPushAttrib (GL_ENABLE_BIT);
00628
00629 glDisable (GL_TEXTURE_2D);
00630
00631 glMatrixMode (GL_MODELVIEW);
00632 glPushMatrix();
00633 if (bTranslateToCenter)
00634 glTranslated(center[0], center[1], center[2]);
00635
00636 glTranslated(-halfCubeSize, -halfCubeSize, -halfCubeSize);
00637 glTranslated(halfVoxelSize, halfVoxelSize, halfVoxelSize);
00638
00639
00640
00641 if (svlColored.size())
00642 {
00643 ColoredSurfaceVoxelList::iterator i;
00644 for (i = svlColored.begin(); i != svlColored.end(); i++)
00645 {
00646 ColoredVoxelPos pos = (*i);
00647
00648 glPushMatrix();
00649
00650 glTranslated (
00651 pos[0] * voxelSize,
00652 pos[1] * voxelSize,
00653 pos[2] * voxelSize);
00654
00655 glColor3ub (pos.color[0], pos.color[1], pos.color[2]);
00656 drawCube (voxelSize, GL_QUADS);
00657
00658 glPopMatrix();
00659 }
00660 }
00661 else
00662 {
00663 SurfaceVoxelList::iterator i;
00664 for (i = svl.begin(); i != svl.end(); i++)
00665 {
00666 VoxelPos pos = (*i);
00667
00668 glPushMatrix();
00669
00670 glTranslated (
00671 pos[0] * voxelSize,
00672 pos[1] * voxelSize,
00673 pos[2] * voxelSize);
00674
00675 srand (pos[0]+pos[1]*voxelsPerSide+pos[2]*voxelsPerSide*voxelsPerSide);
00676
00677 glColor3f (
00678 (rand()%100)/100.,
00679 (rand()%100)/100.,
00680 (rand()%100)/100.);
00681 drawCube (voxelSize, GL_QUADS);
00682
00683 glPopMatrix();
00684 }
00685 }
00686 glPopMatrix();
00687
00688 glPopAttrib ();
00689 }
00690
00691
00692
00693
00694 double VoxelCube::getMinimumFarPlane (Vertex COP, Vertex lookatPoint) const
00695 {
00696 ColVector3 viewDirection = lookatPoint - COP;
00697 viewDirection.normalize();
00698
00699 double rtn = 0.0;
00700
00701 for (int x = -1; x <= 1; x+= 2)
00702 {
00703 for (int y = -1; y <= 1; y+= 2)
00704 {
00705 for (int z = -1; z <= 1; z += 2)
00706 {
00707 Vertex corner = center;
00708 corner[0] += (x * voxelSize * voxelsPerSide) / 2.;
00709 corner[1] += (y * voxelSize * voxelsPerSide) / 2.;
00710 corner[2] += (z * voxelSize * voxelsPerSide) / 2.;
00711
00712 ColVector3 diff = corner - COP;
00713
00714 ColVector3 diffDirection = diff;
00715 diffDirection.normalize();
00716
00717 double cos = diffDirection.dotProduct(viewDirection);
00718
00719 if (cos > 0)
00720 {
00721 double dist = cos * diff.getLength();
00722 rtn = MAX (rtn, dist);
00723 }
00724 }
00725 }
00726 }
00727
00728 return rtn;
00729 }
00730
00731
00735 bool VoxelCube::isTransparent (const VoxelPos &p) const
00736 {
00737 return isTransparent (p[0], p[1], p[2]);
00738 }
00739
00744 bool VoxelCube::isTransparent (int x, int y, int z) const
00745 {
00746 return !solids[PosToIndex (x,y,z)];
00747 }
00748
00749
00750
00757 void VoxelCube::setVoxelsPerSide (int vps)
00758 {
00759 if (vps < 1 || vps > 255) throw ArgError("VoxelCube::setVoxelsPerSide(): voxels per side must be between 1 and 255");
00760
00761 voxelsPerSide = vps;
00762
00763 svl.clear();
00764 svlColored.clear();
00765
00766
00767
00768 int max = voxelsPerSide - 1;
00769 for (int row = 0; row < voxelsPerSide; row++)
00770 for (int col = 0; col < voxelsPerSide; col++)
00771 {
00772 svl.push_back (VoxelPos(0,row,col));
00773 svl.push_back (VoxelPos(row,0,col));
00774 svl.push_back (VoxelPos(row,col,0));
00775
00776 svl.push_back (VoxelPos(max,row,col));
00777 svl.push_back (VoxelPos(row,max,col));
00778 svl.push_back (VoxelPos(row,col,max));
00779 }
00780
00781
00782
00783 solids.resize(vps*vps*vps);
00784
00785
00786
00787 std::fill(solids.begin(), solids.end(), true);
00788 }
00789
00790 unsigned int VoxelCube::PosToIdentifier (int x, int y, int z) const
00791 {
00792 unsigned int rtn = PosToIndex(x,y,z) + 1;
00793 return rtn;
00794 }
00795
00796
00797 unsigned int VoxelCube::PosToIndex (int x, int y, int z) const
00798 {
00799 if (x >= voxelsPerSide ||
00800 y >= voxelsPerSide ||
00801 z >= voxelsPerSide)
00802 {
00803 throw ArgError ("VoxelCube::getIndex(): you've asked for voxel (%d,%d,%d), but there are only %d voxels per side!",
00804 x,y,z,voxelsPerSide);
00805 }
00806
00807 return x + y*voxelsPerSide + z*voxelsPerSide*voxelsPerSide;
00808 }
00809
00810
00811
00812
00821 Rect< double > VoxelCube::getBoundingRect (std::vector< Vertex > &vertices, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4]) const
00822 {
00823 Rect< double > bounds;
00824
00825 double garbage;
00826 GLenum rtn = gluProject (
00827 vertices[0][0], vertices[0][1], vertices[0][2],
00828 modelMatrix,
00829 projMatrix,
00830 viewport,
00831 &bounds.left, &bounds.bottom,
00832 &garbage);
00833
00834 if (rtn != GL_TRUE)
00835 throw Error("VoxelCube::getBoundingRect(): gluProject failure.");
00836
00837 bounds.right = bounds.left;
00838 bounds.top = bounds.bottom;
00839
00840
00841
00842
00843
00844 for (int corner = 1; corner < 8; corner++)
00845 {
00846 double curx, cury;
00847
00848 rtn = gluProject (
00849 vertices[corner][0], vertices[corner][1], vertices[corner][2],
00850 modelMatrix,
00851 projMatrix,
00852 viewport,
00853 &curx, &cury,
00854 &garbage);
00855 if (rtn != GL_TRUE)
00856 throw Error("VoxelCube::getBoundingRect(): gluProject failure.");
00857
00858 bounds.expandToEnclosePoint (curx, cury);
00859 }
00860
00861
00862 bounds.bottom -= 1;
00863 bounds.left -= 1;
00864 bounds.right +=1;
00865 bounds.top +=1;
00866
00867 Rect< double > screen(
00868 viewport[0],
00869 viewport[2]-1,
00870 viewport[3]-1,
00871 viewport[1]);
00872
00873 bounds = bounds.intersectRect (screen);
00874 return bounds;
00875
00876 }