~ubuntu-branches/ubuntu/precise/openwalnut/precise

« back to all changes in this revision

Viewing changes to src/core/graphicsEngine/algorithms/WMarchingLegoAlgorithm.h

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Eichelbaum
  • Date: 2011-06-21 10:26:54 UTC
  • Revision ID: james.westby@ubuntu.com-20110621102654-rq0zf436q949biih
Tags: upstream-1.2.5
ImportĀ upstreamĀ versionĀ 1.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------
 
2
//
 
3
// Project: OpenWalnut ( http://www.openwalnut.org )
 
4
//
 
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
 
6
// For more information see http://www.openwalnut.org/copying
 
7
//
 
8
// This file is part of OpenWalnut.
 
9
//
 
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.
 
14
//
 
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.
 
19
//
 
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/>.
 
22
//
 
23
//---------------------------------------------------------------------------
 
24
 
 
25
#ifndef WMARCHINGLEGOALGORITHM_H
 
26
#define WMARCHINGLEGOALGORITHM_H
 
27
 
 
28
#include <vector>
 
29
#include <map>
 
30
#include "../../common/math/WMatrix.h"
 
31
#include "../../common/WProgressCombiner.h"
 
32
#include "../WTriangleMesh.h"
 
33
#include "../WExportWGE.h"
 
34
 
 
35
/**
 
36
 * A point consisting of its coordinates and ID
 
37
 */
 
38
struct WMLPointXYZId
 
39
{
 
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.
 
44
};
 
45
 
 
46
typedef std::map< unsigned int, WMLPointXYZId > ID2WMLPointXYZId;
 
47
 
 
48
/**
 
49
 * Encapsulated ids representing a triangle.
 
50
 */
 
51
struct WMLTriangle
 
52
{
 
53
    unsigned int pointID[3]; //!< The IDs of the vertices of the triangle.
 
54
};
 
55
 
 
56
typedef std::vector<WMLTriangle> WMLTriangleVECTOR;
 
57
 
 
58
 
 
59
/**
 
60
 * Creates a non interpolated triangulation of an isosurface
 
61
 */
 
62
class WGE_EXPORT WMarchingLegoAlgorithm
 
63
{
 
64
public:
 
65
    /**
 
66
     * standard constructor
 
67
     */
 
68
    WMarchingLegoAlgorithm();
 
69
 
 
70
    /**
 
71
     * destructor
 
72
     */
 
73
    ~WMarchingLegoAlgorithm();
 
74
 
 
75
    /**
 
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.
 
79
     *
 
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.
 
86
     *
 
87
     * \return the created triangle mesh
 
88
     */
 
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,
 
93
                                                          double isoValue );
 
94
 
 
95
    /**
 
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.
 
99
     *
 
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.
 
106
     *
 
107
     * \return the created triangle mesh
 
108
     */
 
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,
 
112
                                                              size_t isoValue );
 
113
 
 
114
protected:
 
115
private:
 
116
    /**
 
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
 
122
     */
 
123
    void addSurface( size_t x, size_t y, size_t z, size_t surface );
 
124
 
 
125
    /**
 
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
 
130
     * \return the id
 
131
     */
 
132
    size_t getVertexID( size_t nX, size_t nY, size_t nZ );
 
133
 
 
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.
 
137
 
 
138
    double m_tIsoLevel;  //!< The isovalue.
 
139
 
 
140
    WMatrix< double > m_matrix; //!< The 4x4 transformation matrix for the triangle vertices.
 
141
 
 
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.
 
144
};
 
145
 
 
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,
 
149
                                                                                                 double isoValue )
 
