Spinning Topp Logo BlackTopp Studios
inc
booleanmeshgenerator.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 /*
41  -----------------------------------------------------------------------------
42  This source file is part of ogre-procedural
43 
44  For the latest info, see http://code.google.com/p/ogre-procedural/
45 
46  Copyright (c) 2010-2013 Michael Broutin
47 
48  Permission is hereby granted, free of charge, to any person obtaining a copy
49  of this software and associated documentation files (the "Software"), to deal
50  in the Software without restriction, including without limitation the rights
51  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52  copies of the Software, and to permit persons to whom the Software is
53  furnished to do so, subject to the following conditions:
54 
55  The above copyright notice and this permission notice shall be included in
56  all copies or substantial portions of the Software.
57 
58  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64  THE SOFTWARE.
65  -----------------------------------------------------------------------------
66  */
67 #ifndef _graphicsproceduralbooleanmeshgenerator_cpp
68 #define _graphicsproceduralbooleanmeshgenerator_cpp
69 
70 #include "Graphics/Procedural/Mesh/booleanmeshgenerator.h"
71 
72 #include "Graphics/Procedural/triangulator.h"
73 #include "Graphics/Procedural/path.h"
74 
75 #include "MathTools/mathtools.h"
76 #include "linesegment.h"
77 #include "triangle.h"
78 #include "exception.h"
79 
80 namespace
81 {
82  // Keeps this section form being documented by doxygen
83  /// @cond DontDocumentInternal
84  /// @todo Document this anonymous namespace?
85 
86  struct Intersect
87  {
89  Mezzanine::Integer Triangle1;
90  Mezzanine::Integer Triangle2;
91 
93  Segment(seg),
94  Triangle1(tri1),
95  Triangle2(tri2)
96  { }
97  };//Intersect
98 
99  struct Seg3Comparator
100  {
101  Mezzanine::Boole operator()(const Mezzanine::LineSegment3D& One, const Mezzanine::LineSegment3D& Two) const
102  {
103  if ( One.EpsilonEquivalent(Two) )
104  return false;
105 
106  if ( One.PointA.SquaredDistance(Two.PointA) > 1e-6 )
107  return Mezzanine::Vector3LengthCompare()( One.PointA, Two.PointA );
108 
109  return Mezzanine::Vector3LengthCompare()( One.PointB, Two.PointB );
110  }
111  };//Seg3Comparator
112 
113  inline Mezzanine::Vector2 ProjectOnAxis(const Mezzanine::Vector3& Input, const Mezzanine::Vector3& Origin, const Mezzanine::Vector3& Axis1, const Mezzanine::Vector3& Axis2)
114  {
115  return Mezzanine::Vector2( (Input - Origin).DotProduct(Axis1), (Input - Origin).DotProduct(Axis2) );
116  }
117 
118  inline Mezzanine::Vector3 DeprojectOnAxis(const Mezzanine::Vector2& Input, const Mezzanine::Vector3& Origin, const Mezzanine::Vector3& Axis1, const Mezzanine::Vector3& Axis2)
119  {
120  return Origin + ( Axis1 * Input.X ) + ( Axis2 * Input.Y );
121  }
122 
123  inline Mezzanine::LineSegment2D ProjectOnAxis(const Mezzanine::LineSegment3D& Input, const Mezzanine::Vector3& Origin, const Mezzanine::Vector3& Axis1, const Mezzanine::Vector3& Axis2)
124  {
125  return Mezzanine::LineSegment2D(ProjectOnAxis(Input.PointA, Origin, Axis1, Axis2), ProjectOnAxis(Input.PointB, Origin, Axis1, Axis2));
126  }
127 
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;
140 
141  void _RemoveFromTriLookup(Mezzanine::Integer Index, TriLookup& Lookup)
142  {
143  for ( TriLookup::iterator LookupIt = Lookup.begin() ; LookupIt != Lookup.end() ; )
144  {
145  TriLookup::iterator RemoveIt = LookupIt++;
146  if( RemoveIt->second == Index )
147  Lookup.erase(RemoveIt);
148  }
149  }
150 
151  void _RecursiveAddNeighbour(TriangleBuffer& Result, const TriangleBuffer& Source, Mezzanine::Integer TriNumber, TriLookup& Lookup, const LineSeg3DSet& Limits, Mezzanine::Boole Inverted)
152  {
153  if( TriNumber == -1 )
154  return;
155  const IndexContainer& Indices = Source.GetIndices();
156  const VertexContainer& Vertices = Source.GetVertices();
157  Result.RebaseOffset();
158  if( Inverted ) {
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);
169  }else{
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 ] ] );
174  }
175 
176  TriLookup::iterator it;
177 
178  Mezzanine::Integer NextTriangle1 = -1;
179  Mezzanine::Integer NextTriangle2 = -1;
180  Mezzanine::Integer NextTriangle3 = -1;
181  it = Lookup.find( Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 1 ] ].Position ).GetOrderedCopy() );
182  //if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) != Limits.end() )
183 
184  if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
185  NextTriangle1 = it->second;
186  _RemoveFromTriLookup(NextTriangle1,Lookup);
187  }
188  it = Lookup.find( Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 + 1 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 2 ] ].Position ).GetOrderedCopy() );
189  //if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) != Limits.end() )
190 
191  if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
192  NextTriangle2 = it->second;
193  _RemoveFromTriLookup(NextTriangle2,Lookup);
194  }
195  it = Lookup.find( Mezzanine::LineSegment3D( Vertices[ Indices[ TriNumber * 3 ] ].Position, Vertices[ Indices[ TriNumber * 3 + 2 ] ].Position ).GetOrderedCopy());
196  //if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) != Limits.end() )
197  if( it != Lookup.end() && Limits.find( it->first.GetOrderedCopy() ) == Limits.end() ) {
198  NextTriangle3 = it->second;
199  _RemoveFromTriLookup(NextTriangle3,Lookup);
200  }
201 
202  _RecursiveAddNeighbour(Result,Source,NextTriangle1,Lookup,Limits,Inverted);
203  _RecursiveAddNeighbour(Result,Source,NextTriangle2,Lookup,Limits,Inverted);
204  _RecursiveAddNeighbour(Result,Source,NextTriangle3,Lookup,Limits,Inverted);
205  }
206 
207  void _Retriangulate(TriangleBuffer& NewBuff, const TriangleBuffer& InputBuff, const IntersectContainer& IntersectionList, Mezzanine::Boole First)
208  {
209  const VertexContainer& Vertices = InputBuff.GetVertices();
210  const IndexContainer& Indices = InputBuff.GetIndices();
211  // Triangulate
212  // Group intersections by triangle indice
213  LineSeg3DMap MeshIntersects;
214  for( IntersectContainer::const_iterator IntersectIt = IntersectionList.begin() ; IntersectIt != IntersectionList.end() ; ++IntersectIt )
215  {
216  LineSeg3DMap::iterator SegMapIt;
217  if( First ) {
218  SegMapIt = MeshIntersects.find( IntersectIt->Triangle1 );
219  }else{
220  SegMapIt = MeshIntersects.find( IntersectIt->Triangle2 );
221  }
222  if( SegMapIt != MeshIntersects.end() ) {
223  SegMapIt->second.push_back( IntersectIt->Segment );
224  }else{
225  LineSeg3DVec Segments;
226  Segments.push_back( IntersectIt->Segment );
227  if( First ) {
228  MeshIntersects[ IntersectIt->Triangle1 ] = Segments;
229  }else{
230  MeshIntersects[ IntersectIt->Triangle2 ] = Segments;
231  }
232  }
233  }
234  // Build a new TriangleBuffer holding non-intersected triangles and retriangulated-intersected triangles
235  for( VertexContainer::const_iterator it = Vertices.begin() ; it != Vertices.end() ; ++it )
236  { NewBuff.AddVertex(*it); }
237  for( Mezzanine::Integer i = 0 ; i < (Mezzanine::Integer)Indices.size() / 3 ; i++ )
238  {
239  if( MeshIntersects.find(i) == MeshIntersects.end() ) {
240  NewBuff.AddTriangle( Indices[i * 3], Indices[i * 3 + 1], Indices[i * 3 + 2] );
241  }
242  }
243  //Mezzanine::Integer numNonIntersected1 = NewBuff.GetIndices().size();
244  for( LineSeg3DMap::iterator SegMapIt = MeshIntersects.begin() ; SegMapIt != MeshIntersects.end() ; ++SegMapIt )
245  {
246  LineSeg3DVec& Segments = SegMapIt->second;
247  Mezzanine::Integer TriIndex = SegMapIt->first;
248  Mezzanine::Vector3 v1 = Vertices[ Indices[ TriIndex * 3 ] ].Position;
249  Mezzanine::Vector3 v2 = Vertices[ Indices[ TriIndex * 3 + 1 ] ].Position;
250  Mezzanine::Vector3 v3 = Vertices[ Indices[ TriIndex * 3 + 2 ] ].Position;
251  Mezzanine::Vector3 TriNormal = ( ( v2 - v1 ).CrossProduct( v3 - v1 ) ).GetNormal();
252  Mezzanine::Vector3 xAxis = TriNormal.Perpendicular();
253  Mezzanine::Vector3 yAxis = TriNormal.CrossProduct(xAxis);
254  Mezzanine::Vector3 PlaneOrigin = Vertices[ Indices[ TriIndex * 3 ] ].Position;
255 
256  // Project intersection segments onto triangle plane
257  LineSeg2DVec Segments2;
258 
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() ; )
262  {
263  if( ( SegVec2It->PointA - SegVec2It->PointB ).SquaredLength() < 1e-5 ) {
264  SegVec2It = Segments2.erase(SegVec2It);
265  }else{
266  SegVec2It++;
267  }
268  }
269 
270  // Triangulate
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;
277  Triangulate.SetManualSuperTriangle(&Tri).SetRemoveOutside(false).SetSegmentListToTriangulate(&Segments2).Triangulate(outIndice, outPointList);
278 
279  // Deproject and add to triangleBuffer
280  NewBuff.RebaseOffset();
281  for( IndexContainer::iterator IndexIt = outIndice.begin() ; IndexIt != outIndice.end() ; ++IndexIt )
282  { NewBuff.AddIndex(*IndexIt); }
283 
284  Mezzanine::Real x1 = Tri.PointA.X;
285  Mezzanine::Real y1 = Tri.PointA.Y;
286  Mezzanine::Vector2 uv1 = Vertices[ Indices[ TriIndex * 3 ] ].UV;
287  Mezzanine::Real x2 = Tri.PointB.X;
288  Mezzanine::Real y2 = Tri.PointB.Y;
289  Mezzanine::Vector2 uv2 = Vertices[ Indices[ TriIndex * 3 + 1 ] ].UV;
290  Mezzanine::Real x3 = Tri.PointC.X;
291  Mezzanine::Real y3 = Tri.PointC.Y;
292  Mezzanine::Vector2 uv3 = Vertices[ Indices[ TriIndex * 3 + 2 ] ].UV;
293  Mezzanine::Real DET = x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3;
294  Mezzanine::Vector2 A = ( uv1 * (y2 - y3) + uv2 * (y3 - y1) + uv3 * (y1 - y2) ) / DET;
295  Mezzanine::Vector2 B = ( uv1 * (x3 - x2) + uv2 * (x1 - x3) + uv3 * (x2 - x1) ) / DET;
296  Mezzanine::Vector2 C = ( uv1 * (x2 * y3 - x3 * y2) + uv2 * (x3 * y1 - x1 * y3) + uv3 * (x1 * y2 - x2 * y1) ) / DET;
297 
298  for( std::vector<Mezzanine::Vector2>::iterator PointIt = outPointList.begin() ; PointIt != outPointList.end() ; ++PointIt )
299  {
300  Mezzanine::Vector2 uv = A * PointIt->X + B * PointIt->Y + C;
301  NewBuff.AddVertex(DeprojectOnAxis(*PointIt, PlaneOrigin, xAxis, yAxis),
302  TriNormal,
303  uv);
304  }
305  }
306  }
307 
308  typedef std::multimap<Mezzanine::LineSegment3D,Mezzanine::Integer,Seg3Comparator> TriLookup;
309  typedef std::pair<Mezzanine::LineSegment3D,Mezzanine::Integer> TriLookupPair;
310 
311  void _BuildTriLookup(TriLookup& Lookup, const TriangleBuffer& NewMesh)
312  {
313  const std::vector<Mezzanine::Graphics::Procedural::Vertex>& Verts = NewMesh.GetVertices();
314  const Mezzanine::Graphics::Procedural::IndexContainer& Inds = NewMesh.GetIndices();
315  for( Mezzanine::Integer Index = 0 ; Index < (Mezzanine::Integer)Inds.size() / 3 ; ++Index )
316  {
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 ) );
320  }
321  }
322 
323  /// @endcond
324 }
325 
326 namespace Mezzanine
327 {
328  namespace Graphics
329  {
330  namespace Procedural
331  {
333  BoolOp(Procedural::BO_Union),
334  FirstBuffer(NULL),
335  SecondBuffer(NULL)
336  { }
337 
339  BoolOp(Op),
340  FirstBuffer(NULL),
341  SecondBuffer(NULL)
342  { }
343 
344  BooleanGenerator::BooleanGenerator(TriangleBuffer* First, TriangleBuffer* Second, const BooleanOperation Op) :
345  BoolOp(Op),
346  FirstBuffer(First),
347  SecondBuffer(Second)
348  { }
349 
351  { }
352 
353  ///////////////////////////////////////////////////////////////////////////////
354  // Utility
355 
356  void BooleanGenerator::AddToTriangleBuffer(TriangleBuffer& Buffer) const
357  {
358  const VertexContainer& Vertices1 = this->FirstBuffer->GetVertices();
359  const IndexContainer& Indexes1 = this->FirstBuffer->GetIndices();
360  const VertexContainer& Vertices2 = this->SecondBuffer->GetVertices();
361  const IndexContainer& Indexes2 = this->SecondBuffer->GetIndices();
362 
363  LineSegment3D IntersectionResult;
364  IntersectContainer IntersectionList;
365 
366  // Find all intersections between FirstBuffer and SecondBuffer
367  Integer FirstIndex = 0;
368  for( IndexContainer::const_iterator FirstBufferIt = Indexes1.begin() ; FirstBufferIt != Indexes1.end() ; FirstIndex++ )
369  {
370  Triangle3D Tri1( Vertices1[ *FirstBufferIt++ ].Position, Vertices1[ *FirstBufferIt++ ].Position, Vertices1[ *FirstBufferIt++ ].Position );
371 
372  Integer SecondIndex = 0;
373  for( IndexContainer::const_iterator SecondBufferIt = Indexes2.begin() ; SecondBufferIt != Indexes2.end() ; SecondIndex++ )
374  {
375  Triangle3D Tri2( Vertices2[ *SecondBufferIt++ ].Position, Vertices2[ *SecondBufferIt++ ].Position, Vertices2[ *SecondBufferIt++ ].Position );
376 
377  IntersectionResult = Tri1.GetOverlap(Tri2);
378  if( IntersectionResult.PointA != IntersectionResult.PointB ) {
379  Intersect Inter(IntersectionResult,FirstIndex,SecondIndex);
380  IntersectionList.push_back(Inter);
381  }
382  }
383  }
384  // Remove all intersection segments too small to be relevant
385  for( IntersectContainer::iterator InterIt = IntersectionList.begin() ; InterIt != IntersectionList.end() ; )
386  {
387  if( ( InterIt->Segment.PointB - InterIt->Segment.PointA ).SquaredLength() < 1e-8 ) {
388  InterIt = IntersectionList.erase(InterIt);
389  }else{
390  ++InterIt;
391  }
392  }
393 
394  // Retriangulate
395  TriangleBuffer NewMesh1, NewMesh2;
396  _Retriangulate(NewMesh1,*(this->FirstBuffer),IntersectionList,true);
397  _Retriangulate(NewMesh2,*(this->SecondBuffer),IntersectionList,false);
398 
399  //Buffer.append(NewMesh1);
400  //Buffer.append(NewMesh2);
401  //return;
402 
403  // Trace contours
404  PathContainer Contours;
405  LineSeg3DVec SegmentSoup;
406  for( IntersectContainer::iterator InterIt = IntersectionList.begin() ; InterIt != IntersectionList.end() ; ++InterIt )
407  { SegmentSoup.push_back( InterIt->Segment ); }
408  Path::BuildFromSegmentSoup(SegmentSoup,Contours);
409 
410  // Build a lookup from segment to triangle
411  TriLookup TriLookup1, TriLookup2;
412  _BuildTriLookup( TriLookup1, NewMesh1 );
413  _BuildTriLookup( TriLookup2, NewMesh2 );
414 
415  LineSeg3DSet Limits;
416  for( LineSeg3DVec::iterator SegSoupIt = SegmentSoup.begin() ; SegSoupIt != SegmentSoup.end() ; ++SegSoupIt )
417  { Limits.insert( SegSoupIt->GetOrderedCopy() ); }
418  // Build resulting mesh
419  for( PathContainer::iterator PathIt = Contours.begin() ; PathIt != Contours.end() ; ++PathIt )
420  {
421  // Find 2 seed triangles for each contour
422  LineSegment3D FirstSeg( PathIt->GetPoint(0), PathIt->GetPoint(1) );
423 
424  TriLookupRange It2mesh1 = TriLookup1.equal_range( FirstSeg.GetOrderedCopy() );
425  TriLookupRange It2mesh2 = TriLookup2.equal_range( FirstSeg.GetOrderedCopy() );
426  Integer Mesh1Seed1, Mesh1Seed2, Mesh2Seed1, Mesh2Seed2;
427 
428  if( It2mesh1.first != TriLookup1.end() && It2mesh2.first != TriLookup2.end() ) {
429  // check which of seed1 and seed2 must be included (it can be 0, 1 or both)
430  Mesh1Seed1 = It2mesh1.first->second;
431  Mesh1Seed2 = (--It2mesh1.second)->second;
432  Mesh2Seed1 = It2mesh2.first->second;
433  Mesh2Seed2 = (--It2mesh2.second)->second;
434  if( Mesh1Seed1 == Mesh1Seed2 ) {
435  Mesh1Seed2 = -1;
436  }
437  if( Mesh2Seed1 == Mesh2Seed2 ) {
438  Mesh2Seed2 = -1;
439  }
440 
441  Vector3 vMesh1, nMesh1, vMesh2, nMesh2;
442  for( Integer i = 0 ; i < 3 ; i++ )
443  {
444  const Vector3& Position = NewMesh1.GetVertices()[ NewMesh1.GetIndices()[ Mesh1Seed1 * 3 + i ] ].Position;
445  if( Position.SquaredDistance( FirstSeg.PointA ) > 1e-6 && Position.SquaredDistance( FirstSeg.PointB ) > 1e-6 ) {
446  vMesh1 = Position;
447  nMesh1 = NewMesh1.GetVertices()[ NewMesh1.GetIndices()[ Mesh1Seed1 * 3 + i ] ].Normal;
448  break;
449  }
450  }
451 
452  for( Integer i = 0 ; i < 3 ; i++ )
453  {
454  const Vector3& Position = NewMesh2.GetVertices()[ NewMesh2.GetIndices()[ Mesh2Seed1 * 3 + i ] ].Position;
455  if( Position.SquaredDistance( FirstSeg.PointA ) > 1e-6 && Position.SquaredDistance( FirstSeg.PointB ) > 1e-6 ) {
456  vMesh2 = Position;
457  nMesh2 = NewMesh2.GetVertices()[ NewMesh2.GetIndices()[ Mesh2Seed1 * 3 + i ] ].Normal;
458  break;
459  }
460  }
461 
462  Boole M2S1InsideM1 = ( nMesh1.DotProduct( vMesh2 - FirstSeg.PointA ) < 0 );
463  Boole M1S1InsideM2 = ( nMesh2.DotProduct( vMesh1 - FirstSeg.PointA ) < 0 );
464 
465  _RemoveFromTriLookup( Mesh1Seed1, TriLookup1 );
466  _RemoveFromTriLookup( Mesh2Seed1, TriLookup2 );
467  _RemoveFromTriLookup( Mesh1Seed2, TriLookup1 );
468  _RemoveFromTriLookup( Mesh2Seed2, TriLookup2 );
469 
470  // Recursively add all neighbours of these triangles
471  // Stop when a contour is touched
472  switch( this->BoolOp )
473  {
474  case BO_Union:
475  {
476  if( M1S1InsideM2 ) {
477  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,false);
478  }else{
479  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,false);
480  }
481  if( M2S1InsideM1 ) {
482  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,false);
483  }else{
484  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,false);
485  }
486  break;
487  }
488  case BO_Intersection:
489  {
490  if( M1S1InsideM2 ) {
491  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,false);
492  }else{
493  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,false);
494  }
495  if( M2S1InsideM1 ) {
496  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,false);
497  }else{
498  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,false);
499  }
500  break;
501  }
502  case BO_Difference:
503  {
504  if( M1S1InsideM2 ) {
505  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed2,TriLookup1,Limits,false);
506  }else{
507  _RecursiveAddNeighbour(Buffer,NewMesh1,Mesh1Seed1,TriLookup1,Limits,false);
508  }
509  if( M2S1InsideM1 ) {
510  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed1,TriLookup2,Limits,true);
511  }else{
512  _RecursiveAddNeighbour(Buffer,NewMesh2,Mesh2Seed2,TriLookup2,Limits,true);
513  }
514  break;
515  }
516  }
517  }
518  }
519  }
520 
521  ///////////////////////////////////////////////////////////////////////////////
522  // Configuration
523 
525  {
526  this->FirstBuffer = First;
527  return *this;
528  }
529 
531  {
532  this->SecondBuffer = Second;
533  return *this;
534  }
535 
537  {
538  this->BoolOp = Op;
539  return *this;
540  }
541  }//Procedural
542  }//Graphics
543 }//Mezzanine
544 
545 #endif
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.
Definition: vector3.cpp:414
Vector3 CrossProduct(const Vector3 &Vec) const
This is used to calculate the crossproduct of this and another vector.
Definition: vector3.cpp:338
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
Boole EpsilonEquivalent(const LineSegment3D &Other) const
Equality comparison with some slack.
Definition: linesegment.cpp:95
A geometry math class for expressing a triangle in 2D space.
Definition: triangle.h:53
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.
Definition: path.cpp:105
int Integer
A datatype used to represent any integer close to.
Definition: datatypes.h:154
A simple definition for a Vertex to be used when procedurally generating meshes.
LineSegment3D GetOverlap(const Triangle3D &Other) const
Gets the overlap of two triangles.
Definition: triangle.cpp:177
A compare fuctor that uses vector length.
Definition: vector3.h:524
This implements the exception hiearchy for Mezzanine.
VertexContainer & GetVertices()
Gets a modifiable reference to Vertices.
BooleanGenerator & SetSecondBuffer(TriangleBuffer *Second)
Sets the second buffers to operate on.
float Real
A Datatype used to represent a real floating point number.
Definition: datatypes.h:141
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.
Definition: vector3.cpp:454
A geometry math class for expressing a line connecting 2 points in 3D space.
Definition: linesegment.h:94
Vector3 PointB
The second point defining the segment.
Definition: linesegment.h:103
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.
Definition: vector2.h:69
A generator class for performing boolean operations on two buffers.
Completely merges the the two buffers.
Real X
Coordinate on the X vector.
Definition: vector2.h:67
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.
Definition: vector2.h:63
Vector3 PointA
The first point defining the segment.
Definition: linesegment.h:101
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.
Definition: path.h:84
A geometry math class for expressing a triangle in 3D space.
Definition: triangle.h:96
A generator class that implements the Delaunay Triangulation algorithm.
Definition: triangulator.h:252
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.
Definition: vector3.cpp:347
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.
Definition: vector3.h:77
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
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.
Definition: linesegment.h:52
BooleanGenerator & SetBooleanOperation(const BooleanOperation Op)
Sets the boolean operation to be performed.