00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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
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
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
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
00181 while ( nx > 1 || ny > 1 || nz > 1 )
00182 {
00183 int size = minvals.size();
00184
00185 if ( size == 0 ){
00186 Dict a;
00187
00188
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
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
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
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
00462 iEdgeFlags = aiCubeEdgeFlags[iFlagIndex];
00463
00464
00465 if(iEdgeFlags == 0) return;
00466
00467
00468
00469 for(iEdge = 0; iEdge < 12; iEdge++)
00470 {
00471
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
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
00514
00515
00516
00517
00518
00519
00520
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
00541
00542
00543
00544
00545
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
00568
00569
00570
00571
00572
00573
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
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
00860
00861 unsigned size = 4+2+2+4+4+8+4+8;
00862 return size;
00863 }
00864 ostream& U3DWriter::write_header(ostream& os)
00865 {
00866
00867 test_type_sizes();
00868
00869 U32 block_type_file_header = 0x00443355;
00870 write( os, block_type_file_header);
00871
00872 I16 major_version = -1;
00873 I16 minor_version = 0;
00874 write( os, major_version);
00875 write( os, minor_version);
00876
00877 U32 profile_identifier = 0x00000000;
00878 write( os, profile_identifier);
00879
00880 U32 declaration_size = size_of_in_bytes();
00881 write( os, declaration_size);
00882
00883 U64 file_size = size_of_in_bytes();
00884 write( os, file_size);
00885
00886 U32 character_encoding = 106;
00887 write( os, character_encoding);
00888
00889 F64 unit_scaling = 1.0;
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
00937
00938 U32 block_type_clod_mesh_generator = 0xFFFFFF31;
00939 write( os, block_type_clod_mesh_generator);
00940
00941 string name("testmesh");
00942 write(os,name);
00943
00944 U32 chain_index = 0x00000000;
00945 write( os, chain_index);
00946
00947
00948
00949
00950 U32 mesh_attributes = 0x00000000;
00951 write(os,mesh_attributes);
00952 U32 face_count = ff.elem();
00953 write(os,face_count);
00954 U32 position_count = pp.elem();
00955 write(os,position_count);
00956 U32 normal_count = nn.elem();
00957 write(os,normal_count);
00958 U32 diffuse_color_count = DIFFUSE_COLOR_COUNT;
00959 write(os,diffuse_color_count);
00960 U32 specular_color_count = SPECULAR_COLOR_COUNT;
00961 write(os,specular_color_count);
00962 U32 texture_coord_count = 0x00000000;
00963 write(os,texture_coord_count);
00964 U32 shading_count = 1;
00965 write(os,shading_count);
00966
00967
00968
00969
00970 U32 shading_attributes = 0x00000003;
00971 write(os,shading_attributes);
00972 U32 texture_layout_count = 0x00000000;
00973 write(os,texture_layout_count);
00974 U32 texture_coord_dimensions = 0x00000002;
00975 write(os,texture_coord_dimensions);
00976 U32 original_shading_id = 0;
00977 write(os,original_shading_id);
00978
00979
00980
00981
00982
00983 U32 minimum_resolution = position_count;
00984 write(os,minimum_resolution);
00985 U32 final_maximum_resolution = position_count;
00986 write(os,final_maximum_resolution);
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 U32 position_quality_factor = 0x00000000;
00997 write(os,position_quality_factor);
00998 U32 normal_quality_factor = 0x00000000;
00999 write(os,normal_quality_factor);
01000 U32 texture_coord_quality_factor = 0x00000000;
01001 write(os,texture_coord_quality_factor);
01002
01003
01004
01005
01006
01007 F32 postion_inverse_quant = 1.0;
01008 write(os,postion_inverse_quant);
01009 F32 normal_inverse_quant = 1.0;
01010 write(os,normal_inverse_quant);
01011 F32 texture_coord_inverse_quant = 1.0;
01012 write(os,texture_coord_inverse_quant);
01013 F32 diffuse_color_inverse_quant = 1.0;
01014 write(os,diffuse_color_inverse_quant);
01015 F32 specular_color_inverse_quant = 1.0;
01016 write(os,specular_color_inverse_quant);
01017
01018
01019
01020
01021
01022
01023 F32 normal_crease_parameter = 1.0;
01024 write(os,normal_crease_parameter);
01025 F32 normal_update_parameter = 0.0;
01026 write(os,normal_update_parameter);
01027 F32 normal_tolerance_parameter = 0.0;
01028 write(os,normal_tolerance_parameter);
01029
01030
01031
01032
01033
01034 U32 bone_count = 0x00000000;
01035 write(os,bone_count);
01036
01037
01038
01040
01041
01042
01043 {
01044 U32 block_type_clod_base_mesh_continuation = 0xFFFFFF3B;
01045 write( os, block_type_clod_base_mesh_continuation);
01046
01047 write(os,name);
01048
01049 U32 chain_index = 0x00000000;
01050 write( os, chain_index);
01051
01052
01053
01054
01055 U32 base_face_count = ff.elem();
01056 write( os, base_face_count);
01057 U32 base_position_count = pp.elem();
01058 write( os, base_position_count);
01059 U32 base_normal_count = nn.elem();
01060 write( os, base_normal_count);
01061 U32 base_diffuse_color_count = DIFFUSE_COLOR_COUNT;
01062 write( os, base_diffuse_color_count);
01063 U32 base_specular_color_count = SPECULAR_COLOR_COUNT;
01064 write( os, base_specular_color_count);
01065 U32 base_texture_coord_count = 0x00000000;
01066 write( os, base_texture_coord_count);
01067
01068
01069
01070
01071
01072
01073 F32* data = pp.get_data();
01074 for(unsigned int i = 0; i < pp.elem(); ++i) {
01075 write(os,data[i]);
01076 }
01077
01078
01079 data = nn.get_data();
01080 for(unsigned int i = 0; i < nn.elem(); ++i) {
01081 write(os,data[i]);
01082 }
01083
01084
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
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
01097
01098
01099
01100 U32* faces = ff.get_data();
01101 for(unsigned int i = 0; i < pp.elem(); i = i+3) {
01102 U32 shading_id = 0;
01103 write(os,shading_id);
01104
01105
01106 for (unsigned int j =0; j < 3; ++j){
01107 U32 position_index = faces[i+j];
01108 write(os,position_index);
01109
01110 U32 normal_index = position_index;
01111 write(os,normal_index);
01112
01113 U32 base_diffuse_color_index = 0;
01114 write(os,base_diffuse_color_index);
01115
01116 U32 base_specular_color_index = 0;
01117 write(os,base_specular_color_index);
01118
01119
01120
01121 }
01122
01123 }
01124
01125 }
01126 return os;
01127 }
01128
01129 template<>
01130 ostream& U3DWriter::write(ostream& os, const string& s )
01131 {
01132
01133
01134 test_type_sizes();
01135
01136 short unsigned int size = s.size();
01137 write(os,size);
01138
01139
01140 for(unsigned int i = 0; i<size; ++i) {
01141 write(os,s[i]);
01142 }
01143
01144 return os;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161