📄 marchingcubes.cpp
字号:
/** * @file MarchingCubes.cpp * @author Thomas Lewiner <thomas.lewiner@polytechnique.org> * @author Math Dept, PUC-Rio * @version 0.2 * @date 12/08/2002 * * @brief MarchingCubes Algorithm *///________________________________________________//#ifndef WIN32//#pragma implementation//#endif // WIN32
#include "stdafx.h"#include <math.h>#include <time.h>#include <memory.h>#include <float.h>#include "MarchingCubes.h"#include "ply_tk.h"#include "LookUpTable.h"// step size of the arrays of vertices and triangles#define ALLOC_SIZE 65536//_____________________________________________________________________________// print cube for debugvoid MarchingCubes::print_cube() { printf( "\t%f %f %f %f %f %f %f %f\n", _cube[0], _cube[1], _cube[2], _cube[3], _cube[4], _cube[5], _cube[6], _cube[7]) ; }//_____________________________________________________________________________//_____________________________________________________________________________// ConstructorMarchingCubes::MarchingCubes( const int size_x /*= -1*/, const int size_y /*= -1*/, const int size_z /*= -1*/ ) ://----------------------------------------------------------------------------- _originalMC(false), _size_x (size_x), _size_y (size_y), _size_z (size_z), _data ((float*)NULL), _x_verts (( int *)NULL), _y_verts (( int *)NULL), _z_verts (( int *)NULL), _nverts (0), _ntrigs (0), _Nverts (0), _Ntrigs (0), _vertices (( Vertex_mc *)NULL), _triangles ((Triangle*)NULL){}//_____________________________________________________________________________//_____________________________________________________________________________// DestructorMarchingCubes::~MarchingCubes()//-----------------------------------------------------------------------------{ clean_all() ;}//_____________________________________________________________________________//_____________________________________________________________________________// main algorithmvoid MarchingCubes::run()//-----------------------------------------------------------------------------{ printf("Marching Cubes begin: cpu %ld\n", clock() ) ; compute_intersection_points( ) ; for( _k = 0 ; _k < _size_z-1 ; _k++ ) for( _j = 0 ; _j < _size_y-1 ; _j++ ) for( _i = 0 ; _i < _size_x-1 ; _i++ ) { _lut_entry = 0 ; for( int p = 0 ; p < 8 ; ++p ) { _cube[p] = get_data( _i+((p^(p>>1))&1), _j+((p>>1)&1), _k+((p>>2)&1) ) ; if( fabs( _cube[p] ) < FLT_EPSILON ) _cube[p] = FLT_EPSILON ; if( _cube[p] > 0 ) _lut_entry += 1 << p ; }/* if( ( _cube[0] = get_data( _i , _j , _k ) ) > 0 ) _lut_entry += 1 ; if( ( _cube[1] = get_data(_i+1, _j , _k ) ) > 0 ) _lut_entry += 2 ; if( ( _cube[2] = get_data(_i+1,_j+1, _k ) ) > 0 ) _lut_entry += 4 ; if( ( _cube[3] = get_data( _i ,_j+1, _k ) ) > 0 ) _lut_entry += 8 ; if( ( _cube[4] = get_data( _i , _j ,_k+1) ) > 0 ) _lut_entry += 16 ; if( ( _cube[5] = get_data(_i+1, _j ,_k+1) ) > 0 ) _lut_entry += 32 ; if( ( _cube[6] = get_data(_i+1,_j+1,_k+1) ) > 0 ) _lut_entry += 64 ; if( ( _cube[7] = get_data( _i ,_j+1,_k+1) ) > 0 ) _lut_entry += 128 ;*/ process_cube( ) ; } printf("Marching Cubes end: cpu %ld\n", clock() ) ; for( _i = 0 ; _i < 15 ; _i++ ) { printf(" %7d cases %d\n", _N[_i], _i ) ; }}//_____________________________________________________________________________//_____________________________________________________________________________// init temporary structures (must set sizes before call)void MarchingCubes::init_temps()//-----------------------------------------------------------------------------{ _data = new float[_size_x * _size_y * _size_z] ; _x_verts = new int [_size_x * _size_y * _size_z] ; _y_verts = new int [_size_x * _size_y * _size_z] ; _z_verts = new int [_size_x * _size_y * _size_z] ; memset( _x_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; memset( _y_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; memset( _z_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; memset( _N, 0, 15 * sizeof(int) ) ;}//_____________________________________________________________________________//_____________________________________________________________________________// init all structures (must set sizes before call)void MarchingCubes::init_all ()//-----------------------------------------------------------------------------{ init_temps() ; _nverts = _ntrigs = 0 ; _Nverts = _Ntrigs = ALLOC_SIZE ; _vertices = new Vertex_mc [_Nverts]; _triangles = new Triangle[_Ntrigs];}//_____________________________________________________________________________//_____________________________________________________________________________// clean temporary structuresvoid MarchingCubes::clean_temps()//-----------------------------------------------------------------------------{ delete [] _data; delete [] _x_verts; delete [] _y_verts; delete [] _z_verts; _data = (float*)NULL ; _x_verts = (int*)NULL ; _y_verts = (int*)NULL ; _z_verts = (int*)NULL ;}//_____________________________________________________________________________//_____________________________________________________________________________// clean all structuresvoid MarchingCubes::clean_all()//-----------------------------------------------------------------------------{ clean_temps() ; delete [] _vertices ; delete [] _triangles ; _vertices = (Vertex_mc *)NULL ; _triangles = (Triangle *)NULL ; _nverts = _ntrigs = 0 ; _Nverts = _Ntrigs = 0 ; _size_x = _size_y = _size_z = -1 ;}//_____________________________________________________________________________//_____________________________________________________________________________//_____________________________________________________________________________//_____________________________________________________________________________// Compute the intersection pointsvoid MarchingCubes::compute_intersection_points( )//-----------------------------------------------------------------------------{ for( _k = 0 ; _k < _size_z ; _k++ ) for( _j = 0 ; _j < _size_y ; _j++ ) for( _i = 0 ; _i < _size_x ; _i++ ) { _cube[0] = get_data( _i, _j, _k ) ; if( _i < _size_x - 1 ) _cube[1] = get_data(_i+1, _j , _k ) ; else _cube[1] = _cube[0] ; if( _j < _size_y - 1 ) _cube[3] = get_data( _i ,_j+1, _k ) ; else _cube[3] = _cube[0] ; if( _k < _size_z - 1 ) _cube[4] = get_data( _i , _j ,_k+1) ; else _cube[4] = _cube[0] ; if( fabs( _cube[0] ) < FLT_EPSILON ) _cube[0] = FLT_EPSILON ; if( fabs( _cube[1] ) < FLT_EPSILON ) _cube[1] = FLT_EPSILON ; if( fabs( _cube[3] ) < FLT_EPSILON ) _cube[3] = FLT_EPSILON ; if( fabs( _cube[4] ) < FLT_EPSILON ) _cube[4] = FLT_EPSILON ; if( _cube[0] < 0 ) { if( _cube[1] > 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ; if( _cube[3] > 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ; if( _cube[4] > 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ; } else { if( _cube[1] < 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ; if( _cube[3] < 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ; if( _cube[4] < 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ; } }}//_____________________________________________________________________________//_____________________________________________________________________________// Test a face// if face>0 return true if the face contains a part of the surfacebool MarchingCubes::test_face( schar face )//-----------------------------------------------------------------------------{ float A,B,C,D ; switch( face ) { case -1 : case 1 : A = _cube[0] ; B = _cube[4] ; C = _cube[5] ; D = _cube[1] ; break ; case -2 : case 2 : A = _cube[1] ; B = _cube[5] ; C = _cube[6] ; D = _cube[2] ; break ; case -3 : case 3 : A = _cube[2] ; B = _cube[6] ; C = _cube[7] ; D = _cube[3] ; break ; case -4 : case 4 : A = _cube[3] ; B = _cube[7] ; C = _cube[4] ; D = _cube[0] ; break ; case -5 : case 5 : A = _cube[0] ; B = _cube[3] ; C = _cube[2] ; D = _cube[1] ; break ; case -6 : case 6 : A = _cube[4] ; B = _cube[7] ; C = _cube[6] ; D = _cube[5] ; break ; default : printf( "Invalid face code %d\n", face ) ; print_cube() ; A = B = C = D = 0 ; }; return face * A * ( A*C - B*D ) >= 0 ; // face and A invert signs}//_____________________________________________________________________________//_____________________________________________________________________________// Test the interior of a cube// if s == 7, return true if the interior is empty// if s ==-7, return false if the interior is emptybool MarchingCubes::test_interior( schar s )//-----------------------------------------------------------------------------{ float t, At=0, Bt=0, Ct=0, Dt=0, a, b ; char test = 0 ; char edge = -1 ; // reference edge of the triangulation switch( _case ) { case 4 : case 10 : a = ( _cube[4] - _cube[0] ) * ( _cube[6] - _cube[2] ) - ( _cube[7] - _cube[3] ) * ( _cube[5] - _cube[1] ) ; b = _cube[2] * ( _cube[4] - _cube[0] ) + _cube[0] * ( _cube[6] - _cube[2] ) - _cube[1] * ( _cube[7] - _cube[3] ) - _cube[3] * ( _cube[5] - _cube[1] ) ; t = - b / (2*a) ; if( t<0 || t>1 ) return s>0 ; At = _cube[0] + ( _cube[4] - _cube[0] ) * t ; Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ; Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; break ; case 6 : case 7 : case 12 : case 13 : switch( _case ) { case 6 : edge = test6 [_config][2] ; break ; case 7 : edge = test7 [_config][4] ; break ; case 12 : edge = test12[_config][3] ; break ; case 13 : edge = tiling13_5_1[_config][_subconfig][0] ; break ; } switch( edge ) { case 0 : t = _cube[0] / ( _cube[0] - _cube[1] ) ; At = 0 ; Bt = _cube[3] + ( _cube[2] - _cube[3] ) * t ; Ct = _cube[7] + ( _cube[6] - _cube[7] ) * t ; Dt = _cube[4] + ( _cube[5] - _cube[4] ) * t ; break ; case 1 : t = _cube[1] / ( _cube[1] - _cube[2] ) ; At = 0 ; Bt = _cube[0] + ( _cube[3] - _cube[0] ) * t ; Ct = _cube[4] + ( _cube[7] - _cube[4] ) * t ; Dt = _cube[5] + ( _cube[6] - _cube[5] ) * t ; break ; case 2 : t = _cube[2] / ( _cube[2] - _cube[3] ) ; At = 0 ; Bt = _cube[1] + ( _cube[0] - _cube[1] ) * t ; Ct = _cube[5] + ( _cube[4] - _cube[5] ) * t ; Dt = _cube[6] + ( _cube[7] - _cube[6] ) * t ; break ; case 3 : t = _cube[3] / ( _cube[3] - _cube[0] ) ; At = 0 ; Bt = _cube[2] + ( _cube[1] - _cube[2] ) * t ; Ct = _cube[6] + ( _cube[5] - _cube[6] ) * t ; Dt = _cube[7] + ( _cube[4] - _cube[7] ) * t ; break ; case 4 : t = _cube[4] / ( _cube[4] - _cube[5] ) ; At = 0 ; Bt = _cube[7] + ( _cube[6] - _cube[7] ) * t ; Ct = _cube[3] + ( _cube[2] - _cube[3] ) * t ; Dt = _cube[0] + ( _cube[1] - _cube[0] ) * t ; break ; case 5 : t = _cube[5] / ( _cube[5] - _cube[6] ) ; At = 0 ; Bt = _cube[4] + ( _cube[7] - _cube[4] ) * t ; Ct = _cube[0] + ( _cube[3] - _cube[0] ) * t ; Dt = _cube[1] + ( _cube[2] - _cube[1] ) * t ; break ; case 6 : t = _cube[6] / ( _cube[6] - _cube[7] ) ; At = 0 ; Bt = _cube[5] + ( _cube[4] - _cube[5] ) * t ; Ct = _cube[1] + ( _cube[0] - _cube[1] ) * t ; Dt = _cube[2] + ( _cube[3] - _cube[2] ) * t ; break ; case 7 : t = _cube[7] / ( _cube[7] - _cube[4] ) ; At = 0 ; Bt = _cube[6] + ( _cube[5] - _cube[6] ) * t ; Ct = _cube[2] + ( _cube[1] - _cube[2] ) * t ; Dt = _cube[3] + ( _cube[0] - _cube[3] ) * t ; break ; case 8 : t = _cube[0] / ( _cube[0] - _cube[4] ) ; At = 0 ; Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ; Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; break ; case 9 : t = _cube[1] / ( _cube[1] - _cube[5] ) ; At = 0 ; Bt = _cube[0] + ( _cube[4] - _cube[0] ) * t ; Ct = _cube[3] + ( _cube[7] - _cube[3] ) * t ; Dt = _cube[2] + ( _cube[6] - _cube[2] ) * t ; break ; case 10 : t = _cube[2] / ( _cube[2] - _cube[6] ) ; At = 0 ; Bt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; Ct = _cube[0] + ( _cube[4] - _cube[0] ) * t ; Dt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; break ; case 11 : t = _cube[3] / ( _cube[3] - _cube[7] ) ; At = 0 ; Bt = _cube[2] + ( _cube[6] - _cube[2] ) * t ; Ct = _cube[1] + ( _cube[5] - _cube[1] ) * t ; Dt = _cube[0] + ( _cube[4] - _cube[0] ) * t ; break ; default : printf( "Invalid edge %d\n", edge ) ; print_cube() ; break ; } break ; default : printf( "Invalid ambiguous case %d\n", _case ) ; print_cube() ; break ; } if( At >= 0 ) test ++ ; if( Bt >= 0 ) test += 2 ; if( Ct >= 0 ) test += 4 ; if( Dt >= 0 ) test += 8 ; switch( test ) { case 0 : return s>0 ; case 1 : return s>0 ; case 2 : return s>0 ; case 3 : return s>0 ; case 4 : return s>0 ; case 5 : if( At * Ct < Bt * Dt ) return s>0 ; break ; case 6 : return s>0 ; case 7 : return s<0 ; case 8 : return s>0 ; case 9 : return s>0 ; case 10 : if( At * Ct >= Bt * Dt ) return s>0 ; break ; case 11 : return s<0 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -