1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
25
#ifndef WMARCHINGLEGOALGORITHM_H
26
#define WMARCHINGLEGOALGORITHM_H
30
#include "../../common/math/WMatrix.h"
31
#include "../../common/WProgressCombiner.h"
32
#include "../WTriangleMesh.h"
33
#include "../WExportWGE.h"
36
* A point consisting of its coordinates and ID
40
unsigned int newID; //!< ID of the point
41
double x; //!< x coordinates of the point.
42
double y; //!< y coordinates of the point.
43
double z; //!< z coordinates of the point.
46
typedef std::map< unsigned int, WMLPointXYZId > ID2WMLPointXYZId;
49
* Encapsulated ids representing a triangle.
53
unsigned int pointID[3]; //!< The IDs of the vertices of the triangle.
56
typedef std::vector<WMLTriangle> WMLTriangleVECTOR;
60
* Creates a non interpolated triangulation of an isosurface
62
class WGE_EXPORT WMarchingLegoAlgorithm
66
* standard constructor
68
WMarchingLegoAlgorithm();
73
~WMarchingLegoAlgorithm();
76
* Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
77
* the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
78
* This might be useful where texture transformation matrices are used.
80
* \param nbCoordsX number of vertices in X direction
81
* \param nbCoordsY number of vertices in Y direction
82
* \param nbCoordsZ number of vertices in Z direction
83
* \param mat the matrix transforming the vertices from canonical space
84
* \param vals the values at the vertices
85
* \param isoValue The surface will run through all positions with this value.
87
* \return the created triangle mesh
89
template< typename T >
90
boost::shared_ptr< WTriangleMesh > generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
91
const WMatrix< double >& mat,
92
const std::vector< T >* vals,
96
* Generate the triangles for the surface on the given dataSet (inGrid, vals). The texture coordinates in the resulting mesh are relative to
97
* the grid. This means they are NOT transformed. This ensure faster grid matrix updates in texture space.
98
* This might be useful where texture transformation matrices are used.
100
* \param nbCoordsX number of vertices in X direction
101
* \param nbCoordsY number of vertices in Y direction
102
* \param nbCoordsZ number of vertices in Z direction
103
* \param mat the matrix transforming the vertices from canonical space
104
* \param vals the values at the vertices
105
* \param isoValue The surface will run through all positions with this value.
107
* \return the created triangle mesh
109
boost::shared_ptr< WTriangleMesh > genSurfaceOneValue( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
110
const WMatrix< double >& mat,
111
const std::vector< size_t >* vals,
117
* adds 2 triangles for a given face of the voxel
118
* \param x position of the voxel
119
* \param y position of the voxel
120
* \param z position of the voxel
121
* \param surface which side of the voxel to paint
123
void addSurface( size_t x, size_t y, size_t z, size_t surface );
126
* returns a vertex id for a given grid point
127
* \param nX x position in space
128
* \param nY y position in space
129
* \param nZ z position in space
132
size_t getVertexID( size_t nX, size_t nY, size_t nZ );
134
unsigned int m_nCellsX; //!< No. of cells in x direction.
135
unsigned int m_nCellsY; //!< No. of cells in y direction.
136
unsigned int m_nCellsZ; //!< No. of cells in z direction.
138
double m_tIsoLevel; //!< The isovalue.
140
WMatrix< double > m_matrix; //!< The 4x4 transformation matrix for the triangle vertices.
142
ID2WMLPointXYZId m_idToVertices; //!< List of WPointXYZIds which form the isosurface.
143
WMLTriangleVECTOR m_trivecTriangles; //!< List of WMCTriangleS which form the triangulation of the isosurface.
146
template<typename T> boost::shared_ptr<WTriangleMesh> WMarchingLegoAlgorithm::generateSurface( size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ,
147
const WMatrix< double >& mat,
148
const std::vector< T >* vals,
151
WAssert( vals, "No value set provided." );
153
m_idToVertices.clear();
154
m_trivecTriangles.clear();
156
m_nCellsX = nbCoordsX - 1;
157
m_nCellsY = nbCoordsY - 1;
158
m_nCellsZ = nbCoordsZ - 1;
162
m_tIsoLevel = isoValue;
164
size_t nX = nbCoordsX;
165
size_t nY = nbCoordsY;
167
size_t nPointsInSlice = nX * nY;
169
// Generate isosurface.
170
for( size_t z = 0; z < m_nCellsZ; z++ )
172
for( size_t y = 0; y < m_nCellsY; y++ )
174
for( size_t x = 0; x < m_nCellsX; x++ )
176
if( ( *vals )[ z * nPointsInSlice + y * nX + x ] < m_tIsoLevel )
181
if( x > 0 && ( ( *vals )[ z * nPointsInSlice + y * nX + x - 1 ] < m_tIsoLevel ) )
183
addSurface( x, y, z, 1 );
185
if( x < m_nCellsX - 1 && ( ( *vals )[ z * nPointsInSlice + y * nX + x + 1 ] < m_tIsoLevel ) )
187
addSurface( x, y, z, 2 );
190
if( y > 0 && ( ( *vals )[ z * nPointsInSlice + ( y - 1 ) * nX + x ] < m_tIsoLevel ) )
192
addSurface( x, y, z, 3 );
195
if( y < m_nCellsY - 1 && ( ( *vals )[ z * nPointsInSlice + ( y + 1 ) * nX + x ] < m_tIsoLevel ) )
197
addSurface( x, y, z, 4 );
200
if( z > 0 && ( ( *vals )[ ( z - 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
202
addSurface( x, y, z, 5 );
205
if( z < m_nCellsZ - 1 && ( ( *vals )[ ( z + 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
207
addSurface( x, y, z, 6 );
212
addSurface( x, y, z, 1 );
214
if( x == m_nCellsX - 1 )
216
addSurface( x, y, z, 2 );
221
addSurface( x, y, z, 3 );
224
if( y == m_nCellsY - 1 )
226
addSurface( x, y, z, 4 );
231
addSurface( x, y, z, 5 );
234
if( z == m_nCellsZ - 1 )
236
addSurface( x, y, z, 6 );
241
unsigned int nextID = 0;
242
boost::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_idToVertices.size(), m_trivecTriangles.size() ) );
245
ID2WMLPointXYZId::iterator mapIterator = m_idToVertices.begin();
246
while( mapIterator != m_idToVertices.end() )
248
WPosition texCoord = WPosition( mapIterator->second.x / nbCoordsX,
249
mapIterator->second.y / nbCoordsY,
250
mapIterator->second.z / nbCoordsZ );
252
// transform from grid coordinate system to world coordinates
253
WPosition pos = WPosition( mapIterator->second.x, mapIterator->second.y, mapIterator->second.z );
255
std::vector< double > resultPos4D( 4 );
256
resultPos4D[0] = m_matrix( 0, 0 ) * pos[0] + m_matrix( 0, 1 ) * pos[1] + m_matrix( 0, 2 ) * pos[2] + m_matrix( 0, 3 ) * 1;
257
resultPos4D[1] = m_matrix( 1, 0 ) * pos[0] + m_matrix( 1, 1 ) * pos[1] + m_matrix( 1, 2 ) * pos[2] + m_matrix( 1, 3 ) * 1;
258
resultPos4D[2] = m_matrix( 2, 0 ) * pos[0] + m_matrix( 2, 1 ) * pos[1] + m_matrix( 2, 2 ) * pos[2] + m_matrix( 2, 3 ) * 1;
259
resultPos4D[3] = m_matrix( 3, 0 ) * pos[0] + m_matrix( 3, 1 ) * pos[1] + m_matrix( 3, 2 ) * pos[2] + m_matrix( 3, 3 ) * 1;
261
( *mapIterator ).second.newID = nextID;
262
triMesh->addVertex( resultPos4D[0] / resultPos4D[3],
263
resultPos4D[1] / resultPos4D[3],
264
resultPos4D[2] / resultPos4D[3] );
265
triMesh->addTextureCoordinate( texCoord );
270
// Now rename triangles.
271
WMLTriangleVECTOR::iterator vecIterator = m_trivecTriangles.begin();
272
while( vecIterator != m_trivecTriangles.end() )
274
for( unsigned int i = 0; i < 3; i++ )
276
unsigned int newID = m_idToVertices[( *vecIterator ).pointID[i]].newID;
277
( *vecIterator ).pointID[i] = newID;
279
triMesh->addTriangle( ( *vecIterator ).pointID[0], ( *vecIterator ).pointID[1], ( *vecIterator ).pointID[2] );
284
#endif // WMARCHINGLEGOALGORITHM_H