1 #ifndef BLUB_PROCEDURAL_VOXEL_EDIT_MESH_HPP
2 #define BLUB_PROCEDURAL_VOXEL_EDIT_MESH_HPP
4 #include "blub/log/global.hpp"
5 #include "blub/core/map.hpp"
6 #include "blub/core/pair.hpp"
7 #include "blub/core/sharedPointer.hpp"
8 #include "blub/core/vector.hpp"
9 #include "blub/math/axisAlignedBox.hpp"
10 #include "blub/math/intersection.hpp"
11 #include "blub/math/plane.hpp"
12 #include "blub/math/ray.hpp"
13 #include "blub/math/transform.hpp"
14 #include "blub/math/triangleVector3.hpp"
15 #include "blub/procedural/voxel/edit/base.hpp"
16 #include "blub/procedural/voxel/tile/container.hpp"
20 #ifdef BLUB_USE_ASSIMP
21 #include <assimp/Importer.hpp>
22 #include <assimp/postprocess.h>
23 #include <assimp/material.h>
24 #include <assimp/mesh.h>
25 #include <assimp/scene.h>
28 #include <boost/geometry.hpp>
29 #include <boost/geometry/geometries/box.hpp>
30 #include <boost/geometry/geometries/point.hpp>
31 #include <boost/geometry/geometries/polygon.hpp>
32 #include <boost/geometry/index/rtree.hpp>
49 template <
class voxelType>
50 class mesh :
public base<voxelType>
53 typedef sharedPointer<mesh<voxelType> > pointer;
55 typedef base<voxelType> t_base;
57 typedef tile::container<voxelType> t_tileContainer;
59 typedef boost::geometry::model::point<real, 3, boost::geometry::cs::cartesian> t_point;
60 typedef boost::geometry::model::box<t_point> t_box;
61 typedef boost::geometry::model::segment<t_point> t_segment;
62 typedef std::pair<t_box, triangleVector3> t_value;
63 typedef boost::geometry::index::rtree<t_value, boost::geometry::index::quadratic<16> > t_tree;
71 return pointer(
new mesh());
78 for (t_trees::const_iterator it = m_trees.cbegin(); it != m_trees.cend(); ++it)
84 #ifdef BLUB_USE_ASSIMP
92 Assimp::Importer* importer(
new Assimp::Importer());
94 const aiScene *scene = importer->ReadFile(path.c_str(), aiProcess_Triangulate);
97 BLUB_PROCEDURAL_LOG_ERROR() <<
"scene == nullptr loader->GetErrorString():" << importer->GetErrorString();
102 bool result(loadScene(*scene, trans));
114 virtual bool loadScene(
const aiScene &scene,
const blub::transform &trans)
116 if (!scene.HasMeshes())
118 BLUB_PROCEDURAL_LOG_ERROR() <<
"!scene.HasMeshes()";
122 #ifdef BLUB_LOG_PROCEDURAL_VOXEL_EDIT_MESH
123 BLUB_LOG_OUT() <<
"scene.mNumMeshes:" << scene.mNumMeshes <<
" scene.mRootNode->mNumChildren:" << scene.mRootNode->mNumChildren;
126 for(uint32 indMesh = 0; indMesh < scene.mNumMeshes; ++indMesh)
128 aiMesh *
mesh(scene.mMeshes[indMesh]);
129 loadMesh(*
mesh, trans);
141 typedef vector<vector3> t_positions;
143 #ifdef BLUB_LOG_PROCEDURAL_VOXEL_EDIT_MESH
144 BLUB_PROCEDURAL_LOG_OUT() <<
"mesh.mName:" <<
blub::string(mesh.mName.C_Str(), mesh.mName.length);
146 if (!mesh.HasFaces())
148 BLUB_PROCEDURAL_LOG_ERROR() <<
"!scene.mMeshes[indMesh]->HasFaces()";
151 if (!mesh.HasPositions())
153 BLUB_PROCEDURAL_LOG_ERROR() <<
"!mesh.HasPositions()";
157 t_tree *tree =
new t_tree();
158 m_trees.push_back(tree);
160 t_positions positions;
161 positions.resize(mesh.mNumVertices);
162 for (blub::uint32 indVertex = 0; indVertex < mesh.mNumVertices; ++indVertex)
164 const aiVector3D &posToCast(mesh.mVertices[indVertex]);
165 vector3 casted(posToCast.x, posToCast.y, posToCast.z);
166 casted *= trans.scale;
167 positions[indVertex] = casted;
168 m_aabb.
merge(casted);
170 for (blub::uint32 indFace = 0; indFace < mesh.mNumFaces; ++indFace)
172 const aiFace &faceToCast(mesh.mFaces[indFace]);
173 BASSERT(faceToCast.mNumIndices == 3);
174 if (faceToCast.mNumIndices != 3)
176 BLUB_PROCEDURAL_LOG_WARNING() <<
"faceToCast.mNumIndices != 3";
179 const triangleVector3 resultTriangle( positions[faceToCast.mIndices[0]],
180 positions[faceToCast.mIndices[1]],
181 positions[faceToCast.mIndices[2]]);
186 t_box toInsert(t_point(aabbMin.x, aabbMin.y, aabbMin.z), t_point(aabbMax.x, aabbMax.y, aabbMax.z));
187 tree->insert(std::make_pair(toInsert, resultTriangle));
190 return !tree->empty();
210 BLUB_LOG_OUT() <<
"trans:" << trans;
213 m_aabb.
getMaximum()*trans.scale + trans.position);
224 const vector3int32 posContainerAbsolut(voxelContainerOffset*t_tileContainer::voxelLength);
226 vector3int32 toLoop[] = {{1, t_tileContainer::voxelLength, t_tileContainer::voxelLength},
227 {t_tileContainer::voxelLength, 1, t_tileContainer::voxelLength},
228 {t_tileContainer::voxelLength, t_tileContainer::voxelLength, 1}
230 vector3 rayDir[] = {{1., 0., 0.},
233 for (uint32 indMesh = 0; indMesh < m_trees.size(); ++indMesh)
235 t_tree *tree(static_cast<t_tree*>(m_trees[indMesh]));
236 for (int32 indAxis = 0; indAxis < 3; ++indAxis)
238 for (int32 indX = 0; indX < toLoop[indAxis].x; ++indX)
240 for (int32 indY = 0; indY < toLoop[indAxis].y; ++indY)
242 for (int32 indZ = 0; indZ < toLoop[indAxis].z; ++indZ)
245 vector3 posAbsolut(posContainerAbsolut + posVoxel);
250 const ray test(posAbsolut, rayDir[indAxis]);
252 const vector3 segmentStart (posAbsolut+rayDir[indAxis]*(-10000.));
253 const vector3 segmentEnd (posAbsolut+rayDir[indAxis]*(+10000.));
255 t_segment segment(t_point(segmentStart.x, segmentStart.y, segmentStart.z), t_point(segmentEnd.x, segmentEnd.y, segmentEnd.z));
256 typedef std::vector<t_value> t_resultTriangles;
257 t_resultTriangles resultTriangles;
258 tree->query(boost::geometry::index::intersects(segment), std::back_inserter(resultTriangles));
262 t_cutPoints cutPoints;
264 for (t_resultTriangles::const_iterator it = resultTriangles.cbegin(); it != resultTriangles.cend(); ++it)
267 if (intersection::intersect(test, triangleWork, &cutPoint))
280 real cutPointStart = cutPoint[indAxis] -
static_cast<real
>(posContainerAbsolut[indAxis]);
281 cutPoints.push_back(t_cutPoint(cutPointStart, triangleWork.getPlane()));
285 if(cutPoints.size() < 2)
291 t_cutPointsFiltered cutPointsFiltered;
292 for (t_cutPoints::const_iterator it = cutPoints.cbegin(); it != cutPoints.cend(); ++it)
294 if (cutPointsFiltered.empty())
296 cutPointsFiltered.push_back(*it);
299 if (math::abs(cutPointsFiltered.back().first - it->first) < 1e-4f)
303 cutPointsFiltered.push_back(*it);
306 if(cutPointsFiltered.size()%2 != 0 && cutPointsFiltered.size() > 0)
308 BLUB_PROCEDURAL_LOG_WARNING() <<
"cutPointsFiltered.size()%2 != 0 cutPointsFiltered.size():" << cutPointsFiltered.size();
309 cutPointsFiltered.pop_back();
311 for (t_cutPointsFiltered::const_iterator it = cutPointsFiltered.cbegin(); it != cutPointsFiltered.cend(); ++it)
313 real cutPointsSorted[2];
315 cutPointsSorted[0] = it->first;
316 cutPlanes[0] = it->second;
318 BASSERT(it != cutPointsFiltered.cend());
319 cutPointsSorted[1] = it->first;
320 cutPlanes[1] = it->second;
322 const real length(cutPointsSorted[1]-cutPointsSorted[0]);
325 #ifdef BLUB_LOG_PROCEDURAL_VOXEL_EDIT_MESH
334 t_base::createLine(voxelContainer, posVoxel, cutPointsSorted[0], length, t_base::axis::x, cutPlanes[0], cutPlanes[1]);
337 t_base::createLine(voxelContainer, posVoxel, cutPointsSorted[0], length, t_base::axis::y, cutPlanes[0], cutPlanes[1]);
340 t_base::createLine(voxelContainer, posVoxel, cutPointsSorted[0], length, t_base::axis::z, cutPlanes[0], cutPlanes[1]);
369 #endif // BLUB_PROCEDURAL_VOXEL_EDIT_MESH_HPP
virtual void createLine(t_voxelContainerTile *voxelContainer, const vector3int32 &posVoxel, const real &from, const real &len, const axis &ax, const blub::plane &planeA, const blub::plane &planeB) const
createLine creates a voxel-line on one axis with a specific length
Definition: base.hpp:198
Definition: vector.hpp:19
Definition: triangleVector3.hpp:10
blub::axisAlignedBox getAxisAlignedBoundingBox(const transform &trans) const override
getAxisAlignedBoundingBox returns the transformed bounding box that includes the mesh.
Definition: mesh.hpp:208
virtual ~mesh()
~mesh destructor
Definition: mesh.hpp:76
void merge(const axisAlignedBox &rhs)
Definition: axisAlignedBox.hpp:284
mesh()
mesh contructor
Definition: mesh.hpp:198
Definition: string.hpp:22
static pointer create()
creates an instance of the class.
Definition: mesh.hpp:69
Definition: vector3.hpp:26
Definition: axisAlignedBox.hpp:20
const vector3 & getMinimum(void) const
Definition: axisAlignedBox.hpp:126
const vector3 & getMaximum(void) const
Definition: axisAlignedBox.hpp:141
Definition: deadlineTimer.hpp:10
void calculateVoxel(t_tileContainer *voxelContainer, const vector3int32 &voxelContainerOffset, const transform &) const
calculateVoxel The tree, which got generated in load() gets intersected for every voxel line...
Definition: mesh.hpp:222