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

Generated on Thu Nov 17 12:42:59 2011 for EMAN2 by  doxygen 1.4.7