67 #ifndef _graphicsproceduralbooleanmeshgenerator_cpp
68 #define _graphicsproceduralbooleanmeshgenerator_cpp
70 #include "Graphics/Procedural/Mesh/booleanmeshgenerator.h"
72 #include "Graphics/Procedural/triangulator.h"
73 #include "Graphics/Procedural/path.h"
75 #include "MathTools/mathtools.h"
76 #include "linesegment.h"
115 return Mezzanine::Vector2( (Input - Origin).DotProduct(Axis1), (Input - Origin).DotProduct(Axis2) );
120 return Origin + ( Axis1 * Input.
X ) + ( Axis2 * Input.
Y );
135 typedef std::multimap<Mezzanine::LineSegment3D,Mezzanine::Integer,Seg3Comparator> TriLookup;
136 typedef std::pair<TriLookup::iterator,TriLookup::iterator> TriLookupRange;
137 typedef std::set<Mezzanine::LineSegment3D,Seg3Comparator> LineSeg3DSet;
138 typedef std::map<Mezzanine::Integer,LineSeg3DVec> LineSeg3DMap;
139 typedef std::vector<Intersect> IntersectContainer;
143 for ( TriLookup::iterator LookupIt = Lookup.begin() ; LookupIt != Lookup.end() ; )
145 TriLookup::iterator RemoveIt = LookupIt++;
146 if( RemoveIt->second == Index )
147 Lookup.erase(RemoveIt);
151 void _RecursiveAddNeighbour(TriangleBuffer& Result,
const TriangleBuffer& Source,
Mezzanine::Integer TriNumber, TriLookup& Lookup,
const LineSeg3DSet& Limits,
Mezzanine::Boole Inverted)
153 if( TriNumber == -1 )
155 const IndexContainer& Indices = Source.GetIndices();
156 const VertexContainer& Vertices = Source.GetVertices();
157 Result.RebaseOffset();
159 Result.AddTriangle(0, 2, 1);
160 Vertex Vert = Vertices[ Indices[ TriNumber * 3 ] ];
161 Vert.Normal = -Vert.Normal;
162 Result.AddVertex(Vert);
163 Vert = Vertices[ Indices[ TriNumber * 3 + 1 ] ];
164 Vert.Normal = -Vert.Normal;
165 Result.AddVertex(Vert);
166 Vert = Vertices[ Indices[ TriNumber * 3 + 2 ] ];
167 Vert.Normal = -Vert.Normal;
168 Result.AddVertex(Vert);
170 Result.AddTriangle(0, 1, 2);
171 Result.AddVertex( Vertices[ Indices[ TriNumber * 3 ] ] );
172 Result.AddVertex( Vertices[ Indices[ TriNumber * 3 + 1 ] ] );
173 Result.AddVertex( Vertices[ Indices[ TriNumber * 3 + 2 ] ] );
176 TriLookup::iterator it;
181 it = Lookup.find(
Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 1 ] ].Position ).GetOrderedCopy() );
184 if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
185 NextTriangle1 = it->second;
186 _RemoveFromTriLookup(NextTriangle1,Lookup);
188 it = Lookup.find(
Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 + 1 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 2 ] ].Position ).GetOrderedCopy() );
191 if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
192 NextTriangle2 = it->second;
193 _RemoveFromTriLookup(NextTriangle2,Lookup);
195 it = Lookup.find(
Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 2 ] ].Position ).GetOrderedCopy());
197 if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
198 NextTriangle3 = it->second;
199 _RemoveFromTriLookup(NextTriangle3,Lookup);
202 _RecursiveAddNeighbour(Result,Source,NextTriangle1,Lookup,Limits,Inverted);
203 _RecursiveAddNeighbour(Result,Source,NextTriangle2,Lookup,Limits,Inverted);
204 _RecursiveAddNeighbour(Result,Source,NextTriangle3,Lookup,Limits,Inverted);
207 void _Retriangulate(TriangleBuffer& NewBuff,
const TriangleBuffer& InputBuff,
const IntersectContainer& IntersectionList,
Mezzanine::Boole First)
209 const VertexContainer& Vertices = InputBuff.GetVertices();
210 const IndexContainer& Indices = InputBuff.GetIndices();
213 LineSeg3DMap MeshIntersects;
214 for( IntersectContainer::const_iterator IntersectIt = IntersectionList.begin() ; IntersectIt != IntersectionList.end() ; ++IntersectIt )
216 LineSeg3DMap::iterator SegMapIt;
218 SegMapIt = MeshIntersects.find( IntersectIt->Triangle1 );
220 SegMapIt = MeshIntersects.find( IntersectIt->Triangle2 );
222 if( SegMapIt != MeshIntersects.end() ) {
223 SegMapIt->second.push_back( IntersectIt->Segment );
225 LineSeg3DVec Segments;
226 Segments.push_back( IntersectIt->Segment );
228 MeshIntersects[ IntersectIt->Triangle1 ] = Segments;
230 MeshIntersects[ IntersectIt->Triangle2 ] = Segments;
235 for( VertexContainer::const_iterator it = Vertices.begin() ; it != Vertices.end() ; ++it )
236 { NewBuff.AddVertex(*it); }
239 if( MeshIntersects.find(i) == MeshIntersects.end() ) {
240 NewBuff.AddTriangle( Indices[i * 3], Indices[i * 3 + 1], Indices[i * 3 + 2] );
244 for( LineSeg3DMap::iterator SegMapIt = MeshIntersects.begin() ; SegMapIt != MeshIntersects.end() ; ++SegMapIt )
246 LineSeg3DVec& Segments = SegMapIt->second;
257 LineSeg2DVec Segments2;
259 for( LineSeg3DVec::iterator SegVec1It = Segments.begin() ; SegVec1It != Segments.end() ; SegVec1It++ )
260 { Segments2.push_back( ProjectOnAxis(*SegVec1It, PlaneOrigin, xAxis, yAxis) ); }
261 for( LineSeg2DVec::iterator SegVec2It = Segments2.begin() ; SegVec2It != Segments2.end() ; )
263 if( ( SegVec2It->PointA - SegVec2It->PointB ).SquaredLength() < 1e-5 ) {
264 SegVec2It = Segments2.erase(SegVec2It);
272 Mezzanine::Triangle2D Tri(ProjectOnAxis( Vertices[ Indices[ TriIndex * 3] ].Position, PlaneOrigin, xAxis, yAxis),
273 ProjectOnAxis( Vertices[ Indices[ TriIndex * 3 + 1] ].Position, PlaneOrigin, xAxis, yAxis),
274 ProjectOnAxis( Vertices[ Indices[ TriIndex * 3 + 2] ].Position, PlaneOrigin, xAxis, yAxis));
276 IndexContainer outIndice;
280 NewBuff.RebaseOffset();
281 for( IndexContainer::iterator IndexIt = outIndice.begin() ; IndexIt != outIndice.end() ; ++IndexIt )
282 { NewBuff.AddIndex(*IndexIt); }
293 Mezzanine::Real DET = x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3;
296 Mezzanine::Vector2 C = ( uv1 * (x2 * y3 - x3 * y2) + uv2 * (x3 * y1 - x1 * y3) + uv3 * (x1 * y2 - x2 * y1) ) / DET;
298 for( std::vector<Mezzanine::Vector2>::iterator PointIt = outPointList.begin() ; PointIt != outPointList.end() ; ++PointIt )
301 NewBuff.AddVertex(DeprojectOnAxis(*PointIt, PlaneOrigin, xAxis, yAxis),
308 typedef std::multimap<Mezzanine::LineSegment3D,Mezzanine::Integer,Seg3Comparator> TriLookup;
309 typedef std::pair<Mezzanine::LineSegment3D,Mezzanine::Integer> TriLookupPair;
311 void _BuildTriLookup(TriLookup& Lookup,
const TriangleBuffer& NewMesh)
313 const std::vector<Mezzanine::Graphics::Procedural::Vertex>& Verts = NewMesh.GetVertices();
317 Lookup.insert( TriLookupPair(
Mezzanine::LineSegment3D( Verts[ Inds[ Index * 3 ] ].Position, Verts[ Inds[ Index * 3 + 1 ] ].Position ).GetOrderedCopy(), Index ) );
318 Lookup.insert( TriLookupPair(
Mezzanine::LineSegment3D( Verts[ Inds[ Index * 3 ] ].Position, Verts[ Inds[ Index * 3 + 2 ] ].Position ).GetOrderedCopy(), Index ) );
319 Lookup.insert( TriLookupPair(
Mezzanine::LineSegment3D( Verts[ Inds[ Index * 3 + 1 ] ].Position, Verts[ Inds[ Index * 3 + 2 ] ].Position ).GetOrderedCopy(), Index ) );
364 IntersectContainer IntersectionList;
368 for( IndexContainer::const_iterator FirstBufferIt = Indexes1.begin() ; FirstBufferIt != Indexes1.end() ; FirstIndex++ )
370 Triangle3D Tri1( Vertices1[ *FirstBufferIt++ ].Position, Vertices1[ *FirstBufferIt++ ].Position, Vertices1[ *FirstBufferIt++ ].Position );
373 for( IndexContainer::const_iterator SecondBufferIt = Indexes2.begin() ; SecondBufferIt != Indexes2.end() ; SecondIndex++ )
375 Triangle3D Tri2( Vertices2[ *SecondBufferIt++ ].Position, Vertices2[ *SecondBufferIt++ ].Position, Vertices2[ *SecondBufferIt++ ].Position );
378 if( IntersectionResult.
PointA != IntersectionResult.
PointB ) {
379 Intersect Inter(IntersectionResult,FirstIndex,SecondIndex);
380 IntersectionList.push_back(Inter);
385 for( IntersectContainer::iterator InterIt = IntersectionList.begin() ; InterIt != IntersectionList.end() ; )
387 if( ( InterIt->Segment.PointB - InterIt->Segment.PointA ).SquaredLength() < 1e-8 ) {
388 InterIt = IntersectionList.erase(InterIt);
395 TriangleBuffer NewMesh1, NewMesh2;
396 _Retriangulate(NewMesh1,*(this->
FirstBuffer),IntersectionList,
true);
397 _Retriangulate(NewMesh2,*(this->
SecondBuffer),IntersectionList,
false);
404 PathContainer Contours;
405 LineSeg3DVec SegmentSoup;
406 for( IntersectContainer::iterator InterIt = IntersectionList.begin() ; InterIt != IntersectionList.end() ; ++InterIt )
407 { SegmentSoup.push_back( InterIt->Segment ); }
411 TriLookup TriLookup1, TriLookup2;
412 _BuildTriLookup( TriLookup1, NewMesh1 );
413 _BuildTriLookup( TriLookup2, NewMesh2 );
416 for( LineSeg3DVec::iterator SegSoupIt = SegmentSoup.begin() ; SegSoupIt != SegmentSoup.end() ; ++SegSoupIt )
417 { Limits.insert( SegSoupIt->GetOrderedCopy() ); }
419 for( PathContainer::iterator PathIt = Contours.begin() ; PathIt != Contours.end() ; ++PathIt )
422 LineSegment3D FirstSeg( PathIt->GetPoint(0), PathIt->GetPoint(1) );
424 TriLookupRange It2mesh1 = TriLookup1.equal_range( FirstSeg.GetOrderedCopy() );
425 TriLookupRange It2mesh2 = TriLookup2.equal_range( FirstSeg.GetOrderedCopy() );
426 Integer Mesh1Seed1, Mesh1Seed2, Mesh2Seed1, Mesh2Seed2;
428 if( It2mesh1.first != TriLookup1.end() && It2mesh2.first != TriLookup2.end() ) {
430 Mesh1Seed1 = It2mesh1.first->second;
431 Mesh1Seed2 = (--It2mesh1.second)->second;
432 Mesh2Seed1 = It2mesh2.first->second;
433 Mesh2Seed2 = (--It2mesh2.second)->second;
434 if( Mesh1Seed1 == Mesh1Seed2 ) {
437 if( Mesh2Seed1 == Mesh2Seed2 ) {
441 Vector3 vMesh1, nMesh1, vMesh2, nMesh2;
442 for(
Integer i = 0 ; i < 3 ; i++ )
452 for(
Integer i = 0 ; i < 3 ; i++ )
462 Boole M2S1InsideM1 = ( nMesh1.
DotProduct( vMesh2 - FirstSeg.PointA ) < 0 );
463 Boole M1S1InsideM2 = ( nMesh2.
DotProduct( vMesh1 - FirstSeg.PointA ) < 0 );
465 _RemoveFromTriLookup( Mesh1Seed1, TriLookup1 );
466 _RemoveFromTriLookup( Mesh2Seed1, TriLookup2 );
467 _RemoveFromTriLookup( Mesh1Seed2, TriLookup1 );
468 _RemoveFromTriLookup( Mesh2Seed2, TriLookup2 );
477 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,
false);
479 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,
false);
482 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,
false);
484 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,
false);
491 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,
false);
493 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,
false);
496 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,
false);
498 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,
false);
505 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,
false);
507 _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,
false);
510 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,
true);
512 _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,
true);
std::vector< Vertex > VertexContainer
Basic container type for Vertex storage.
Triangulator & SetManualSuperTriangle(Triangle2D *Tri)
Sets manual super triangle.
BooleanOperation BoolOp
The operation to be performed on the two buffers.
IndexContainer & GetIndices()
Gets a modifiable reference to Indices.
std::vector< LineSegment2D > LineSeg2DVec
Basic container type for the storage of 2D line segments.
Vector3 Perpendicular() const
Gets a vector that is perpendicular to this one.
Vector3 CrossProduct(const Vector3 &Vec) const
This is used to calculate the crossproduct of this and another vector.
bool Boole
Generally acts a single bit, true or false.
Boole EpsilonEquivalent(const LineSegment3D &Other) const
Equality comparison with some slack.
A geometry math class for expressing a triangle in 2D space.
TriangleBuffer * FirstBuffer
The first of the two buffers to operate on.
A convenience buffer that stores vertices and indices of a mesh to be generated.
static void BuildFromSegmentSoup(const LineSeg3DVec &Segments, PathContainer &GeneratedPaths)
Generates one or more paths from a series of segments.
int Integer
A datatype used to represent any integer close to.
A simple definition for a Vertex to be used when procedurally generating meshes.
virtual ~BooleanGenerator()
Class destructor.
LineSegment3D GetOverlap(const Triangle3D &Other) const
Gets the overlap of two triangles.
A compare fuctor that uses vector length.
This implements the exception hiearchy for Mezzanine.
VertexContainer & GetVertices()
Gets a modifiable reference to Vertices.
BooleanGenerator()
Blank constructor.
BooleanGenerator & SetSecondBuffer(TriangleBuffer *Second)
Sets the second buffers to operate on.
float Real
A Datatype used to represent a real floating point number.
BooleanGenerator & SetFirstBuffer(TriangleBuffer *First)
Sets the first buffers to operate on.
Real SquaredDistance(const Vector3 &OtherVec) const
Gets the squared distance between this and another vector.
A geometry math class for expressing a line connecting 2 points in 3D space.
Vector3 PointB
The second point defining the segment.
std::vector< Integer > IndexContainer
A container of Integers used to represent the indicies of a shape.
std::vector< Vector2 > Point2DContainer
Basic container type for the storage of 2D points.
Real Y
Coordinate on the Y vector.
A generator class for performing boolean operations on two buffers.
Completely merges the the two buffers.
Vector3 Position
Position to apply to the mesh.
Real X
Coordinate on the X vector.
TriangleBuffer * SecondBuffer
The second of the two buffers to operate on.
This is used to represent a point on a 2 dimentional area, such as a screen.
Vector3 PointA
The first point defining the segment.
virtual void AddToTriangleBuffer(TriangleBuffer &Buffer) const
Adds the vertices and indices as configured in this generator to a triangle buffer.
std::vector< Path > PathContainer
Basic container type for the storage of Paths.
A geometry math class for expressing a triangle in 3D space.
A generator class that implements the Delaunay Triangulation algorithm.
BooleanOperation
An enum used to describe which boolean operation to take when processing two triangle buffers...
Gets only the parts of the two buffers that aren't overlapping.
Gets only the parts of the two buffers that are overlapping.
Triangulator & SetRemoveOutside(const Boole Remove)
Sets if the outside of the shape must be removed.
Real DotProduct(const Vector3 &Vec) const
This is used to calculate the dotproduct of this and another vector.
void Triangulate(IndexContainer &Indexes, Point2DContainer &Vertices) const
Executes the Constrained Delaunay Triangulation algorithm. INVALID_STATE_EXCEPTION will be thrown if ...
This is used to represent a point in space, or a vector through space.
The bulk of the engine components go in this namspace.
Triangulator & SetSegmentListToTriangulate(SegmentContainer *Segments)
Sets segment list to triangulate.
std::vector< LineSegment3D > LineSeg3DVec
Basic container type for the storage of 3D line segments.
A geometry math class for expressing a line connecting 2 points in 2D space.
BooleanGenerator & SetBooleanOperation(const BooleanOperation Op)
Sets the boolean operation to be performed.