Carna Version 3.3.3
Loading...
Searching...
No Matches
MeshFactory.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 - 2015 Leonid Kostrykin
3 *
4 * Chair of Medical Engineering (mediTEC)
5 * RWTH Aachen University
6 * Pauwelsstr. 20
7 * 52074 Aachen
8 * Germany
9 *
10 */
11
12#ifndef MESHFACTORY_H_6014714286
13#define MESHFACTORY_H_6014714286
14
19#include <Carna/base/Vertex.h>
20#include <Carna/base/math.h>
21#include <cstdint>
22#include <unordered_set>
23#include <functional>
24#include <memory>
25#include <istream>
26#include <ios>
27#include <string>
28
33namespace Carna
34{
35
36namespace base
37{
38
39
40
41// ----------------------------------------------------------------------------------
42// MeshFactory
43// ----------------------------------------------------------------------------------
44
55template< typename VertexType >
57{
58
59 template< typename VectorType >
60 static VertexType vertex( const VectorType& position, const VectorType& normal = VectorType(), const VectorType& color = VectorType() );
61
62public:
63
68 static ManagedMesh< VertexType, uint8_t >& createBox( float width, float height, float depth );
69
73
81 static ManagedMesh< VertexType, uint16_t >& createBall( float radius, unsigned int degree = 3 );
82
87
95 inline static ManagedMesh< VertexType, uint32_t >& createFromSTL( const std::string& path );
96
100
101}; // MeshFactory
102
103
104template< typename VertexType >
105template< typename VectorType >
107{
108 VertexType vertex;
109 vertex.x = position.x();
110 vertex.y = position.y();
111 vertex.z = position.z();
112 vertex.setNormal( normal );
113 vertex.setColor ( color );
114 return vertex;
115}
116
117
118template< typename VertexType >
120{
121 return createBox( size.x(), size.y(), size.z() );
122}
123
124
125template< typename VertexType >
127{
129
130 /* Define faces.
131 */
133 transforms[ 0 ] = math::basis4f( math::Vector3f( 0, 0, +1 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( -1, 0, 0 ) ); // left
134 transforms[ 1 ] = math::basis4f( math::Vector3f( 0, 0, -1 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( +1, 0, 0 ) ); // right
135 transforms[ 2 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( 0, 0, +1 ) ); // front
136 transforms[ 3 ] = math::basis4f( math::Vector3f( -1, 0, 0 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( 0, 0, -1 ) ); // back
137 transforms[ 4 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, 0, -1 ), math::Vector3f( 0, +1, 0 ) ); // top
138 transforms[ 5 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, 0, +1 ), math::Vector3f( 0, -1, 0 ) ); // bottom
139
140 const std::size_t verticesCount = 6 * 4;
141 const std::size_t indicesCount = 6 * 2 * 3;
142
144 typedef typename MeshInstance::Vertex Vertex;
145 typedef typename MeshInstance:: Index Index;
146 Vertex vertices[ verticesCount ];
147 Index indices[ indicesCount ];
148
149 int lastVertex = -1;
150 int lastIndex = -1;
151
152 /* Create vertices and indices.
153 */
154 for( unsigned int faceIndex = 0; faceIndex < 6; ++faceIndex )
155 {
157 const auto normalTransform = positionTransform.inverse().transpose();
158 const auto normalVector = ( normalTransform * math::Vector4f( 0, 0, 1, 0 ) ).normalized();
159
164
165 indices[ ++lastIndex ] = lastVertex - 3;
166 indices[ ++lastIndex ] = lastVertex - 2;
167 indices[ ++lastIndex ] = lastVertex;
168
169 indices[ ++lastIndex ] = lastVertex;
170 indices[ ++lastIndex ] = lastVertex - 2;
171 indices[ ++lastIndex ] = lastVertex - 1;
172 }
173
174 return MeshInstance::create
176 , vertices, verticesCount
177 , indices, indicesCount );
178}
179
180
181template< typename VertexType >
183{
184 const math::Matrix4f baseTransform = math::scaling4f( radius, radius, radius );
185 const unsigned int verticesPerEdge = 2 + degree;
186 const unsigned int verticesPerSide = verticesPerEdge * verticesPerEdge;
187 const unsigned int facesPerSide = ( verticesPerEdge - 1 ) * ( verticesPerEdge - 1 );
188 const unsigned int indicesPerSide = 6 * facesPerSide;
189
190 /* Define sides.
191 */
193 transforms[ 0 ] = math::basis4f( math::Vector3f( 0, 0, +1 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( -1, 0, 0 ) ); // left
194 transforms[ 1 ] = math::basis4f( math::Vector3f( 0, 0, -1 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( +1, 0, 0 ) ); // right
195 transforms[ 2 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( 0, 0, +1 ) ); // front
196 transforms[ 3 ] = math::basis4f( math::Vector3f( -1, 0, 0 ), math::Vector3f( 0, +1, 0 ), math::Vector3f( 0, 0, -1 ) ); // back
197 transforms[ 4 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, 0, -1 ), math::Vector3f( 0, +1, 0 ) ); // top
198 transforms[ 5 ] = math::basis4f( math::Vector3f( +1, 0, 0 ), math::Vector3f( 0, 0, +1 ), math::Vector3f( 0, -1, 0 ) ); // bottom
199
200 const std::size_t verticesCount = 6 * verticesPerSide;
201 const std::size_t indicesCount = 6 * indicesPerSide;
202 CARNA_ASSERT(indicesCount < ( 1 << 16 ));
203
205 typedef typename MeshInstance::Vertex Vertex;
206 typedef typename MeshInstance:: Index Index;
207 Vertex vertices[ verticesCount ];
208 Index indices[ indicesCount ];
209
210 int lastVertex = -1;
211 int lastIndex = -1;
212
213 /* Create vertices and indices.
214 */
215 for( unsigned int sideIndex = 0; sideIndex < 6; ++sideIndex )
216 {
218 const auto normalTransform = positionTransform.inverse().transpose();
219
220 for( unsigned int y = 0; y < verticesPerEdge; ++y )
221 for( unsigned int x = 0; x < verticesPerEdge; ++x )
222 {
223 const float fx = 2 * x / float( verticesPerEdge - 1 );
224 const float fy = 2 * y / float( verticesPerEdge - 1 );
225 const auto position = math::Vector3f( -1 + fx, -1 + fy, 1 ).normalized();
227 ( positionTransform * math::Vector4f( position.x(), position.y(), position.z(), 1 )
228 , normalTransform * math::Vector4f( position.x(), position.y(), position.z(), 0 )
229 );
230 }
231
232 for( unsigned int y = 0; y < verticesPerEdge - 1; ++y )
233 for( unsigned int x = 0; x < verticesPerEdge - 1; ++x )
234 {
235 const uint16_t ul = x + y * verticesPerEdge; // upper left
236 const uint16_t ur = x + 1 + y * verticesPerEdge; // upper right
237 const uint16_t ll = x + ( y + 1 ) * verticesPerEdge; // lower left
238 const uint16_t lr = x + 1 + ( y + 1 ) * verticesPerEdge; // lower right
239
240 indices[ ++lastIndex ] = verticesPerSide * sideIndex + ul;
241 indices[ ++lastIndex ] = verticesPerSide * sideIndex + lr;
242 indices[ ++lastIndex ] = verticesPerSide * sideIndex + ll;
243
244 indices[ ++lastIndex ] = verticesPerSide * sideIndex + ul;
245 indices[ ++lastIndex ] = verticesPerSide * sideIndex + ur;
246 indices[ ++lastIndex ] = verticesPerSide * sideIndex + lr;
247 }
248 }
249
250 return MeshInstance::create
252 , vertices, verticesCount
253 , indices, indicesCount );
254}
255
256
257template< typename VertexType >
259{
261 typedef typename MeshInstance::Vertex Vertex;
262 typedef typename MeshInstance:: Index Index;
263
264 Vertex vertex;
265 Index index = 0;
266
267 return MeshInstance::create( IndexBufferBase::PRIMITIVE_TYPE_POINTS, &vertex, 1, &index, 1 );
268}
269
270template< typename VertexType >
272{
273 return createFromSTL( std::fstream(path, std::ios::in | std::ios::binary) );
274}
275
276template< typename VertexType >
278{
279 auto origExceptMask = stlStream.exceptions();
280 stlStream.exceptions(std::istream::failbit | std::istream::badbit | std::istream::eofbit);
281
283
284 //discard first 80 bytes
285 stlStream.seekg(stlStream.beg + 80);
286
287 //read amount of triangles (32bit-uint)
288 stlStream.read(reinterpret_cast<char*>(&amountTriangles), 4);
289
291 typedef typename MeshInstance::Vertex Vertex;
292 typedef typename MeshInstance::Index Index;
293 typedef typename std::pair< Vertex, std::size_t > VertexIndexPair;
294
295 std::size_t indicesCount = amountTriangles * 3;
296 std::unique_ptr<Index[]> indices (new Index [indicesCount]);
297 std::unique_ptr<Vertex[]> vertices(new Vertex [indicesCount]);
298
299 std::function<std::size_t(const VertexIndexPair&)> vertexHash =
300 [](const VertexIndexPair& vertAndIndex) -> std::size_t
301 {
302 //creates combined hash value of the 3 public members "x","y","z" of a Vertex object; ignores the second member of pair
303 //This hash-combine-technique is taken from : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf (Page 2)
304 std::size_t hashVal = std::hash<decltype(vertAndIndex.first.x)>()(vertAndIndex.first.x);
305 hashVal ^= std::hash<decltype(vertAndIndex.first.y)>()(vertAndIndex.first.y) + 0x9e3779b9 + (hashVal << 6) + (hashVal >> 2);
306 hashVal ^= std::hash<decltype(vertAndIndex.first.z)> ()(vertAndIndex.first.z) + 0x9e3779b9 + (hashVal << 6) + (hashVal >> 2);
307 return hashVal;
308 };
309
310 std::function<std::size_t(const VertexIndexPair&, const VertexIndexPair&)> vertexComp =
312 {
313 //checks whether the members "x", "y", "z" of two Vertex objects are equal
314 return ((vertAndIndex1.first.x) == (vertAndIndex2.first.x)) && ((vertAndIndex1.first.y) == (vertAndIndex2.first.y)) && ((vertAndIndex1.first.z) == (vertAndIndex2.first.z));
315 };
316
317 std::unordered_set< VertexIndexPair, decltype(vertexHash), decltype(vertexComp) > vertsWithArrIndices(amountTriangles * 3, vertexHash, vertexComp);
318
319 std::size_t indicesItCount = 0;
320 std::size_t verticesItCount = 0;
321
322 //read triangles
323 for (unsigned int i = 0; i < amountTriangles; i++)
324 {
325 //discard normal
326 stlStream.seekg(12, std::ios_base::cur);
327
328 //read vertices
329 for (unsigned int j = 0; j < 3; j++) //read 3 vertices
330 {
331 float x, y, z;
332
333 //read 1 vertex
334 stlStream.read(reinterpret_cast<char*>(&x), 4);
335 stlStream.read(reinterpret_cast<char*>(&y), 4);
336 stlStream.read(reinterpret_cast<char*>(&z), 4);
337
338 Vertex vert;
339 vert.x = x;
340 vert.y = y;
341 vert.z = z;
342 //vert gets invalidated here
343 auto emplRes = vertsWithArrIndices.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(vert)), std::forward_as_tuple(verticesItCount));
344
345 if (emplRes.second)
346 {
347 vertices[verticesItCount++] = (emplRes.first)->first;
348 }
349
350 indices[indicesItCount++] = (emplRes.first)->second;
351 }
352
353 //discard 2 bytes
354 stlStream.seekg(2, std::ios_base::cur);
355 }
356
357 stlStream.exceptions(origExceptMask);
358
359 return MeshInstance::create
361 , vertices.get(), verticesItCount
362 , indices.get(), indicesCount);
363}
364
365
366
367} // namespace Carna :: base
368
369} // namespace Carna
370
371#endif // MESHFACTORY_H_6014714286
#define CARNA_ASSERT(expression)
If the given expression is false, a break point is raised in debug mode and an AssertionFailure throw...
Defines Carna::base::IndexBuffer.
Defines Carna::base::ManagedMesh.
Defines Carna::base::VertexAttributes.
Defines Carna::base::VertexBuffer.
Defines Carna::base::PVertex, Carna::base::PNVertex, Carna::base::VertexPosition, Carna::base::Vertex...
Represents an association.
Definition Association.h:45
AssociatedObjectType * get() const
Returns raw pointer to the referenced object.
Definition Association.h:61
static const unsigned int PRIMITIVE_TYPE_POINTS
Draws points. Indicates that each index makes up a single point.
static const unsigned int PRIMITIVE_TYPE_TRIANGLES
Draws triangles. Indicates that the indices make up the th triangle with .
Definition IndexBuffer.h:65
Creates simple predefined ManagedMesh instances.
Definition MeshFactory.h:57
static ManagedMesh< VertexType, uint8_t > & createPoint()
Creates mesh that consists of a single point.
static ManagedMesh< VertexType, uint16_t > & createBall(float radius, unsigned int degree=3)
Creates sphere with radius and a vertices number determined by degree. The ball is centered in .
static ManagedMesh< VertexType, uint8_t > & createBox(float width, float height, float depth)
Creates box with width, height and depth. The box is centered in .
static ManagedMesh< VertexType, uint32_t > & createFromSTL(const std::string &path)
Creates mesh from an STL file.
Defines Carna::base::math namespace and CARNA_FOR_VECTOR3UI.
Matrix4f basis4f(const Vector4f &x, const Vector4f &y, const Vector4f &z, const Vector4f &t=Vector4f(0, 0, 0, 0))
Creates basis embedded into a homogenous coordinates matrix.
Definition math.h:242
Eigen::Matrix< float, 4, 1 > Vector4f
Defines vector.
Definition math.h:195
Eigen::Matrix< float, 3, 1 > Vector3f
Defines vector.
Definition math.h:196
Eigen::Matrix< float, 4, 4, Eigen::ColMajor > Matrix4f
Defines matrix.
Definition math.h:193
Matrix4f scaling4f(float x, float y, float z)
Creates scaling matrix for homogeneous coordinates.
Definition math.h:292