You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1974 lines
51 KiB
1974 lines
51 KiB
/**
|
|
* @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
|
|
*///________________________________________________
|
|
#if !defined(WIN32) || defined(__CYGWIN__)
|
|
#pragma implementation
|
|
#endif // WIN32
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <memory.h>
|
|
#include <stdlib.h>
|
|
#include <float.h>
|
|
#include "MarchingCubes.h"
|
|
#include "ply.h"
|
|
#include "LookUpTable.h"
|
|
|
|
|
|
// step size of the arrays of vertices and triangles
|
|
#define ALLOC_SIZE 65536
|
|
|
|
//_____________________________________________________________________________
|
|
// print cube for debug
|
|
void 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]);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Constructor
|
|
MarchingCubes::MarchingCubes(const int size_x /*= -1*/,
|
|
const int size_y /*= -1*/, const int size_z /*= -1*/) :
|
|
//-----------------------------------------------------------------------------
|
|
_originalMC(false), _ext_data(false), _size_x(size_x), _size_y(size_y), _size_z(
|
|
size_z), _data((real *) NULL), _x_verts((int *) NULL), _y_verts(
|
|
(int *) NULL), _z_verts((int *) NULL), _nverts(0), _ntrigs(0), _Nverts(
|
|
0), _Ntrigs(0), _vertices((Vertex *) NULL), _triangles(
|
|
(Triangle*) NULL) {
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Destructor
|
|
MarchingCubes::~MarchingCubes()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
clean_all();
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// main algorithm
|
|
void MarchingCubes::run(real iso)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
clock_t time = clock();
|
|
|
|
compute_intersection_points(iso);
|
|
|
|
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)) - iso;
|
|
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("New Marching Cubes 33:ran in %lf secs.\n",
|
|
(double) (clock() - time) / CLOCKS_PER_SEC);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// init temporary structures (must set sizes before call)
|
|
void MarchingCubes::init_temps()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if (!_ext_data)
|
|
_data = new real[_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));
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// init all structures (must set sizes before call)
|
|
void MarchingCubes::init_all()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
init_temps();
|
|
|
|
_nverts = _ntrigs = 0;
|
|
_Nverts = _Ntrigs = ALLOC_SIZE;
|
|
_vertices = new Vertex[_Nverts];
|
|
_triangles = new Triangle[_Ntrigs];
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// clean temporary structures
|
|
void MarchingCubes::clean_temps()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if (!_ext_data)
|
|
delete[] _data;
|
|
delete[] _x_verts;
|
|
delete[] _y_verts;
|
|
delete[] _z_verts;
|
|
|
|
if (!_ext_data)
|
|
_data = (real*) NULL;
|
|
_x_verts = (int*) NULL;
|
|
_y_verts = (int*) NULL;
|
|
_z_verts = (int*) NULL;
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// clean all structures
|
|
void MarchingCubes::clean_all()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
clean_temps();
|
|
delete[] _vertices;
|
|
delete[] _triangles;
|
|
_vertices = (Vertex *) NULL;
|
|
_triangles = (Triangle *) NULL;
|
|
_nverts = _ntrigs = 0;
|
|
_Nverts = _Ntrigs = 0;
|
|
|
|
_size_x = _size_y = _size_z = -1;
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Compute the intersection points
|
|
void MarchingCubes::compute_intersection_points(real iso)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
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) - iso;
|
|
if (_i < _size_x - 1)
|
|
_cube[1] = get_data(_i + 1, _j, _k) - iso;
|
|
else
|
|
_cube[1] = _cube[0];
|
|
|
|
if (_j < _size_y - 1)
|
|
_cube[3] = get_data(_i, _j + 1, _k) - iso;
|
|
else
|
|
_cube[3] = _cube[0];
|
|
|
|
if (_k < _size_z - 1)
|
|
_cube[4] = get_data(_i, _j, _k + 1) - iso;
|
|
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 surface
|
|
bool MarchingCubes::test_face(schar face)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
real 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;
|
|
break;
|
|
};
|
|
|
|
if (fabs(A * C - B * D) < FLT_EPSILON)
|
|
return face >= 0;
|
|
|
|
return face * A * (A * C - B * D) >= 0; // face and A invert signs
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
|
|
bool MarchingCubes::modified_test_interior(schar s)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
|
|
char edge = -1;
|
|
int amb_face;
|
|
|
|
int inter_amb = 0;
|
|
|
|
switch (_case) {
|
|
case 4:
|
|
|
|
amb_face = 1;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
amb_face = 2;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
amb_face = 5;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
if (inter_amb == 0) return false;
|
|
else return true;
|
|
break;
|
|
|
|
case 6:
|
|
|
|
amb_face = abs(test6[_config][0]);
|
|
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb = interior_ambiguity_verification(edge);
|
|
|
|
if (inter_amb == 0) return false;
|
|
else return true;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
s = s * -1;
|
|
|
|
amb_face = 1;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
amb_face = 2;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
amb_face = 5;
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
if (inter_amb == 0) return false;
|
|
else return true;
|
|
break;
|
|
|
|
case 10:
|
|
|
|
amb_face = abs(test10[_config][0]);
|
|
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb = interior_ambiguity_verification(edge);
|
|
|
|
if (inter_amb == 0) return false;
|
|
else return true;
|
|
break;
|
|
|
|
case 12:
|
|
amb_face = abs(test12[_config][0]);
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
|
|
amb_face = abs(test12[_config][1]);
|
|
edge = interior_ambiguity(amb_face, s);
|
|
inter_amb += interior_ambiguity_verification(edge);
|
|
|
|
if (inter_amb == 0) return false;
|
|
else return true;
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//________________________________________________________________________________________________________
|
|
int MarchingCubes::interior_ambiguity(int amb_face, int s) {
|
|
int edge;
|
|
|
|
switch (amb_face) {
|
|
case 1:
|
|
case 3:
|
|
if (((_cube[1] * s) > 0) && ((_cube[7] * s) > 0))
|
|
edge = 4;
|
|
if (((_cube[0] * s) > 0) && ((_cube[6] * s) > 0))
|
|
edge = 5;
|
|
if (((_cube[3] * s) > 0) && ((_cube[5] * s) > 0))
|
|
edge = 6;
|
|
if (((_cube[2] * s) > 0) && ((_cube[4] * s) > 0))
|
|
edge = 7;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
case 4:
|
|
if (((_cube[1] * s) > 0) && ((_cube[7] * s) > 0))
|
|
edge = 0;
|
|
if (((_cube[2] * s) > 0) && ((_cube[4] * s) > 0))
|
|
edge = 1;
|
|
if (((_cube[3] * s) > 0) && ((_cube[5] * s) > 0))
|
|
edge = 2;
|
|
if (((_cube[0] * s) > 0) && ((_cube[6] * s) > 0))
|
|
edge = 3;
|
|
break;
|
|
|
|
case 5:
|
|
case 6:
|
|
case 0:
|
|
if (((_cube[0] * s) > 0) && ((_cube[6] * s) > 0))
|
|
edge = 8;
|
|
if (((_cube[1] * s) > 0) && ((_cube[7] * s) > 0))
|
|
edge = 9;
|
|
if (((_cube[2] * s) > 0) && ((_cube[4] * s) > 0))
|
|
edge = 10;
|
|
if (((_cube[3] * s) > 0) && ((_cube[5] * s) > 0))
|
|
edge = 11;
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return edge;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
int MarchingCubes::interior_ambiguity_verification(int edge) {
|
|
real t, At = 0, Bt = 0, Ct = 0, Dt = 0, a = 0, b = 0;
|
|
real verify;
|
|
|
|
switch (edge) {
|
|
|
|
case 0:
|
|
a = (_cube[0] - _cube[1]) * (_cube[7] - _cube[6])
|
|
- (_cube[4] - _cube[5]) * (_cube[3] - _cube[2]);
|
|
b = _cube[6] * (_cube[0] - _cube[1]) + _cube[1] * (_cube[7] - _cube[6])
|
|
- _cube[2] * (_cube[4] - _cube[5])
|
|
- _cube[5] * (_cube[3] - _cube[2]);
|
|
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[1] + (_cube[0] - _cube[1]) * t;
|
|
Bt = _cube[5] + (_cube[4] - _cube[5]) * t;
|
|
Ct = _cube[6] + (_cube[7] - _cube[6]) * t;
|
|
Dt = _cube[2] + (_cube[3] - _cube[2]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
a = (_cube[3] - _cube[2]) * (_cube[4] - _cube[5])
|
|
- (_cube[0] - _cube[1]) * (_cube[7] - _cube[6]);
|
|
b = _cube[5] * (_cube[3] - _cube[2]) + _cube[2] * (_cube[4] - _cube[5])
|
|
- _cube[6] * (_cube[0] - _cube[1])
|
|
- _cube[1] * (_cube[7] - _cube[6]);
|
|
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[2] + (_cube[3] - _cube[2]) * t;
|
|
Bt = _cube[1] + (_cube[0] - _cube[1]) * t;
|
|
Ct = _cube[5] + (_cube[4] - _cube[5]) * t;
|
|
Dt = _cube[6] + (_cube[7] - _cube[6]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 2:
|
|
a = (_cube[2] - _cube[3]) * (_cube[5] - _cube[4])
|
|
- (_cube[6] - _cube[7]) * (_cube[1] - _cube[0]);
|
|
b = _cube[4] * (_cube[2] - _cube[3]) + _cube[3] * (_cube[5] - _cube[4])
|
|
- _cube[0] * (_cube[6] - _cube[7])
|
|
- _cube[7] * (_cube[1] - _cube[0]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[3] + (_cube[2] - _cube[3]) * t;
|
|
Bt = _cube[7] + (_cube[6] - _cube[7]) * t;
|
|
Ct = _cube[4] + (_cube[5] - _cube[4]) * t;
|
|
Dt = _cube[0] + (_cube[1] - _cube[0]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 3:
|
|
a = (_cube[1] - _cube[0]) * (_cube[6] - _cube[7])
|
|
- (_cube[2] - _cube[3]) * (_cube[5] - _cube[4]);
|
|
b = _cube[7] * (_cube[1] - _cube[0]) + _cube[0] * (_cube[6] - _cube[7])
|
|
- _cube[4] * (_cube[2] - _cube[3])
|
|
- _cube[3] * (_cube[5] - _cube[4]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[0] + (_cube[1] - _cube[0]) * t;
|
|
Bt = _cube[3] + (_cube[2] - _cube[3]) * t;
|
|
Ct = _cube[7] + (_cube[6] - _cube[7]) * t;
|
|
Dt = _cube[4] + (_cube[5] - _cube[4]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 4:
|
|
|
|
a = (_cube[2] - _cube[1]) * (_cube[7] - _cube[4])
|
|
- (_cube[3] - _cube[0]) * (_cube[6] - _cube[5]);
|
|
b = _cube[4] * (_cube[2] - _cube[1]) + _cube[1] * (_cube[7] - _cube[4])
|
|
- _cube[5] * (_cube[3] - _cube[0])
|
|
- _cube[0] * (_cube[6] - _cube[5]);
|
|
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[1] + (_cube[2] - _cube[1]) * t;
|
|
Bt = _cube[0] + (_cube[3] - _cube[0]) * t;
|
|
Ct = _cube[4] + (_cube[7] - _cube[4]) * t;
|
|
Dt = _cube[5] + (_cube[6] - _cube[5]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 5:
|
|
|
|
a = (_cube[3] - _cube[0]) * (_cube[6] - _cube[5])
|
|
- (_cube[2] - _cube[1]) * (_cube[7] - _cube[4]);
|
|
b = _cube[5] * (_cube[3] - _cube[0]) + _cube[0] * (_cube[6] - _cube[5])
|
|
- _cube[4] * (_cube[2] - _cube[1])
|
|
- _cube[1] * (_cube[7] - _cube[4]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[0] + (_cube[3] - _cube[0]) * t;
|
|
Bt = _cube[1] + (_cube[2] - _cube[1]) * t;
|
|
Ct = _cube[5] + (_cube[6] - _cube[5]) * t;
|
|
Dt = _cube[4] + (_cube[7] - _cube[4]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 6:
|
|
a = (_cube[0] - _cube[3]) * (_cube[5] - _cube[6])
|
|
- (_cube[4] - _cube[7]) * (_cube[1] - _cube[2]);
|
|
b = _cube[6] * (_cube[0] - _cube[3]) + _cube[3] * (_cube[5] - _cube[6])
|
|
- _cube[2] * (_cube[4] - _cube[7])
|
|
- _cube[7] * (_cube[1] - _cube[2]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[3] + (_cube[0] - _cube[3]) * t;
|
|
Bt = _cube[7] + (_cube[4] - _cube[7]) * t;
|
|
Ct = _cube[6] + (_cube[5] - _cube[6]) * t;
|
|
Dt = _cube[2] + (_cube[1] - _cube[2]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 7:
|
|
a = (_cube[1] - _cube[2]) * (_cube[4] - _cube[7])
|
|
- (_cube[0] - _cube[3]) * (_cube[5] - _cube[6]);
|
|
b = _cube[7] * (_cube[1] - _cube[2]) + _cube[2] * (_cube[4] - _cube[7])
|
|
- _cube[6] * (_cube[0] - _cube[3])
|
|
- _cube[3] * (_cube[5] - _cube[6]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[2] + (_cube[1] - _cube[2]) * t;
|
|
Bt = _cube[3] + (_cube[0] - _cube[3]) * t;
|
|
Ct = _cube[7] + (_cube[4] - _cube[7]) * t;
|
|
Dt = _cube[6] + (_cube[5] - _cube[6]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 8:
|
|
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]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
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;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 9:
|
|
a = (_cube[5] - _cube[1]) * (_cube[7] - _cube[3])
|
|
- (_cube[4] - _cube[0]) * (_cube[6] - _cube[2]);
|
|
b = _cube[3] * (_cube[5] - _cube[1]) + _cube[1] * (_cube[7] - _cube[3])
|
|
- _cube[2] * (_cube[4] - _cube[0])
|
|
- _cube[0] * (_cube[6] - _cube[2]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[1] + (_cube[5] - _cube[1]) * t;
|
|
Bt = _cube[0] + (_cube[4] - _cube[0]) * t;
|
|
Ct = _cube[3] + (_cube[7] - _cube[3]) * t;
|
|
Dt = _cube[2] + (_cube[6] - _cube[2]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 10:
|
|
a = (_cube[6] - _cube[2]) * (_cube[4] - _cube[0])
|
|
- (_cube[5] - _cube[1]) * (_cube[7] - _cube[3]);
|
|
b = _cube[0] * (_cube[6] - _cube[2]) + _cube[2] * (_cube[4] - _cube[0])
|
|
- _cube[3] * (_cube[5] - _cube[1])
|
|
- _cube[1] * (_cube[7] - _cube[3]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[2] + (_cube[6] - _cube[2]) * t;
|
|
Bt = _cube[1] + (_cube[5] - _cube[1]) * t;
|
|
Ct = _cube[0] + (_cube[4] - _cube[0]) * t;
|
|
Dt = _cube[3] + (_cube[7] - _cube[3]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
|
|
case 11:
|
|
a = (_cube[7] - _cube[3]) * (_cube[5] - _cube[1])
|
|
- (_cube[6] - _cube[2]) * (_cube[4] - _cube[0]);
|
|
b = _cube[1] * (_cube[7] - _cube[3]) + _cube[3] * (_cube[5] - _cube[1])
|
|
- _cube[0] * (_cube[6] - _cube[2])
|
|
- _cube[2] * (_cube[4] - _cube[0]);
|
|
if (a > 0)
|
|
return 1;
|
|
|
|
t = -b / (2 * a);
|
|
if (t < 0 || t > 1)
|
|
return 1;
|
|
|
|
At = _cube[3] + (_cube[7] - _cube[3]) * t;
|
|
Bt = _cube[2] + (_cube[6] - _cube[2]) * t;
|
|
Ct = _cube[1] + (_cube[5] - _cube[1]) * t;
|
|
Dt = _cube[0] + (_cube[4] - _cube[0]) * t;
|
|
|
|
verify = At * Ct - Bt * Dt;
|
|
|
|
if (verify > 0)
|
|
return 0;
|
|
if (verify < 0)
|
|
return 1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//_____________________________________________________________________________
|
|
// NEWS INTERIOR TEST FOR CASE 13
|
|
// Return true if the interior is empty(two faces)
|
|
|
|
bool MarchingCubes::interior_test_case13()
|
|
{
|
|
real t1, t2, At1 = 0, Bt1 = 0, Ct1 = 0, Dt1 = 0, At2 = 0, Bt2 = 0, Ct2 = 0, Dt2 = 0, a = 0, b = 0, c = 0;
|
|
|
|
a = (_cube[0] - _cube[1]) * (_cube[7] - _cube[6])
|
|
- (_cube[4] - _cube[5]) * (_cube[3] - _cube[2]);
|
|
b = _cube[6] * (_cube[0] - _cube[1]) + _cube[1] * (_cube[7] - _cube[6])
|
|
- _cube[2] * (_cube[4] - _cube[5])
|
|
- _cube[5] * (_cube[3] - _cube[2]);
|
|
|
|
c = _cube[1]*_cube[6] - _cube[5]*_cube[2];
|
|
|
|
double delta = b*b - 4*a*c;
|
|
|
|
t1 = (-b + sqrt(delta))/(2*a);
|
|
t2 = (-b - sqrt(delta))/(2*a);
|
|
|
|
printf("t1 = %f, t2 = %f\n", t1, t2);
|
|
|
|
if ((t1 < 1)&&(t1>0) &&(t2 < 1)&&(t2 > 0))
|
|
{
|
|
|
|
At1 = _cube[1] + (_cube[0] - _cube[1]) * t1;
|
|
Bt1 = _cube[5] + (_cube[4] - _cube[5]) * t1;
|
|
Ct1 = _cube[6] + (_cube[7] - _cube[6]) * t1;
|
|
Dt1 = _cube[2] + (_cube[3] - _cube[2]) * t1;
|
|
|
|
float x1 = (At1 - Dt1)/(At1 + Ct1 - Bt1 - Dt1);
|
|
float y1 = (At1 - Bt1)/(At1 + Ct1 - Bt1 - Dt1);
|
|
|
|
At2 = _cube[1] + (_cube[0] - _cube[1]) * t2;
|
|
Bt2 = _cube[5] + (_cube[4] - _cube[5]) * t2;
|
|
Ct2 = _cube[6] + (_cube[7] - _cube[6]) * t2;
|
|
Dt2 = _cube[2] + (_cube[3] - _cube[2]) * t2;
|
|
|
|
float x2 = (At2 - Dt2)/(At2 + Ct2 - Bt2 - Dt2);
|
|
float y2 = (At2 - Bt2)/(At2 + Ct2 - Bt2 - Dt2);
|
|
|
|
if ((x1 < 1)&&(x1>0) &&(x2 < 1)&&(x2 > 0)&&(y1 < 1)&&(y1>0) &&(y2 < 1)&&(y2 > 0))
|
|
return false;
|
|
}
|
|
|
|
else return true;
|
|
|
|
}
|
|
//--------------------------------------------------------------------------------------------------------------------
|
|
// control the tunnel orientation triangulation
|
|
int tunnelOrientation = 0;
|
|
|
|
bool MarchingCubes::interior_test_case13_2(float isovalue) {
|
|
|
|
double critival_point_value1, critival_point_value2;
|
|
|
|
double a = - _cube[0] + _cube[1] + _cube[3] - _cube[2] + _cube[4] - _cube[5] - _cube[7] + _cube[6],
|
|
b = _cube[0] - _cube[1] - _cube[3] + _cube[2],
|
|
c = _cube[0] - _cube[1] - _cube[4] + _cube[5],
|
|
d = _cube[0] - _cube[3] - _cube[4] + _cube[7],
|
|
e = -_cube[0] + _cube[1],
|
|
f = -_cube[0] + _cube[3],
|
|
g = -_cube[0] + _cube[4],
|
|
h = _cube[0];
|
|
|
|
double x1, y1, z1, x2, y2, z2;
|
|
int numbercritivalpoints = 0;
|
|
|
|
double dx = b * c - a * e, dy = b * d - a * f, dz = c * d - a * g;
|
|
|
|
if (dx != 0.0f && dy != 0.0f && dz != 0.0f) {
|
|
if (dx * dy * dz < 0)
|
|
return true;
|
|
|
|
double disc = sqrt(dx * dy * dz);
|
|
|
|
x1 = (-d * dx - disc) / (a * dx);
|
|
y1 = (-c * dy - disc) / (a * dy);
|
|
z1 = (-b * dz - disc) / (a * dz);
|
|
|
|
if ((x1 > 0) && (x1 < 1) && (y1 > 0) && (y1 < 1)
|
|
&& (z1 > 0) && (z1 < 1)) {
|
|
numbercritivalpoints++;
|
|
|
|
critival_point_value1 = a * x1 * y1 * z1 + b * x1 * y1 + c * x1 * z1
|
|
+ d * y1 * z1 + e * x1 + f * y1 + g * z1 + h - isovalue;
|
|
}
|
|
|
|
x2 = (-d * dx + disc) / (a * dx);
|
|
y2 = (-c * dy + disc) / (a * dy);
|
|
z2 = (-b * dz + disc) / (a * dz);
|
|
|
|
if ((x2 > 0) && (x2 < 1) && (y2 > 0) && (y2 < 1)
|
|
&& (z2 > 0) && (z2 < 1)) {
|
|
numbercritivalpoints++;
|
|
|
|
critival_point_value2 = a * x2 * y2 * z2 + b * x2 * y2 + c * x2 * z2
|
|
+ d * y2 * z2 + e * x2 + f * y2 + g * z2 + h - isovalue;
|
|
|
|
}
|
|
|
|
if (numbercritivalpoints < 2)
|
|
return true;
|
|
else
|
|
{
|
|
if ((critival_point_value1 * critival_point_value2 > 0))
|
|
{
|
|
if (critival_point_value1 > 0)
|
|
tunnelOrientation = 1;
|
|
else
|
|
tunnelOrientation = -1;
|
|
}
|
|
|
|
return critival_point_value1 * critival_point_value2 < 0;
|
|
}
|
|
|
|
} else
|
|
return true;
|
|
}
|
|
//_____________________________________________________________________________
|
|
// Process a unit cube
|
|
void MarchingCubes::process_cube()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
|
|
if (_originalMC) {
|
|
char nt = 0;
|
|
while (casesClassic[_lut_entry][3 * nt] != -1)
|
|
nt++;
|
|
add_triangle(casesClassic[_lut_entry], nt);
|
|
return;
|
|
}
|
|
|
|
int v12 = -1;
|
|
_case = cases[_lut_entry][0];
|
|
_config = cases[_lut_entry][1];
|
|
_subconfig = 0;
|
|
|
|
switch (_case) {
|
|
|
|
case 0:
|
|
break;
|
|
|
|
case 1:
|
|
add_triangle(tiling1[_config], 1);
|
|
break;
|
|
|
|
case 2:
|
|
add_triangle(tiling2[_config], 2);
|
|
break;
|
|
|
|
case 3:
|
|
if (test_face(test3[_config]))
|
|
add_triangle(tiling3_2[_config], 4); // 3.2
|
|
else
|
|
add_triangle(tiling3_1[_config], 2); // 3.1
|
|
break;
|
|
|
|
case 4:
|
|
if (modified_test_interior(test4[_config]))
|
|
add_triangle(tiling4_1[_config], 2); // 4.1.1
|
|
else
|
|
add_triangle(tiling4_2[_config], 6); // 4.1.2
|
|
break;
|
|
|
|
case 5:
|
|
add_triangle(tiling5[_config], 3);
|
|
break;
|
|
|
|
case 6:
|
|
if (test_face(test6[_config][0]))
|
|
add_triangle(tiling6_2[_config], 5); // 6.2
|
|
else {
|
|
if (modified_test_interior(test6[_config][1]))
|
|
add_triangle(tiling6_1_1[_config], 3); // 6.1.1
|
|
else {
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling6_1_2[_config], 9, v12); // 6.1.2
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
if (test_face(test7[_config][0]))
|
|
_subconfig += 1;
|
|
if (test_face(test7[_config][1]))
|
|
_subconfig += 2;
|
|
if (test_face(test7[_config][2]))
|
|
_subconfig += 4;
|
|
switch (_subconfig) {
|
|
case 0:
|
|
add_triangle(tiling7_1[_config], 3);
|
|
break;
|
|
case 1:
|
|
add_triangle(tiling7_2[_config][0], 5);
|
|
break;
|
|
case 2:
|
|
add_triangle(tiling7_2[_config][1], 5);
|
|
break;
|
|
case 3:
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling7_3[_config][0], 9, v12);
|
|
break;
|
|
case 4:
|
|
add_triangle(tiling7_2[_config][2], 5);
|
|
break;
|
|
case 5:
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling7_3[_config][1], 9, v12);
|
|
break;
|
|
case 6:
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling7_3[_config][2], 9, v12);
|
|
break;
|
|
case 7:
|
|
if (modified_test_interior(test7[_config][3]))
|
|
add_triangle(tiling7_4_1[_config], 5);
|
|
else
|
|
add_triangle(tiling7_4_2[_config], 9);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
add_triangle(tiling8[_config], 2);
|
|
break;
|
|
|
|
case 9:
|
|
add_triangle(tiling9[_config], 4);
|
|
break;
|
|
|
|
case 10:
|
|
if (test_face(test10[_config][0])) {
|
|
if (test_face(test10[_config][1])) {
|
|
if (modified_test_interior(-test10[_config][2]))
|
|
add_triangle(tiling10_1_1_[_config], 4); // 10.1.1
|
|
else
|
|
add_triangle(tiling10_1_2[5 - _config], 8); // 10.1.2
|
|
|
|
} else {
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling10_2[_config], 8, v12); // 10.2
|
|
}
|
|
} else {
|
|
if (test_face(test10[_config][1])) {
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling10_2_[_config], 8, v12); // 10.2
|
|
} else {
|
|
if (modified_test_interior(test10[_config][2]))
|
|
add_triangle(tiling10_1_1[_config], 4); // 10.1.1
|
|
else
|
|
add_triangle(tiling10_1_2[_config], 8); // 10.1.2
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 11:
|
|
add_triangle(tiling11[_config], 4);
|
|
break;
|
|
|
|
case 12:
|
|
if (test_face(test12[_config][0])) {
|
|
if (test_face(test12[_config][1])) {
|
|
if (modified_test_interior(-test12[_config][2]))
|
|
add_triangle(tiling12_1_1_[_config], 4); // 12.1.1
|
|
else
|
|
add_triangle(tiling12_1_2[23 - _config], 8); // 12.1.2
|
|
} else {
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling12_2[_config], 8, v12); // 12.2
|
|
}
|
|
} else {
|
|
if (test_face(test12[_config][1])) {
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling12_2_[_config], 8, v12); // 12.2
|
|
} else {
|
|
if (modified_test_interior(test12[_config][2]))
|
|
add_triangle(tiling12_1_1[_config], 4); // 12.1.1
|
|
else
|
|
add_triangle(tiling12_1_2[_config], 8); // 12.1.2
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 13:
|
|
if (test_face(test13[_config][0]))
|
|
_subconfig += 1;
|
|
if (test_face(test13[_config][1]))
|
|
_subconfig += 2;
|
|
if (test_face(test13[_config][2]))
|
|
_subconfig += 4;
|
|
if (test_face(test13[_config][3]))
|
|
_subconfig += 8;
|
|
if (test_face(test13[_config][4]))
|
|
_subconfig += 16;
|
|
if (test_face(test13[_config][5]))
|
|
_subconfig += 32;
|
|
switch (subconfig13[_subconfig]) {
|
|
case 0:/* 13.1 */
|
|
add_triangle(tiling13_1[_config], 4);
|
|
break;
|
|
|
|
case 1:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][0], 6);
|
|
break;
|
|
case 2:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][1], 6);
|
|
break;
|
|
case 3:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][2], 6);
|
|
break;
|
|
case 4:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][3], 6);
|
|
break;
|
|
case 5:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][4], 6);
|
|
break;
|
|
case 6:/* 13.2 */
|
|
add_triangle(tiling13_2[_config][5], 6);
|
|
break;
|
|
|
|
case 7:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][0], 10, v12);
|
|
break;
|
|
case 8:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][1], 10, v12);
|
|
break;
|
|
case 9:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][2], 10, v12);
|
|
break;
|
|
case 10:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][3], 10, v12);
|
|
break;
|
|
case 11:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][4], 10, v12);
|
|
break;
|
|
case 12:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][5], 10, v12);
|
|
break;
|
|
case 13:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][6], 10, v12);
|
|
break;
|
|
case 14:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][7], 10, v12);
|
|
break;
|
|
case 15:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][8], 10, v12);
|
|
break;
|
|
case 16:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][9], 10, v12);
|
|
break;
|
|
case 17:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][10], 10, v12);
|
|
break;
|
|
case 18:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3[_config][11], 10, v12);
|
|
break;
|
|
|
|
case 19:/* 13.4 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_4[_config][0], 12, v12);
|
|
break;
|
|
case 20:/* 13.4 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_4[_config][1], 12, v12);
|
|
break;
|
|
case 21:/* 13.4 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_4[_config][2], 12, v12);
|
|
break;
|
|
case 22:/* 13.4 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_4[_config][3], 12, v12);
|
|
break;
|
|
|
|
case 23:/* 13.5 */
|
|
_subconfig = 0;
|
|
if (_config == 0) {
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[0][0], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[0][0], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[1][2], 10);
|
|
}
|
|
} else {
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[1][0], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[1][0], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[0][2], 10);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 24:/* 13.5 */
|
|
_subconfig = 1;
|
|
if (_config == 0) {
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[0][1], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[0][1], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[1][0], 10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[1][1], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[1][1], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[0][3], 10);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 25:/* 13.5 */
|
|
_subconfig = 2;
|
|
if(_config == 0)
|
|
{
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[0][2], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[0][2], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[1][3], 10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[1][2], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[1][2], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[0][0], 10);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case 26: /* 13.5 */
|
|
_subconfig = 3;
|
|
if(_config == 0)
|
|
{
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[0][3], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[0][3], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[1][1], 10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (interior_test_case13())
|
|
add_triangle(tiling13_5_1[1][3], 6);
|
|
else {
|
|
if (tunnelOrientation == 1)
|
|
add_triangle(tiling13_5_2[1][3], 10);
|
|
else
|
|
add_triangle(tiling13_5_2[0][2], 10);
|
|
}
|
|
}
|
|
/* 13.4 common node is negative*/
|
|
// v12 = add_c_vertex() ;
|
|
// add_triangle( tiling13_4[_config][3], 12, v12 ) ;
|
|
break;
|
|
|
|
case 27:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][0], 10, v12);
|
|
break;
|
|
case 28:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][1], 10, v12);
|
|
break;
|
|
case 29:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][2], 10, v12);
|
|
break;
|
|
case 30:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][3], 10, v12);
|
|
break;
|
|
case 31:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][4], 10, v12);
|
|
break;
|
|
case 32:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][5], 10, v12);
|
|
break;
|
|
case 33:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][6], 10, v12);
|
|
break;
|
|
case 34:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][7], 10, v12);
|
|
break;
|
|
case 35:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][8], 10, v12);
|
|
break;
|
|
case 36:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][9], 10, v12);
|
|
break;
|
|
case 37:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][10], 10, v12);
|
|
break;
|
|
case 38:/* 13.3 */
|
|
v12 = add_c_vertex();
|
|
add_triangle(tiling13_3_[_config][11], 10, v12);
|
|
break;
|
|
|
|
case 39:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][0], 6);
|
|
break;
|
|
case 40:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][1], 6);
|
|
break;
|
|
case 41:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][2], 6);
|
|
break;
|
|
case 42:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][3], 6);
|
|
break;
|
|
case 43:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][4], 6);
|
|
break;
|
|
case 44:/* 13.2 */
|
|
add_triangle(tiling13_2_[_config][5], 6);
|
|
break;
|
|
|
|
case 45:/* 13.1 */
|
|
add_triangle(tiling13_1_[_config], 4);
|
|
break;
|
|
|
|
default:
|
|
printf("Marching Cubes: Impossible case 13?\n");
|
|
print_cube();
|
|
}
|
|
break;
|
|
|
|
case 14:
|
|
add_triangle(tiling14[_config], 4);
|
|
break;
|
|
};
|
|
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Adding triangles
|
|
void MarchingCubes::add_triangle(const char* trig, char n, int v12)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
int tv[3];
|
|
|
|
for (int t = 0; t < 3 * n; t++) {
|
|
switch (trig[t]) {
|
|
case 0:
|
|
tv[t % 3] = get_x_vert(_i, _j, _k);
|
|
break;
|
|
case 1:
|
|
tv[t % 3] = get_y_vert(_i + 1, _j, _k);
|
|
break;
|
|
case 2:
|
|
tv[t % 3] = get_x_vert(_i, _j + 1, _k);
|
|
break;
|
|
case 3:
|
|
tv[t % 3] = get_y_vert(_i, _j, _k);
|
|
break;
|
|
case 4:
|
|
tv[t % 3] = get_x_vert(_i, _j, _k + 1);
|
|
break;
|
|
case 5:
|
|
tv[t % 3] = get_y_vert(_i + 1, _j, _k + 1);
|
|
break;
|
|
case 6:
|
|
tv[t % 3] = get_x_vert(_i, _j + 1, _k + 1);
|
|
break;
|
|
case 7:
|
|
tv[t % 3] = get_y_vert(_i, _j, _k + 1);
|
|
break;
|
|
case 8:
|
|
tv[t % 3] = get_z_vert(_i, _j, _k);
|
|
break;
|
|
case 9:
|
|
tv[t % 3] = get_z_vert(_i + 1, _j, _k);
|
|
break;
|
|
case 10:
|
|
tv[t % 3] = get_z_vert(_i + 1, _j + 1, _k);
|
|
break;
|
|
case 11:
|
|
tv[t % 3] = get_z_vert(_i, _j + 1, _k);
|
|
break;
|
|
case 12:
|
|
tv[t % 3] = v12;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (tv[t % 3] == -1) {
|
|
printf("Marching Cubes: invalid triangle %d\n", _ntrigs + 1);
|
|
print_cube();
|
|
}
|
|
|
|
if (t % 3 == 2) {
|
|
if (_ntrigs >= _Ntrigs) {
|
|
Triangle *temp = _triangles;
|
|
_triangles = new Triangle[2 * _Ntrigs];
|
|
memcpy(_triangles, temp, _Ntrigs * sizeof(Triangle));
|
|
delete[] temp;
|
|
printf("%d allocated triangles\n", _Ntrigs);
|
|
_Ntrigs *= 2;
|
|
}
|
|
|
|
Triangle *T = _triangles + _ntrigs++;
|
|
T->v1 = tv[0];
|
|
T->v2 = tv[1];
|
|
T->v3 = tv[2];
|
|
}
|
|
}
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Calculating gradient
|
|
|
|
real MarchingCubes::get_x_grad(const int i, const int j, const int k) const
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if (i > 0) {
|
|
if (i < _size_x - 1)
|
|
return (get_data(i + 1, j, k) - get_data(i - 1, j, k)) / 2;
|
|
else
|
|
return get_data(i, j, k) - get_data(i - 1, j, k);
|
|
} else
|
|
return get_data(i + 1, j, k) - get_data(i, j, k);
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
real MarchingCubes::get_y_grad(const int i, const int j, const int k) const
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if (j > 0) {
|
|
if (j < _size_y - 1)
|
|
return (get_data(i, j + 1, k) - get_data(i, j - 1, k)) / 2;
|
|
else
|
|
return get_data(i, j, k) - get_data(i, j - 1, k);
|
|
} else
|
|
return get_data(i, j + 1, k) - get_data(i, j, k);
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
real MarchingCubes::get_z_grad(const int i, const int j, const int k) const
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if (k > 0) {
|
|
if (k < _size_z - 1)
|
|
return (get_data(i, j, k + 1) - get_data(i, j, k - 1)) / 2;
|
|
else
|
|
return get_data(i, j, k) - get_data(i, j, k - 1);
|
|
} else
|
|
return get_data(i, j, k + 1) - get_data(i, j, k);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Adding vertices
|
|
|
|
void MarchingCubes::test_vertex_addition() {
|
|
if (_nverts >= _Nverts) {
|
|
Vertex *temp = _vertices;
|
|
_vertices = new Vertex[_Nverts * 2];
|
|
memcpy(_vertices, temp, _Nverts * sizeof(Vertex));
|
|
delete[] temp;
|
|
printf("%d allocated vertices\n", _Nverts);
|
|
_Nverts *= 2;
|
|
}
|
|
}
|
|
|
|
int MarchingCubes::add_x_vertex()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
test_vertex_addition();
|
|
Vertex *vert = _vertices + _nverts++;
|
|
|
|
real u = (_cube[0]) / (_cube[0] - _cube[1]);
|
|
|
|
vert->x = (real) _i + u;
|
|
vert->y = (real) _j;
|
|
vert->z = (real) _k;
|
|
|
|
vert->nx = (1 - u) * get_x_grad(_i, _j, _k) + u * get_x_grad(_i + 1, _j, _k);
|
|
vert->ny = (1 - u) * get_y_grad(_i, _j, _k) + u * get_y_grad(_i + 1, _j, _k);
|
|
vert->nz = (1 - u) * get_z_grad(_i, _j, _k) + u * get_z_grad(_i + 1, _j, _k);
|
|
|
|
u = (real) sqrt(vert->nx * vert->nx + vert->ny * vert->ny + vert->nz * vert->nz);
|
|
if (u > 0) {
|
|
vert->nx /= u;
|
|
vert->ny /= u;
|
|
vert->nz /= u;
|
|
}
|
|
|
|
return _nverts - 1;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int MarchingCubes::add_y_vertex()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
test_vertex_addition();
|
|
Vertex *vert = _vertices + _nverts++;
|
|
|
|
real u = (_cube[0]) / (_cube[0] - _cube[3]);
|
|
|
|
vert->x = (real) _i;
|
|
vert->y = (real) _j + u;
|
|
vert->z = (real) _k;
|
|
|
|
vert->nx = (1 - u) * get_x_grad(_i, _j, _k)
|
|
+ u * get_x_grad(_i, _j + 1, _k);
|
|
vert->ny = (1 - u) * get_y_grad(_i, _j, _k)
|
|
+ u * get_y_grad(_i, _j + 1, _k);
|
|
vert->nz = (1 - u) * get_z_grad(_i, _j, _k)
|
|
+ u * get_z_grad(_i, _j + 1, _k);
|
|
|
|
u = (real) sqrt(
|
|
vert->nx * vert->nx + vert->ny * vert->ny + vert->nz * vert->nz);
|
|
if (u > 0) {
|
|
vert->nx /= u;
|
|
vert->ny /= u;
|
|
vert->nz /= u;
|
|
}
|
|
|
|
return _nverts - 1;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int MarchingCubes::add_z_vertex()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
test_vertex_addition();
|
|
Vertex *vert = _vertices + _nverts++;
|
|
|
|
real u = (_cube[0]) / (_cube[0] - _cube[4]);
|
|
|
|
vert->x = (real) _i;
|
|
vert->y = (real) _j;
|
|
vert->z = (real) _k + u;
|
|
|
|
vert->nx = (1 - u) * get_x_grad(_i, _j, _k)
|
|
+ u * get_x_grad(_i, _j, _k + 1);
|
|
vert->ny = (1 - u) * get_y_grad(_i, _j, _k)
|
|
+ u * get_y_grad(_i, _j, _k + 1);
|
|
vert->nz = (1 - u) * get_z_grad(_i, _j, _k)
|
|
+ u * get_z_grad(_i, _j, _k + 1);
|
|
|
|
u = (real) sqrt(
|
|
vert->nx * vert->nx + vert->ny * vert->ny + vert->nz * vert->nz);
|
|
if (u > 0) {
|
|
vert->nx /= u;
|
|
vert->ny /= u;
|
|
vert->nz /= u;
|
|
}
|
|
|
|
return _nverts - 1;
|
|
}
|
|
|
|
int MarchingCubes::add_c_vertex()
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
test_vertex_addition();
|
|
Vertex *vert = _vertices + _nverts++;
|
|
|
|
real u = 0;
|
|
int vid;
|
|
|
|
vert->x = vert->y = vert->z = vert->nx = vert->ny = vert->nz = 0;
|
|
|
|
// Computes the average of the intersection points of the cube
|
|
vid = get_x_vert(_i, _j, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_y_vert(_i + 1, _j, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_x_vert(_i, _j + 1, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_y_vert(_i, _j, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_x_vert(_i, _j, _k + 1);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_y_vert(_i + 1, _j, _k + 1);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_x_vert(_i, _j + 1, _k + 1);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_y_vert(_i, _j, _k + 1);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_z_vert(_i, _j, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_z_vert(_i + 1, _j, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_z_vert(_i + 1, _j + 1, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
vid = get_z_vert(_i, _j + 1, _k);
|
|
if (vid != -1) {
|
|
++u;
|
|
const Vertex &v = _vertices[vid];
|
|
vert->x += v.x;
|
|
vert->y += v.y;
|
|
vert->z += v.z;
|
|
vert->nx += v.nx;
|
|
vert->ny += v.ny;
|
|
vert->nz += v.nz;
|
|
}
|
|
|
|
vert->x /= u;
|
|
vert->y /= u;
|
|
vert->z /= u;
|
|
|
|
u = (real) sqrt(
|
|
vert->nx * vert->nx + vert->ny * vert->ny + vert->nz * vert->nz);
|
|
if (u > 0) {
|
|
vert->nx /= u;
|
|
vert->ny /= u;
|
|
vert->nz /= u;
|
|
}
|
|
|
|
return _nverts - 1;
|
|
}
|
|
//_____________________________________________________________________________
|
|
#ifdef MC_OUTPUT
|
|
//_____________________________________________________________________________
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Grid exportation
|
|
void MarchingCubes::writeISO(const char *fn)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
unsigned char buf[sizeof(float)];
|
|
|
|
FILE *fp = fopen(fn, "wb");
|
|
|
|
// header
|
|
*(int*) buf = _size_x;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(int*) buf = _size_y;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(int*) buf = _size_z;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
|
|
*(float*) buf = -1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(float*) buf = 1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(float*) buf = -1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(float*) buf = 1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(float*) buf = -1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
*(float*) buf = 1.0f;
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
|
|
for (int i = 0; i < _size_x; i++) {
|
|
for (int j = 0; j < _size_y; j++) {
|
|
for (int k = 0; k < _size_z; k++) {
|
|
*(float*) buf = (float) get_data(i, j, k);
|
|
fwrite(buf, sizeof(float), 1, fp);
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
|
|
//_____________________________________________________________________________
|
|
// PLY exportation
|
|
void MarchingCubes::writePLY(const char *fn, bool bin)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
|
|
typedef struct PlyFace {
|
|
unsigned char nverts; /* number of Vertex indices in list */
|
|
int *verts; /* Vertex index list */
|
|
} PlyFace;
|
|
|
|
PlyProperty vert_props[] = { /* list of property information for a PlyVertex */
|
|
{ "x", Float32, Float32, offsetof( Vertex ,x ), 0, 0, 0, 0 }, { "y",
|
|
Float32, Float32, offsetof( Vertex ,y ), 0, 0, 0, 0 }, { "z",
|
|
Float32, Float32, offsetof( Vertex ,z ), 0, 0, 0, 0 }, { "nx",
|
|
Float32, Float32, offsetof( Vertex ,nx ), 0, 0, 0, 0 }, { "ny",
|
|
Float32, Float32, offsetof( Vertex ,ny ), 0, 0, 0, 0 }, { "nz",
|
|
Float32, Float32, offsetof( Vertex ,nz ), 0, 0, 0, 0 } };
|
|
|
|
PlyProperty face_props[] = { /* list of property information for a PlyFace */
|
|
{ "vertex_indices", Int32, Int32, offsetof( PlyFace,verts ), 1, Uint8,
|
|
Uint8, offsetof( PlyFace,nverts ) }, };
|
|
|
|
PlyFile *ply;
|
|
FILE *fp = fopen(fn, "w");
|
|
|
|
int i;
|
|
PlyFace face;
|
|
int verts[3];
|
|
char *elem_names[] = { "vertex", "face" };
|
|
printf("Marching Cubes::writePLY(%s)...", fn);
|
|
ply = write_ply(fp, 2, elem_names, bin ? PLY_BINARY_LE : PLY_ASCII);
|
|
|
|
/* describe what properties go into the PlyVertex elements */
|
|
describe_element_ply(ply, "vertex", _nverts);
|
|
describe_property_ply(ply, &vert_props[0]);
|
|
describe_property_ply(ply, &vert_props[1]);
|
|
describe_property_ply(ply, &vert_props[2]);
|
|
describe_property_ply(ply, &vert_props[3]);
|
|
describe_property_ply(ply, &vert_props[4]);
|
|
describe_property_ply(ply, &vert_props[5]);
|
|
|
|
/* describe PlyFace properties (just list of PlyVertex indices) */
|
|
describe_element_ply(ply, "face", _ntrigs);
|
|
describe_property_ply(ply, &face_props[0]);
|
|
|
|
header_complete_ply(ply);
|
|
|
|
/* set up and write the PlyVertex elements */
|
|
put_element_setup_ply(ply, "vertex");
|
|
for (i = 0; i < _nverts; i++)
|
|
put_element_ply(ply, (void *) &(_vertices[i]));
|
|
printf(" %d vertices written\n", _nverts);
|
|
|
|
/* set up and write the PlyFace elements */
|
|
put_element_setup_ply(ply, "face");
|
|
face.nverts = 3;
|
|
face.verts = verts;
|
|
for (i = 0; i < _ntrigs; i++) {
|
|
face.verts[0] = _triangles[i].v1;
|
|
face.verts[1] = _triangles[i].v2;
|
|
face.verts[2] = _triangles[i].v3;
|
|
put_element_ply(ply, (void *) &face);
|
|
}
|
|
printf(" %d triangles written\n", _ntrigs);
|
|
|
|
close_ply(ply);
|
|
free_ply(ply);
|
|
// fclose(fp);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// PLY importation
|
|
void MarchingCubes::readPLY(const char *fn)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
typedef struct PlyFace {
|
|
unsigned char nverts; /* number of Vertex indices in list */
|
|
int *verts; /* Vertex index list */
|
|
} PlyFace;
|
|
|
|
PlyProperty vert_props[] = { /* list of property information for a PlyVertex */
|
|
{ "x", Float32, Float32, offsetof( Vertex ,x ), 0, 0, 0, 0 }, { "y",
|
|
Float32, Float32, offsetof( Vertex ,y ), 0, 0, 0, 0 }, { "z",
|
|
Float32, Float32, offsetof( Vertex ,z ), 0, 0, 0, 0 }, { "nx",
|
|
Float32, Float32, offsetof( Vertex ,nx ), 0, 0, 0, 0 }, { "ny",
|
|
Float32, Float32, offsetof( Vertex ,ny ), 0, 0, 0, 0 }, { "nz",
|
|
Float32, Float32, offsetof( Vertex ,nz ), 0, 0, 0, 0 } };
|
|
|
|
PlyProperty face_props[] = { /* list of property information for a PlyFace */
|
|
{ "vertex_indices", Int32, Int32, offsetof( PlyFace,verts ), 1, Uint8,
|
|
Uint8, offsetof( PlyFace,nverts ) }, };
|
|
|
|
FILE *fp = fopen(fn, "r");
|
|
if (!fp)
|
|
return;
|
|
PlyFile *ply = read_ply(fp);
|
|
printf("Marching Cubes::readPLY(%s)...", fn);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// gets the number of faces and vertices
|
|
for (int i = 0; i < ply->num_elem_types; ++i) {
|
|
int elem_count;
|
|
char *elem_name = setup_element_read_ply(ply, i, &elem_count);
|
|
if (equal_strings("vertex", elem_name))
|
|
_Nverts = _nverts = elem_count;
|
|
if (equal_strings("face", elem_name))
|
|
_Ntrigs = _ntrigs = elem_count;
|
|
}
|
|
delete[] _vertices;
|
|
_vertices = new Vertex[_Nverts];
|
|
delete[] _triangles;
|
|
_triangles = new Triangle[_Ntrigs];
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/* examine each element type that is in the file (PlyVertex, PlyFace) */
|
|
|
|
for (int i = 0; i < ply->num_elem_types; ++i) {
|
|
/* prepare to read the i'th list of elements */
|
|
int elem_count;
|
|
char *elem_name = setup_element_read_ply(ply, i, &elem_count);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
if (equal_strings("vertex", elem_name)) {
|
|
/* set up for getting PlyVertex elements */
|
|
setup_property_ply(ply, &vert_props[0]);
|
|
setup_property_ply(ply, &vert_props[1]);
|
|
setup_property_ply(ply, &vert_props[2]);
|
|
setup_property_ply(ply, &vert_props[3]);
|
|
setup_property_ply(ply, &vert_props[4]);
|
|
setup_property_ply(ply, &vert_props[5]);
|
|
|
|
for (int j = 0; j < _nverts; ++j) {
|
|
get_element_ply(ply, (void *) (_vertices + j));
|
|
}
|
|
printf(" %d vertices read\n", _nverts);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
else if (equal_strings("face", elem_name)) {
|
|
/* set up for getting PlyFace elements */
|
|
/* (all we need are PlyVertex indices) */
|
|
|
|
setup_property_ply(ply, &face_props[0]);
|
|
PlyFace face;
|
|
for (int j = 0; j < _ntrigs; ++j) {
|
|
get_element_ply(ply, (void *) &face);
|
|
if (face.nverts != 3) {
|
|
printf(
|
|
"not a triangulated surface: polygon %d has %d sides\n",
|
|
j, face.nverts);
|
|
return;
|
|
}
|
|
|
|
_triangles[j].v1 = face.verts[0];
|
|
_triangles[j].v2 = face.verts[1];
|
|
_triangles[j].v3 = face.verts[2];
|
|
|
|
free(face.verts);
|
|
}
|
|
printf(" %d triangles read\n", _ntrigs);
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
else
|
|
/* all non-PlyVertex and non-PlyFace elements are grabbed here */
|
|
get_other_element_ply(ply);
|
|
//-----------------------------------------------------------------------------
|
|
}
|
|
|
|
close_ply(ply);
|
|
free_ply(ply);
|
|
|
|
// fit_to_bbox() ;
|
|
fclose(fp);
|
|
}
|
|
//_____________________________________________________________________________
|
|
|
|
//_____________________________________________________________________________
|
|
// Open Inventor / VRML 1.0 ascii exportation
|
|
void MarchingCubes::writeIV(const char *fn)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
FILE *fp = fopen(fn, "w");
|
|
int i;
|
|
|
|
printf("Marching Cubes::exportIV(%s)...", fn);
|
|
|
|
fprintf(fp,
|
|
"#Inventor V2.1 ascii \n\nSeparator { \n ShapeHints {\n vertexOrdering COUNTERCLOCKWISE\n shapeType UNKNOWN_SHAPE_TYPE\n creaseAngle 0.0\n }\n Coordinate3 { \n point [ \n");
|
|
for (i = 0; i < _nverts; i++)
|
|
fprintf(fp, " %f %f %f,\n", _vertices[i].x, _vertices[i].y,
|
|
_vertices[i].z);
|
|
printf(" %d vertices written\n", _nverts);
|
|
|
|
fprintf(fp, "\n ] \n} \nNormal { \nvector [ \n");
|
|
for (i = 0; i < _nverts; i++)
|
|
fprintf(fp, " %f %f %f,\n", _vertices[i].nx, _vertices[i].ny,
|
|
_vertices[i].nz);
|
|
|
|
fprintf(fp, "\n ] \n} \nIndexedFaceSet { \ncoordIndex [ \n");
|
|
for (i = 0; i < _ntrigs; i++)
|
|
fprintf(fp, "%d, %d, %d, -1,\n", _triangles[i].v1, _triangles[i].v2,
|
|
_triangles[i].v3);
|
|
|
|
fprintf(fp, " ] \n } \n } \n");
|
|
fclose(fp);
|
|
printf(" %d triangles written\n", _ntrigs);
|
|
}
|
|
//_____________________________________________________________________________
|
|
#endif
|
|
|