150
{
 
151
    WAssert( vals, "No value set provided." );
 
152
 
 
153
    m_idToVertices.clear();
 
154
    m_trivecTriangles.clear();
 
155
 
 
156
    m_nCellsX = nbCoordsX - 1;
 
157
    m_nCellsY = nbCoordsY - 1;
 
158
    m_nCellsZ = nbCoordsZ - 1;
 
159
 
 
160
    m_matrix = mat;
 
161
 
 
162
    m_tIsoLevel = isoValue;
 
163
 
 
164
    size_t nX = nbCoordsX;
 
165
    size_t nY = nbCoordsY;
 
166
 
 
167
    size_t nPointsInSlice = nX * nY;
 
168
 
 
169
    // Generate isosurface.
 
170
    for( size_t z = 0; z < m_nCellsZ; z++ )
 
171
    {
 
172
        for( size_t y = 0; y < m_nCellsY; y++ )
 
173
        {
 
174
            for( size_t x = 0; x < m_nCellsX; x++ )
 
175
            {
 
176
                if( ( *vals )[ z * nPointsInSlice + y * nX + x ] < m_tIsoLevel )
 
177
                {
 
178
                    continue;
 
179
                }
 
180
 
 
181
                if( x > 0 && ( ( *vals )[ z * nPointsInSlice + y * nX + x - 1 ] < m_tIsoLevel ) )
 
182
                {
 
183
                    addSurface( x, y, z, 1 );
 
184
                }
 
185
                if( x < m_nCellsX - 1 && ( ( *vals )[ z * nPointsInSlice + y * nX + x + 1 ] < m_tIsoLevel ) )
 
186
                {
 
187
                    addSurface( x, y, z, 2 );
 
188
                }
 
189
 
 
190
                if( y > 0 && ( ( *vals )[ z * nPointsInSlice + ( y - 1 ) * nX + x ] < m_tIsoLevel ) )
 
191
                {
 
192
                    addSurface( x, y, z, 3 );
 
193
                }
 
194
 
 
195
                if( y < m_nCellsY - 1 && ( ( *vals )[ z * nPointsInSlice + ( y + 1 ) * nX + x ] < m_tIsoLevel ) )
 
196
                {
 
197
                    addSurface( x, y, z, 4 );
 
198
                }
 
199
 
 
200
                if( z > 0 && ( ( *vals )[ ( z - 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
 
201
                {
 
202
                    addSurface( x, y, z, 5 );
 
203
                }
 
204
 
 
205
                if( z < m_nCellsZ - 1 && ( ( *vals )[ ( z + 1 ) * nPointsInSlice + y * nX + x ] < m_tIsoLevel ) )
 
206
                {
 
207
                    addSurface( x, y, z, 6 );
 
208
                }
 
209
 
 
210
                if( x == 0 )
 
211
                {
 
212
                    addSurface( x, y, z, 1 );
 
213
                }
 
214
                if( x == m_nCellsX - 1 )
 
215
                {
 
216
                    addSurface( x, y, z, 2 );
 
217
                }
 
218
 
 
219
                if( y == 0 )
 
220
                {
 
221
                    addSurface( x, y, z, 3 );
 
222
                }
 
223
 
 
224
                if( y == m_nCellsY - 1 )
 
225
                {
 
226
                    addSurface( x, y, z, 4 );
 
227
                }
 
228
 
 
229
                if( z == 0 )
 
230
                {
 
231
                    addSurface( x, y, z, 5 );
 
232
                }
 
233
 
 
234
                if( z == m_nCellsZ - 1 )
 
235
                {
 
236
                    addSurface( x, y, z, 6 );
 
237
                }
 
238
            }
 
239
        }
 
240
    }
 
241
    unsigned int nextID = 0;
 
242
    boost::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_idToVertices.size(), m_trivecTriangles.size() ) );
 
243
 
 
244
    // Rename vertices.
 
245
    ID2WMLPointXYZId::iterator mapIterator = m_idToVertices.begin();
 
246
    while( mapIterator != m_idToVertices.end() )
 
247
    {
 
248
        WPosition texCoord = WPosition( mapIterator->second.x / nbCoordsX,
 
249
                                                      mapIterator->second.y / nbCoordsY,
 
250
                                                      mapIterator->second.z / nbCoordsZ );
 
251
 
 
252
        // transform from grid coordinate system to world coordinates
 
253
        WPosition pos = WPosition( mapIterator->second.x, mapIterator->second.y, mapIterator->second.z );
 
254
 
 
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;
 
260
 
 
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 );
 
266
        nextID++;
 
267
        mapIterator++;
 
268
    }
 
269
 
 
270
    // Now rename triangles.
 
271
    WMLTriangleVECTOR::iterator vecIterator = m_trivecTriangles.begin();
 
272
    while( vecIterator != m_trivecTriangles.end() )
 
273
    {
 
274
        for( unsigned int i = 0; i < 3; i++ )
 
275
        {
 
276
            unsigned int newID = m_idToVertices[( *vecIterator ).pointID[i]].newID;
 
277
            ( *vecIterator ).pointID[i] = newID;
 
278
        }
 
279
        triMesh->addTriangle( ( *vecIterator ).pointID[0], ( *vecIterator ).pointID[1], ( *vecIterator ).pointID[2] );
 
280
        vecIterator++;
 
281
    }
 
282
    return triMesh;
 
283
}
 
284
#endif  // WMARCHINGLEGOALGORITHM_H