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

marchingcubes.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Tao Ju, 5/16/2007 <taoju@cs.wustl.edu>, code ported by Grant Tang
00007  * code extensively modified and optimized by David Woolford
00008  * Copyright (c) 2000-2006 Baylor College of Medicine
00009  *
00010  * This software is issued under a joint BSD/GNU license. You may use the
00011  * source code in this file under either license. However, note that the
00012  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00013  * so you are responsible for compliance with the licenses of these packages
00014  * if you opt to use BSD licensing. The warranty disclaimer below holds
00015  * in either instance.
00016  *
00017  * This complete copyright notice must be included in any revised version of the
00018  * source code. Additional authorship citations may be added, but existing
00019  * author citations must be preserved.
00020  *
00021  * This program is free software; you can redistribute it and/or modify
00022  * it under the terms of the GNU General Public License as published by
00023  * the Free Software Foundation; either version 2 of the License, or
00024  * (at your option) any later version.
00025  *
00026  * This program is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00029  * GNU General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU General Public License
00032  * along with this program; if not, write to the Free Software
00033  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00034  *
00035  * */
00036 
00037 #ifdef _WIN32
00038         #include <windows.h>
00039 #endif  //_WIN32
00040 
00041 #include "marchingcubes.h"
00042 
00043 #include <time.h>
00044 
00045 using namespace EMAN;
00046 #include "transform.h"
00047 #include "emobject.h"
00048 #include "vec3.h"
00049 
00050 #define min(a,b)(((a) < (b)) ? (a) : (b))
00051 #define max(a,b)(((a) > (b)) ? (a) : (b))
00052 
00053 //a2fVertexOffset lists the positions, relative to vertex0, of each of the 8 vertices of a cube
00054 static const int a2fVertexOffset[8][3] =
00055 {
00056                 {0, 0, 0},{1, 0, 0},{1, 1, 0},{0, 1, 0},
00057                 {0, 0, 1},{1, 0, 1},{1, 1, 1},{0, 1, 1}
00058 };
00059 
00060 
00061 static const int a2fPosXOffset[4][3] =
00062 {
00063         {2, 0, 0},{2, 1, 0},
00064         {2, 0, 1},{2, 1, 1}
00065 };
00066 
00067 static const int a2fPosYOffset[4][3] =
00068 {
00069         {1, 2, 0},{0, 2, 0},
00070         {1, 2, 1},{0, 2, 1}
00071 };
00072 
00073 static const int a2fPosZOffset[4][3] =
00074 {
00075         {0, 0, 2},{1, 0, 2},
00076         {1, 1, 2},{0, 1, 2}
00077 };
00078 
00079 static const int a2fPosXPosYOffset[2][3] =
00080 {
00081         {2, 2, 0},{2, 2, 1}
00082 };
00083 
00084 static const int a2fPosXPosZOffset[2][3] =
00085 {
00086         {2, 0, 2},{2, 1, 2}
00087 };
00088 
00089 static const int a2fPosYPosZOffset[2][3] =
00090 {
00091         {1, 2, 2},{0, 2, 2}
00092 };
00093 
00094 
00095 static const int a2fPosXPosZPosYOffset[3] =
00096 {
00097         2, 2, 2
00098 };
00099 
00100 //a2fVertexOffset lists the positions, relative to vertex0, of each of the 8 vertices of a cube
00101 static const int a2OddXOffset[8] =
00102 {
00103         1,0,0,1,
00104         1,0,0,1
00105 };
00106 
00107 static const int a2OddYOffset[8] =
00108 {
00109         1,1,0,0,
00110         1,1,0,0
00111 };
00112 
00113 static const int a2OddZOffset[8] =
00114 {
00115         1,1,1,1,
00116         0,0,0,0
00117 };
00118 
00119 //a2iEdgeConnection lists the index of the endpoint vertices for each of the 12 edges of the cube
00120 static const int a2iEdgeConnection[12][2] =
00121 {
00122                 {0,1}, {1,2}, {2,3}, {3,0},
00123                 {4,5}, {5,6}, {6,7}, {7,4},
00124                 {0,4}, {1,5}, {2,6}, {3,7}
00125 };
00126 
00127 //a2fEdgeDirection lists the direction vector (vertex1-vertex0) for each edge in the cube
00128 static const float a2fEdgeDirection[12][3] =
00129 {
00130                 {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
00131                 {1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0},{0.0, -1.0, 0.0},
00132                 {0.0, 0.0, 1.0},{0.0, 0.0, 1.0},{ 0.0, 0.0, 1.0},{0.0,  0.0, 1.0}
00133 };
00134 
00135 // right = 0, up = 1, back = 2
00136 static const int edgeLookUp[12][4] =
00137 {
00138         {0,0,0,0},{1,0,0,1},{0,1,0,0},{0,0,0,1},
00139         {0,0,1,0},{1,0,1,1},{0,1,1,0},{0,0,1,1},
00140         {0,0,0,2},{1,0,0,2},{1,1,0,2},{0,1,0,2}
00141 };
00142 
00143 MarchingCubes::MarchingCubes()
00144         : _isodl(0)
00145 {
00146 }
00147 
00148 MarchingCubes::MarchingCubes(EMData * em)
00149         : _isodl(0)
00150 {
00151         set_data(em);
00152 }
00153 
00154 void MarchingCubes::clear_min_max_vals()
00155 {
00156         for (vector<EMData*>::iterator it = minvals.begin(); it != minvals.end(); ++it)
00157         {
00158                 if ( (*it) != 0 ) delete *it;
00159         }
00160         minvals.clear();
00161 
00162         for (vector<EMData*>::iterator it = maxvals.begin(); it != maxvals.end(); ++it)
00163         {
00164                 if ( (*it) != 0 ) delete *it;
00165         }
00166         maxvals.clear();
00167 }
00168 
00169 bool MarchingCubes::calculate_min_max_vals()
00170 {
00171 
00172         if (_emdata == NULL ) throw NullPointerException("Error, cannot generate search tree if the overriding EMData object is NULL");
00173 
00174         clear_min_max_vals();
00175 
00176         int nx = _emdata->get_xsize();
00177         int ny = _emdata->get_ysize();
00178         int nz = _emdata->get_zsize();
00179 
00180         // Create the binary min max tree
00181         while ( nx > 1 || ny > 1 || nz > 1 )
00182         {
00183                 int size = minvals.size();
00184 
00185                 if ( size == 0 ){
00186                         Dict a;
00187                         // Setting search to 3 at the bottom level is most important.
00188                         // FIXME - d.woolford add comments heere
00189                         a["search"] = 3;
00190                         minvals.push_back(_emdata->process("math.minshrink",a));
00191                         maxvals.push_back(_emdata->process("math.maxshrink",a));
00192                 }else {
00193                         minvals.push_back(minvals[size-1]->process("math.minshrink"));
00194                         maxvals.push_back(maxvals[size-1]->process("math.maxshrink"));
00195                 }
00196 
00197                 nx = minvals[size]->get_xsize();
00198                 ny = minvals[size]->get_ysize();
00199                 nz = minvals[size]->get_zsize();
00200 #if MARCHING_CUBES_DEBUG
00201                 cout << "dims are " << nx << " " << ny << " " << nz << endl;
00202 #endif
00203         }
00204 
00205         drawing_level = -1;
00206 
00207         return true;
00208 }
00209 
00210 MarchingCubes::~MarchingCubes() {
00211         clear_min_max_vals();
00212 }
00213 
00214 Dict MarchingCubes::get_isosurface()
00215 {
00216         calculate_surface();
00217         Dict d;
00218         d.put("points", (float*)pp.get_data());
00219         for (unsigned int i = 0; i < ff.elem(); ++i ) ff[i] /= 3;
00220         d.put("faces", (unsigned int*)ff.get_data());
00221         d.put("normals", (float*)nn.get_data());
00222         d.put("size", ff.elem());
00223         return d;
00224 }
00225 
00226 void MarchingCubes::surface_face_z()
00227 {
00228         float* f = pp.get_data();
00229         float* n = nn.get_data();
00230         for (unsigned int i = 0; i < pp.elem(); i += 3 ) {
00231                 if (f[i+2] == 0.5) continue;
00232                 Vec3f z(0,0,1.0);
00233                 Vec3f axis(-n[i+1],n[i],0);
00234                 axis.normalize();
00235         
00236                 Dict d;
00237                 d["type"] = "spin";
00238                 d["Omega"] =  90.f;
00239                 d["n1"] = axis[0];
00240                 d["n2"] = axis[1];
00241                 d["n3"] = 0;
00242                 Transform t(d);
00243                 Vec3f delta = t*z;
00244                 
00245                 f[i] += delta[0]*.25f;
00246                 f[i+1] += delta[1]*.25f;
00247                 f[i+2] = 0.5;
00248         }
00249         
00250         for (unsigned int i = 0; i < nn.elem(); i += 3 ) {
00251                 n[i] = 0;
00252                 n[i+1] = 0;
00253                 n[i+2] = 1;
00254         }
00255 }
00256 
00257 void MarchingCubes::set_data(EMData* data)
00258 {
00259         if ( data->get_zsize() == 1 ) throw ImageDimensionException("The z dimension of the image must be greater than 1");
00260         _emdata = data;
00261         calculate_min_max_vals();
00262 }
00263 
00264 void MarchingCubes::set_surface_value(const float value) {
00265 
00266         if(_surf_value == value) return;
00267 
00268         _surf_value = value;
00269 
00270 }
00271 
00272 void MarchingCubes::calculate_surface() {
00273 
00274         if ( _emdata == 0 ) throw NullPointerException("Error, attempt to generate isosurface, but the emdata image object has not been set");
00275         if ( minvals.size() == 0 || maxvals.size() == 0 ) throw NotExistingObjectException("Vector of EMData pointers", "Error, the min and max val search trees have not been created");
00276 
00277         point_map.clear();
00278         pp.clear();
00279         nn.clear();
00280         ff.clear();
00281 
00282 #if MARCHING_CUBES_DEBUG
00283         int time0 = clock();
00284 #endif
00285 
00286         float min = minvals[minvals.size()-1]->get_value_at(0,0,0);
00287         float max = maxvals[minvals.size()-1]->get_value_at(0,0,0);
00288         if ( min < _surf_value &&  max > _surf_value) draw_cube(0,0,0,minvals.size()-1);
00289 
00290 #if MARCHING_CUBES_DEBUG
00291         int time1 = clock();
00292         cout << "It took " << (time1-time0) << " " << (float)(time1-time0)/CLOCKS_PER_SEC << " to traverse the search tree and generate polygons" << endl;
00293         cout << "... using surface value " << _surf_value << endl;
00294 #endif
00295 }
00296 
00297 void MarchingCubes::draw_cube(const int x, const int y, const int z, const int cur_level ) {
00298 
00299         if ( cur_level == drawing_level )
00300         {
00301                 EMData* e;
00302                 if ( drawing_level == - 1 ) e = _emdata;
00303                 else e = minvals[drawing_level];
00304                 if ( x < (e->get_xsize()-1) && y < (e->get_ysize()-1) && z < (e->get_zsize()-1))
00305                         marching_cube(x,y,z, cur_level);
00306         }
00307         else
00308         {
00309                 EMData* e;
00310                 if ( cur_level > 0 ) {
00311                         int xsize = minvals[cur_level-1]->get_xsize();
00312                         int ysize = minvals[cur_level-1]->get_ysize();
00313                         int zsize = minvals[cur_level-1]->get_zsize();
00314                         e = minvals[cur_level-1];
00315                         for(int i=0; i<8; ++i ) {
00316                                 int xx = 2*x+a2fVertexOffset[i][0];
00317                                 if ( xx >= xsize ) continue;
00318                                 int yy = 2*y+a2fVertexOffset[i][1];
00319                                 if ( yy >= ysize ) continue;
00320                                 int zz = 2*z+a2fVertexOffset[i][2];
00321                                 if ( zz >= zsize ) continue;
00322 
00323                                 float min = minvals[cur_level-1]->get_value_at(xx,yy,zz);
00324                                 float max = maxvals[cur_level-1]->get_value_at(xx,yy,zz);
00325                                 if ( min < _surf_value &&  max > _surf_value)
00326                                         draw_cube(xx,yy,zz,cur_level-1);
00327                         }
00328                 }
00329                 else {
00330                         e = _emdata;
00331                         for(int i=0; i<8; ++i ) {
00332                                         draw_cube(2*x+a2fVertexOffset[i][0],2*y+a2fVertexOffset[i][1],2*z+a2fVertexOffset[i][2],cur_level-1);
00333                         }
00334                 }
00335 
00336                 if ( x == (minvals[cur_level]->get_xsize()-1) ) {
00337                         if ( e->get_xsize() > 2*x ){
00338                                 for(int i=0; i<4; ++i ) {
00339                                         draw_cube(2*x+a2fPosXOffset[i][0],2*y+a2fPosXOffset[i][1],2*z+a2fPosXOffset[i][2],cur_level-1);
00340                                 }
00341                         }
00342                         if ( y == (minvals[cur_level]->get_ysize()-1) ) {
00343                                 if ( e->get_ysize() > 2*y ) {
00344                                         for(int i=0; i<2; ++i ) {
00345                                                 draw_cube(2*x+a2fPosXPosYOffset[i][0],2*y+a2fPosXPosYOffset[i][1],2*z+a2fPosXPosYOffset[i][2],cur_level-1);
00346                                         }
00347                                 }
00348                                 if (  z == (minvals[cur_level]->get_zsize()-1) ){
00349                                         if ( e->get_zsize() > 2*z ) {
00350                                                 draw_cube(2*x+2,2*y+2,2*z+2,cur_level-1);
00351                                         }
00352                                 }
00353                         }
00354                         if ( z == (minvals[cur_level]->get_zsize()-1) ) {
00355                                 if ( e->get_zsize() > 2*z ) {
00356                                         for(int i=0; i<2; ++i ) {
00357                                                 draw_cube(2*x+a2fPosXPosZOffset[i][0],2*y+a2fPosXPosZOffset[i][1],2*z+a2fPosXPosZOffset[i][2],cur_level-1);
00358                                         }
00359                                 }
00360                         }
00361                 }
00362                 if ( y == (minvals[cur_level]->get_ysize()-1) ) {
00363                         if ( e->get_ysize() > 2*y ) {
00364                                 for(int i=0; i<4; ++i ) {
00365                                         draw_cube(2*x+a2fPosYOffset[i][0],2*y+a2fPosYOffset[i][1],2*z+a2fPosYOffset[i][2],cur_level-1);
00366                                 }
00367                         }
00368                         if ( z == (minvals[cur_level]->get_ysize()-1) ) {
00369                                 if ( e->get_zsize() > 2*z ) {
00370                                         for(int i=0; i<2; ++i ) {
00371                                                 draw_cube(2*x+a2fPosYPosZOffset[i][0],2*y+a2fPosYPosZOffset[i][1],2*z+a2fPosYPosZOffset[i][2],cur_level-1);
00372                                         }
00373                                 }
00374                         }
00375                 }
00376                 if ( z == (minvals[cur_level]->get_zsize()-1) ) {
00377                         if ( e->get_zsize() > 2*z ) {
00378                                 for(int i=0; i<4; ++i ) {
00379                                         draw_cube(2*x+a2fPosZOffset[i][0],2*y+a2fPosZOffset[i][1],2*z+a2fPosZOffset[i][2],cur_level-1);
00380                                 }
00381                         }
00382                 }
00383 
00384         }
00385 }
00386 
00387 void MarchingCubes::get_normal(Vector3 &normal, int fX, int fY, int fZ)
00388 {
00389         normal[0] = _emdata->get_value_at(fX-1, fY, fZ) - _emdata->get_value_at(fX+1, fY, fZ);
00390     normal[1] = _emdata->get_value_at(fX, fY-1, fZ) - _emdata->get_value_at(fX, fY+1, fZ);
00391     normal[2] = _emdata->get_value_at(fX, fY, fZ-1) - _emdata->get_value_at(fX, fY, fZ+1);
00392     normal.normalize();
00393 }
00394 
00395 float MarchingCubes::get_offset(float fValue1, float fValue2, float fValueDesired)
00396 {
00397         float fDelta = fValue2 - fValue1;
00398 
00399         if(fDelta == 0.0f)
00400         {
00401                 return 0.5f;
00402         }
00403         return (fValueDesired - fValue1)/fDelta;
00404 }
00405 
00406 int MarchingCubes::get_edge_num(int x, int y, int z, int edge) {
00407         // edge direction is right, down, back (x, y, z)
00408         unsigned int index = 0;
00409         index = (x << 22) | (y << 12) | (z << 2) | edge;
00410         return index;
00411 }
00412 
00413 void MarchingCubes::marching_cube(int fX, int fY, int fZ, int cur_level)
00414 {
00415         extern int aiCubeEdgeFlags[256];
00416         extern int a2iTriangleConnectionTable[256][16];
00417 
00418         int iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
00419         float fOffset;
00420         Vector3 sColor;
00421         float afCubeValue[8];
00422         float asEdgeVertex[12][3];
00423         int pointIndex[12];
00424 
00425         int fxScale = 1, fyScale = 1, fzScale = 1;
00426         if ( cur_level != -1 )
00427         {
00428                 fxScale = _emdata->get_xsize()/minvals[cur_level]->get_xsize();
00429                 fyScale = _emdata->get_ysize()/minvals[cur_level]->get_ysize();
00430                 fzScale = _emdata->get_zsize()/minvals[cur_level]->get_zsize();
00431                 for(iVertex = 0; iVertex < 8; iVertex++)
00432                 {
00433                         afCubeValue[iVertex] = _emdata->get_value_at( fxScale*(fX + a2fVertexOffset[iVertex][0]),
00434                                                 fyScale*(fY + a2fVertexOffset[iVertex][1]), fzScale*(fZ + a2fVertexOffset[iVertex][2]));
00435                 }
00436         }
00437         else
00438         {
00439                 //Make a local copy of the values at the cube's corners
00440                 for(iVertex = 0; iVertex < 8; iVertex++)
00441                 {
00442                         afCubeValue[iVertex] = _emdata->get_value_at( fX + a2fVertexOffset[iVertex][0],
00443                                         fY + a2fVertexOffset[iVertex][1], fZ + a2fVertexOffset[iVertex][2]);
00444                 }
00445         }
00446 
00447         //Find which vertices are inside of the surface and which are outside
00448         iFlagIndex = 0;
00449         for(iVertexTest = 0; iVertexTest < 8; iVertexTest++)
00450         {
00451                 if (_surf_value >= 0 ){
00452                         if(afCubeValue[iVertexTest] <= _surf_value)
00453                                 iFlagIndex |= 1<<iVertexTest;
00454                 }
00455                 else {
00456                         if(afCubeValue[iVertexTest] >= _surf_value)
00457                                 iFlagIndex |= 1<<iVertexTest;
00458                 }
00459         }
00460 
00461         //Find which edges are intersected by the surface
00462         iEdgeFlags = aiCubeEdgeFlags[iFlagIndex];
00463 
00464         //If the cube is entirely inside or outside of the surface, then there will be no intersections
00465         if(iEdgeFlags == 0) return;
00466 
00467         //Find the point of intersection of the surface with each edge
00468         //Then find the normal to the surface at those points
00469         for(iEdge = 0; iEdge < 12; iEdge++)
00470         {
00471                 //if there is an intersection on this edge
00472                 if(iEdgeFlags & (1<<iEdge))
00473                 {
00474                         fOffset = get_offset(afCubeValue[ a2iEdgeConnection[iEdge][0] ],
00475                                                                  afCubeValue[ a2iEdgeConnection[iEdge][1] ], _surf_value);
00476 
00477                         if ( cur_level == -1 ){
00478                                 asEdgeVertex[iEdge][0] = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]  +  fOffset * a2fEdgeDirection[iEdge][0]) + 0.5f;
00479                                 asEdgeVertex[iEdge][1] = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]  +  fOffset * a2fEdgeDirection[iEdge][1]) + 0.5f;
00480                                 asEdgeVertex[iEdge][2] = fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2]  +  fOffset * a2fEdgeDirection[iEdge][2]) + 0.5f;
00481                         } else {
00482                                 asEdgeVertex[iEdge][0] = fxScale*(fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]  +  fOffset * a2fEdgeDirection[iEdge][0])) + 0.5f;
00483                                 asEdgeVertex[iEdge][1] = fyScale*(fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]  +  fOffset * a2fEdgeDirection[iEdge][1])) + 0.5f;
00484                                 asEdgeVertex[iEdge][2] = fzScale*(fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2]  +  fOffset * a2fEdgeDirection[iEdge][2])) + 0.5f;
00485                         }
00486 
00487                         pointIndex[iEdge] = get_edge_num(fX+edgeLookUp[iEdge][0], fY+edgeLookUp[iEdge][1], fZ+edgeLookUp[iEdge][2], edgeLookUp[iEdge][3]);
00488                 }
00489         }
00490 
00491         //Draw the triangles that were found.  There can be up to five per cube
00492         for(iTriangle = 0; iTriangle < 5; iTriangle++)
00493         {
00494                 if(a2iTriangleConnectionTable[iFlagIndex][3*iTriangle] < 0)
00495                         break;
00496 
00497                 float pts[3][3];
00498                 for(iCorner = 0; iCorner < 3; iCorner++)
00499                 {
00500                         iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner];
00501                         memcpy(&pts[iCorner][0],  &asEdgeVertex[iVertex][0], 3*sizeof(float));
00502                 }
00503 
00504                 
00505                 
00506                 float v1[3] = {pts[1][0]-pts[0][0],pts[1][1]-pts[0][1],pts[1][2]-pts[0][2]};
00507                 float v2[3] = {pts[2][0]-pts[1][0],pts[2][1]-pts[1][1],pts[2][2]-pts[1][2]};
00508                 
00509                 float n[3] = { v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0] };
00510                 
00511                 for(iCorner = 0; iCorner < 3; iCorner++)
00512                 {
00513                         // Without vertex normalization
00514 //                      iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner];
00515 //                      int ss = pp.elem();
00516 //                      pp.push_back_3(&pts[iCorner][0]);
00517 //                      nn.push_back_3(&n[0]);
00518 //                      ff.push_back(ss);
00519 
00520 //                      With vertex normalization
00521                         iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner];
00522                         map<int,int>::iterator it = point_map.find(pointIndex[iVertex]);
00523                         if ( it == point_map.end() ){
00524                                 int ss = pp.elem();
00525                                 pp.push_back_3(&pts[iCorner][0]);
00526                                 nn.push_back_3(&n[0]);
00527                                 ff.push_back(ss);
00528                                 point_map[pointIndex[iVertex]] = ss;
00529                         } else {
00530                                 int idx = it->second;
00531                                 ff.push_back(idx);
00532                                 nn[idx] += n[0];
00533                                 nn[idx+1] += n[1];
00534                                 nn[idx+2] += n[2];
00535                         }
00536                 }
00537         }
00538 }
00539 
00540 // For any edge, if one vertex is inside of the surface and the other is outside of the surface
00541 // then the edge intersects the surface
00542 // For each of the 8 vertices of the cube can be two possible states : either inside or outside of the surface
00543 // For any cube the are 2^8=256 possible sets of vertex states
00544 // This table lists the edges intersected by the surface for all 256 possible vertex states
00545 // There are 12 edges.  For each entry in the table, if edge #n is intersected, then bit #n is set to 1
00546 
00547 int aiCubeEdgeFlags[256]=
00548 {
00549         0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
00550         0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
00551         0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
00552         0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
00553         0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
00554         0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
00555         0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
00556         0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
00557         0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
00558         0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
00559         0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
00560         0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
00561         0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
00562         0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
00563         0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
00564         0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
00565 };
00566 
00567 //  For each of the possible vertex states listed in aiCubeEdgeFlags there is a specific triangulation
00568 //  of the edge intersection points.  a2iTriangleConnectionTable lists all of thminvals[cur_level]-> in the form of
00569 //  0-5 edge triples with the list terminated by the invalid value -1.
00570 //  For example: a2iTriangleConnectionTable[3] list the 2 triangles formed when corner[0]
00571 //  and corner[1] are inside of the surface, but the rest of the cube is not.
00572 //
00573 //  I found this table in an example program someone wrote long ago.  It was probably generated by hand
00574 
00575 int a2iTriangleConnectionTable[256][16] =
00576 {
00577         {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00578         {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00579         {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00580         {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00581         {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00582         {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00583         {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00584         {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
00585         {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00586         {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00587         {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00588         {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
00589         {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00590         {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
00591         {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
00592         {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00593         {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00594         {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00595         {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00596         {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
00597         {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00598         {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
00599         {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
00600         {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
00601         {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00602         {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
00603         {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
00604         {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
00605         {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
00606         {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
00607         {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
00608         {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
00609         {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00610         {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00611         {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00612         {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
00613         {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00614         {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
00615         {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
00616         {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
00617         {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00618         {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
00619         {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
00620         {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
00621         {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
00622         {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
00623         {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
00624         {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
00625         {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00626         {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
00627         {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
00628         {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00629         {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
00630         {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
00631         {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
00632         {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
00633         {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
00634         {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
00635         {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
00636         {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
00637         {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
00638         {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
00639         {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
00640         {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00641         {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00642         {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00643         {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00644         {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
00645         {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00646         {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
00647         {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
00648         {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
00649         {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00650         {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
00651         {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
00652         {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
00653         {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
00654         {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
00655         {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
00656         {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
00657         {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00658         {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
00659         {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
00660         {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
00661         {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
00662         {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
00663         {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
00664         {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
00665         {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
00666         {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
00667         {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
00668         {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
00669         {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
00670         {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
00671         {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
00672         {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
00673         {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00674         {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
00675         {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
00676         {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
00677         {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
00678         {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
00679         {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00680         {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
00681         {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
00682         {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
00683         {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
00684         {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
00685         {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
00686         {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
00687         {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
00688         {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00689         {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
00690         {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
00691         {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
00692         {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
00693         {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
00694         {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
00695         {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
00696         {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00697         {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
00698         {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
00699         {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
00700         {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
00701         {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
00702         {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00703         {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
00704         {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00705         {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00706         {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00707         {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00708         {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
00709         {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00710         {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
00711         {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
00712         {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
00713         {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00714         {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
00715         {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
00716         {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
00717         {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
00718         {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
00719         {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
00720         {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
00721         {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00722         {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
00723         {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
00724         {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
00725         {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
00726         {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
00727         {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
00728         {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
00729         {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
00730         {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00731         {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
00732         {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
00733         {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
00734         {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
00735         {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
00736         {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00737         {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00738         {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
00739         {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00740         {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
00741         {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00742         {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
00743         {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
00744         {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
00745         {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
00746         {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
00747         {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
00748         {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
00749         {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
00750         {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
00751         {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
00752         {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
00753         {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
00754         {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
00755         {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
00756         {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
00757         {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
00758         {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
00759         {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
00760         {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
00761         {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
00762         {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
00763         {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
00764         {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00765         {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
00766         {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
00767         {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00768         {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00769         {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00770         {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
00771         {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
00772         {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
00773         {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00774         {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
00775         {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
00776         {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
00777         {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
00778         {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
00779         {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
00780         {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
00781         {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00782         {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
00783         {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
00784         {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00785         {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
00786         {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
00787         {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
00788         {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
00789         {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
00790         {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
00791         {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
00792         {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00793         {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
00794         {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
00795         {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
00796         {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
00797         {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00798         {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00799         {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
00800         {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00801         {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
00802         {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
00803         {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
00804         {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
00805         {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
00806         {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
00807         {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
00808         {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
00809         {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
00810         {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
00811         {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
00812         {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00813         {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
00814         {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
00815         {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00816         {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00817         {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00818         {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
00819         {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
00820         {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00821         {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
00822         {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
00823         {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00824         {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00825         {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
00826         {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00827         {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
00828         {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00829         {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00830         {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00831         {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00832         {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
00833 };
00834 
00835 
00836 U3DWriter::U3DWriter() : DIFFUSE_COLOR_COUNT(1),
00837                 SPECULAR_COLOR_COUNT(1)
00838 {
00839 }
00840 U3DWriter::~U3DWriter() {}
00841 
00842 using std::ofstream;
00843 
00844 int U3DWriter::write(const string& filename) {
00845         // Must open the ofstream in binary mode
00846         ofstream of(filename.c_str(), ofstream::binary);
00847         write(of);
00848         of.close();
00849 
00850         return 1;
00851 }
00852 
00853 ostream& U3DWriter::write(ostream& os) {
00854         write_header(os);
00855         return os;
00856 }
00857 
00858 unsigned int U3DWriter::size_of_in_bytes(){
00859         // this is just the size in bytes of all of the entries in this object that are written to the binary
00860         // output. This is based only on the behavior of write_header and needs to be udpated
00861         unsigned size = 4+2+2+4+4+8+4+8; // 36 bytes
00862         return size;
00863 }
00864 ostream& U3DWriter::write_header(ostream& os)
00865 {
00866         // checks
00867         test_type_sizes();
00868 
00869         U32 block_type_file_header = 0x00443355; // This is the block type tag of a file header, as taken form the ECMA spec
00870         write( os, block_type_file_header);
00871 //
00872         I16 major_version = -1; // Compliance has not been tested for this encoder, so we must specify a value less than 0
00873         I16 minor_version =  0; // This is the version of this encoder, which we are calling '0'
00874         write( os, major_version);
00875         write( os, minor_version);
00876 
00877         U32 profile_identifier = 0x00000000; // Base profile - no optional features ares used
00878         write( os, profile_identifier);
00879 
00880         U32 declaration_size = size_of_in_bytes(); // This will have to be addressed at a later point, this is the size if the declaration block in bytes
00881         write( os, declaration_size);
00882 
00883         U64 file_size = size_of_in_bytes(); // This is the size of the file in bytes
00884         write( os, file_size);
00885 
00886         U32 character_encoding = 106; // UTF-8 MIB from the IANA
00887         write( os, character_encoding);
00888 
00889         F64 unit_scaling = 1.0; // This should eventually be the correct scaling of the objects
00890         write( os, unit_scaling);
00891 
00892 
00893         return os;
00894 }
00895 
00896 void U3DWriter::test_type_sizes()
00897 {
00898         bool error = false;
00899         if (sizeof(F64) != 8 ){
00900                 cout << "Error, size of double is not 64 bytes, it's " << sizeof(F64)*4 << endl;
00901                 error = true;
00902         }
00903         if (sizeof(F32) != 4 ){
00904                 cout << "Error, size of float is not 32 bytes, it's " << sizeof(F32)*4 << endl;
00905                 error = true;
00906         }
00907         if (sizeof(U64) != 8) {
00908                 cout << "Error, size of long unsigned int is not 64 bytes, it's " << sizeof(U64)*4 << endl;
00909                 error = true;
00910         }
00911         if (sizeof(U32) != 4) {
00912                 cout << "Error, size of unsigned int is not 32 bytes, it's " << sizeof(U32)*4 << endl;
00913                 error = true;
00914         }
00915         if (sizeof(I16) != 2) {
00916                 cout << "Error, size of short int is not 16 bytes, it's " << sizeof(I16)*4 << endl;
00917                 error = true;
00918         }
00919         if (sizeof(U16) != 2) {
00920                 cout << "Error, size of short unsigned int is not 16 bytes, it's " << sizeof(U16)*4 << endl;
00921                 error = true;
00922         }
00923         if (sizeof(U8) != 1) {
00924                 cout << "Error, size of unsigned char is not  bytes, it's " << sizeof(U8)*4 << endl;
00925                 error = true;
00926         }
00927 
00928         if (error) {
00929                 throw;
00930         }
00931 }
00932 
00933 ostream& U3DWriter::write_clod_mesh_generator_node(ostream& os)
00934 {
00935         /*
00936         CLOD Mesh Declaration
00937         */
00938         U32 block_type_clod_mesh_generator = 0xFFFFFF31; // This is the block type tag of the continuous level of detail mesh generator, as taken form the ECMA spec
00939         write( os, block_type_clod_mesh_generator);
00940 
00941         string name("testmesh"); // The unique name, we get to make this up ourselves. It could be an empty string, we'd still have to call write_string(os,"")
00942         write(os,name);
00943 
00944         U32 chain_index = 0x00000000; // the value of Chain Index shall be zero for this type - as in the SPEC
00945         write( os, chain_index);
00946 
00947         /*
00948         Max Mesh Description
00949         */
00950         U32 mesh_attributes = 0x00000000; // Faces in the mesh have a normal index at each corner 0x00000001 is used to exlude normals POTENTIALLY USEFUL
00951         write(os,mesh_attributes);
00952         U32 face_count = ff.elem(); // The number of faces TO FILL IN LATER
00953         write(os,face_count);
00954         U32 position_count = pp.elem(); // The number of positions in the position array TO FILL IN LATER
00955         write(os,position_count);
00956         U32 normal_count = nn.elem(); // The number of normals in the normal array TO FILL IN LATER
00957         write(os,normal_count);
00958         U32 diffuse_color_count = DIFFUSE_COLOR_COUNT; // The number of colors in the diffuse color array TO FILL IN LATER
00959         write(os,diffuse_color_count);
00960         U32 specular_color_count = SPECULAR_COLOR_COUNT; // The number of colors in the specular color array TO FILL IN LATER
00961         write(os,specular_color_count);
00962         U32 texture_coord_count = 0x00000000; // The number of texture coordinates in teh texture coordinate array POTENTIALLY USEFUL
00963         write(os,texture_coord_count);
00964         U32 shading_count = 1; // The number of shading descriptions used in the mesh. This must correspond with the shader list in the shading group (see directly below we are using only one shader
00965         write(os,shading_count);
00966 
00967         /*
00968         Shading  Description
00969         */
00970         U32 shading_attributes = 0x00000003; // 0 means use neither diffuse or specular colors, 1 means use per vertex diffuse, 2 means use per vertex specular, 3 means use both POTENTIALLY USEFUL
00971         write(os,shading_attributes);
00972         U32 texture_layout_count = 0x00000000; // The number of texture layers used by this shader list
00973         write(os,texture_layout_count);
00974         U32 texture_coord_dimensions = 0x00000002; // The number of dimensions in the texture coordinate vector. I chose default to be 2. No particular reason. POTENTIALLY USEFUL
00975         write(os,texture_coord_dimensions);
00976         U32 original_shading_id = 0; // Original shading index for this shader list. Informative parameter only. This is shader 0
00977         write(os,original_shading_id);
00978 
00979         /*
00980         CLOD Description - describes the range of resolutions available for the continuous level of detail mesh
00981         If there were more than one level of detail than these two numbers would be different
00982         */
00983         U32 minimum_resolution = position_count; // the number of positions in the base mesh
00984         write(os,minimum_resolution);
00985         U32 final_maximum_resolution = position_count; // the number of positions in the Max Mesh Description (by definition)
00986         write(os,final_maximum_resolution);
00987 
00988         /*
00989         Resource Description
00990         */
00991 
00992         /*
00993         Quality Factors
00994         for information only. Not used by the renderer. Helpful for conveying information to the user
00995         */
00996         U32 position_quality_factor = 0x00000000; // position quality factor. Descriptive information only
00997         write(os,position_quality_factor);
00998         U32 normal_quality_factor = 0x00000000; // normal quality factor. Descriptive information only
00999         write(os,normal_quality_factor);
01000         U32 texture_coord_quality_factor = 0x00000000; // texture coordinate quality factor. Descriptive information only
01001         write(os,texture_coord_quality_factor);
01002 
01003         /*
01004         Inverse Quantization
01005         used to reconstruct floating point values that have been quantized.
01006         */
01007         F32 postion_inverse_quant = 1.0; // inverse quantization factor used in the reconstruction of the position vectors
01008         write(os,postion_inverse_quant);
01009         F32 normal_inverse_quant = 1.0; // inverse quantization factor used in the reconstruction of the normal vectors
01010         write(os,normal_inverse_quant);
01011         F32 texture_coord_inverse_quant = 1.0; // inverse quantization factor used in the reconstruction of the texture coordinates
01012         write(os,texture_coord_inverse_quant);
01013         F32 diffuse_color_inverse_quant = 1.0; // inverse quantization factor used in the reconstruction of the diffuse colors
01014         write(os,diffuse_color_inverse_quant);
01015         F32 specular_color_inverse_quant = 1.0; // inverse quantization factor used in the reconstruction of the specular colors
01016         write(os,specular_color_inverse_quant);
01017 
01018         /*
01019         Resource Parameters
01020         parameters that help to define the conversion from the Author Mesh format to the Render Mesh format
01021         */
01022 
01023         F32 normal_crease_parameter = 1.0; // A dot product value in the range -1 to 1, used to decide whether or not normals at the same position will be merged. 1.0 means never, -1.0 means always. 0 means the two normals must be separated by an angle no greater than 90 degrees to be merged. Think in angles.
01024         write(os,normal_crease_parameter);
01025         F32 normal_update_parameter = 0.0; // A strange a parameter that I couldn't make sense of - I think it means it will change the actual file itself if it encounters what it deems 'normal errors'
01026         write(os,normal_update_parameter);
01027         F32 normal_tolerance_parameter = 0.0; // Normals which are closer together than this value are considered equivalent in the Render Mesh. This is useful for compression
01028         write(os,normal_tolerance_parameter);
01029 
01030         /*
01031         Skeleton description
01032         used in bones-based animation by the Animation Modifier
01033         */
01034         U32 bone_count = 0x00000000; // The number of bones associated with this mesh. We will always have 0, but this could change (unlikely).
01035         write(os,bone_count);
01036 
01037         // WARNING - if bone_count is ever greater than one, then more writing would have to occur here
01038 
01040         /*
01041         Base mesh is basically the minimum LOD mesh - it must exist
01042         */
01043         {
01044         U32 block_type_clod_base_mesh_continuation = 0xFFFFFF3B; // This is the block type tag of the CLOD Base Mesh Continuation, as taken form the ECMA spec
01045         write( os, block_type_clod_base_mesh_continuation);
01046 
01047         write(os,name); // We use the same name as above
01048 
01049         U32 chain_index = 0x00000000; // the value of Chain Index shall be zero for this type - as in the SPEC
01050         write( os, chain_index);
01051 
01052         /*
01053         Base Mesh Description
01054         */
01055         U32     base_face_count = ff.elem(); // The number of faces in the base mesh TO FILL IN LATER
01056         write( os, base_face_count);
01057         U32     base_position_count = pp.elem(); // The number of positions used by base mesh in the position array TO FILL IN LATER
01058         write( os, base_position_count);
01059         U32 base_normal_count = nn.elem(); // The number of normals used by the base mesh in the normal array TO FILL IN LATER
01060         write( os, base_normal_count);
01061         U32 base_diffuse_color_count = DIFFUSE_COLOR_COUNT; // The number of diffuse colors used by the base mesh in the diffuse color array TO FILL IN LATER
01062         write( os, base_diffuse_color_count);
01063         U32 base_specular_color_count = SPECULAR_COLOR_COUNT; // The number of specular colors used by the base mesh in the specular color array TO FILL IN LATER
01064         write( os, base_specular_color_count);
01065         U32 base_texture_coord_count = 0x00000000; // The number of texture coordinates used by the base mesh in texture coordinate array TO FILL IN LATER
01066         write( os, base_texture_coord_count);
01067 
01068         /*
01069         Base mesh data
01070         */
01071 
01072         // Write position data
01073         F32* data = pp.get_data();
01074         for(unsigned int i = 0; i < pp.elem(); ++i) {
01075                 write(os,data[i]);
01076         }
01077 
01078         // Write normal data
01079         data = nn.get_data();
01080         for(unsigned int i = 0; i < nn.elem(); ++i) {
01081                 write(os,data[i]);
01082         }
01083 
01084         // Write Diffuse color, this is in rgba format
01085         F32 diffuse_rgba[4] = {1.0,0.0,0.0,1.0};
01086         for (unsigned int i = 0; i < 4; ++i) {
01087                 write(os,diffuse_rgba[i]);
01088         }
01089 
01090         // Write Specular color, this is in rgba format
01091         F32 specular_rgba[4] = {1.0,0.0,0.0,1.0};
01092         for (unsigned int i = 0; i < 4; ++i) {
01093                 write(os,specular_rgba[i]);
01094         }
01095 
01096         // THERE ARE NO TEXTURE COORDINATES, BUT IF THERE WERE WE WOULD HAVE TO WRITE THEM HERE
01097         // i.e. for i in range(0,base_texture_coord_count) write texture coords
01098 
01099         // Write normal data
01100         U32* faces = ff.get_data();
01101         for(unsigned int i = 0; i < pp.elem(); i = i+3) {
01102                 U32 shading_id = 0; // We only have one shader defined. This could could changed in future
01103                 write(os,shading_id);
01104 
01105                 // write base corner info - there are always three corners
01106                 for (unsigned int j =0; j < 3; ++j){
01107                         U32 position_index = faces[i+j];
01108                         write(os,position_index); // Write the position index
01109 
01110                         U32 normal_index = position_index;
01111                         write(os,normal_index); // Write the normal index, it is exactly the same as the normal index!
01112 
01113                         U32 base_diffuse_color_index = 0; // only using one diffuse color
01114                         write(os,base_diffuse_color_index);
01115 
01116                         U32 base_specular_color_index = 0; // only using one specular color
01117                         write(os,base_specular_color_index);
01118 
01119                         // Would need to write texture data here if we were doing that
01120 
01121                 }
01122 
01123         }
01124 
01125         }
01126         return os;
01127 }
01128 
01129 template<>
01130 ostream& U3DWriter::write(ostream& os, const string& s )
01131 {
01132         // WARNING - I AM NOT SURE IF THIS APPROACH WILL PRESENT UTF8 PROBLEMS.
01133         // See character_encoding in the file header writing module above
01134         test_type_sizes();
01135 
01136         short unsigned int size = s.size(); // To write a string you must first place its
01137         write(os,size);
01138 
01139         // Write the characters
01140         for(unsigned int i = 0; i<size; ++i) {
01141                 write(os,s[i]);
01142         }
01143 
01144         return os;
01145 }
01146 /*
01147 #include <boost/python.hpp>
01148 using namespace boost::python;
01149 
01150 BOOST_PYTHON_MODULE(gorgon)
01151 {
01152     class_<MarchingCubes>("MarchingCubes", init<>())
01153         .def("drawMesh", &MarchingCubes::drawMesh)
01154                 .def("setSurfaceValue", &MarchingCubes::setSurfaceValue)
01155                 .def("getSurfaceValue", &MarchingCubes::getSurfaceValue)
01156                 .def("set_sample_density", &MarchingCubes::set_sample_density)
01157                 .def("getSampleDensity", &MarchingCubes::getSampleDensity)
01158                 .def("loadMRC", &MarchingCubes::loadMRC)
01159     ;
01160 }
01161 */

Generated on Tue May 25 17:34:11 2010 for EMAN2 by  doxygen 1.4.4