1 /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
\r
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
\r
7 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
\r
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
\r
11 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
\r
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
15 #include "hacdManifoldMesh.h"
\r
16 using namespace std;
\r
21 Material::Material(void)
\r
23 m_diffuseColor.X() = 0.5;
\r
24 m_diffuseColor.Y() = 0.5;
\r
25 m_diffuseColor.Z() = 0.5;
\r
26 m_specularColor.X() = 0.5;
\r
27 m_specularColor.Y() = 0.5;
\r
28 m_specularColor.Z() = 0.5;
\r
29 m_ambientIntensity = 0.4;
\r
30 m_emissiveColor.X() = 0.0;
\r
31 m_emissiveColor.Y() = 0.0;
\r
32 m_emissiveColor.Z() = 0.0;
\r
34 m_transparency = 0.0;
\r
37 TMMVertex::TMMVertex(void)
\r
45 TMMVertex::~TMMVertex(void)
\r
48 TMMEdge::TMMEdge(void)
\r
51 m_triangles[0] = m_triangles[1] = m_newFace = 0;
\r
52 m_vertices[0] = m_vertices[1] = 0;
\r
54 TMMEdge::~TMMEdge(void)
\r
57 TMMTriangle::TMMTriangle(void)
\r
60 for(int i = 0; i < 3; i++)
\r
67 TMMTriangle::~TMMTriangle(void)
\r
70 TMMesh::TMMesh(void)
\r
72 m_barycenter = Vec3<Real>(0,0,0);
\r
75 TMMesh::~TMMesh(void)
\r
79 void TMMesh::Print()
\r
81 size_t nV = m_vertices.GetSize();
\r
82 std::cout << "-----------------------------" << std::endl;
\r
83 std::cout << "vertices (" << nV << ")" << std::endl;
\r
84 for(size_t v = 0; v < nV; v++)
\r
86 const TMMVertex & currentVertex = m_vertices.GetData();
\r
87 std::cout << currentVertex.m_id << ", "
\r
88 << currentVertex.m_pos.X() << ", "
\r
89 << currentVertex.m_pos.Y() << ", "
\r
90 << currentVertex.m_pos.Z() << std::endl;
\r
95 size_t nE = m_edges.GetSize();
\r
96 std::cout << "edges (" << nE << ")" << std::endl;
\r
97 for(size_t e = 0; e < nE; e++)
\r
99 const TMMEdge & currentEdge = m_edges.GetData();
\r
100 const CircularListElement<TMMVertex> * v0 = currentEdge.m_vertices[0];
\r
101 const CircularListElement<TMMVertex> * v1 = currentEdge.m_vertices[1];
\r
102 const CircularListElement<TMMTriangle> * f0 = currentEdge.m_triangles[0];
\r
103 const CircularListElement<TMMTriangle> * f1 = currentEdge.m_triangles[1];
\r
105 std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ")" << std::endl;
\r
106 std::cout << "-> F0 (" << f0->GetData().m_vertices[0]->GetData().m_name << ", "
\r
107 << f0->GetData().m_vertices[1]->GetData().m_name << ", "
\r
108 << f0->GetData().m_vertices[2]->GetData().m_name <<")" << std::endl;
\r
109 std::cout << "-> F1 (" << f1->GetData().m_vertices[0]->GetData().m_name << ", "
\r
110 << f1->GetData().m_vertices[1]->GetData().m_name << ", "
\r
111 << f1->GetData().m_vertices[2]->GetData().m_name << ")" << std::endl;
\r
114 size_t nT = m_triangles.GetSize();
\r
115 std::cout << "triangles (" << nT << ")" << std::endl;
\r
116 for(size_t t = 0; t < nT; t++)
\r
118 const TMMTriangle & currentTriangle = m_triangles.GetData();
\r
119 const CircularListElement<TMMVertex> * v0 = currentTriangle.m_vertices[0];
\r
120 const CircularListElement<TMMVertex> * v1 = currentTriangle.m_vertices[1];
\r
121 const CircularListElement<TMMVertex> * v2 = currentTriangle.m_vertices[2];
\r
122 const CircularListElement<TMMEdge> * e0 = currentTriangle.m_edges[0];
\r
123 const CircularListElement<TMMEdge> * e1 = currentTriangle.m_edges[1];
\r
124 const CircularListElement<TMMEdge> * e2 = currentTriangle.m_edges[2];
\r
126 std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ", "<< v2->GetData().m_name << ")" << std::endl;
\r
128 std::cout << "-> E0 (" << e0->GetData().m_vertices[0]->GetData().m_name << ", "
\r
129 << e0->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
\r
130 std::cout << "-> E1 (" << e1->GetData().m_vertices[0]->GetData().m_name << ", "
\r
131 << e1->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
\r
132 std::cout << "-> E2 (" << e2->GetData().m_vertices[0]->GetData().m_name << ", "
\r
133 << e2->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
\r
134 m_triangles.Next();
\r
137 bool TMMesh::Save(const char *fileName)
\r
139 std::ofstream fout(fileName);
\r
140 std::cout << "Saving " << fileName << std::endl;
\r
141 if (SaveVRML2(fout))
\r
148 bool TMMesh::SaveVRML2(std::ofstream &fout)
\r
150 return SaveVRML2(fout, Material());
\r
152 bool TMMesh::SaveVRML2(std::ofstream &fout, const Material & material)
\r
154 if (fout.is_open())
\r
156 size_t nV = m_vertices.GetSize();
\r
157 size_t nT = m_triangles.GetSize();
\r
158 fout <<"#VRML V2.0 utf8" << std::endl;
\r
159 fout <<"" << std::endl;
\r
160 fout <<"# Vertices: " << nV << std::endl;
\r
161 fout <<"# Triangles: " << nT << std::endl;
\r
162 fout <<"" << std::endl;
\r
163 fout <<"Group {" << std::endl;
\r
164 fout <<" children [" << std::endl;
\r
165 fout <<" Shape {" << std::endl;
\r
166 fout <<" appearance Appearance {" << std::endl;
\r
167 fout <<" material Material {" << std::endl;
\r
168 fout <<" diffuseColor " << material.m_diffuseColor.X() << " "
\r
169 << material.m_diffuseColor.Y() << " "
\r
170 << material.m_diffuseColor.Z() << std::endl;
\r
171 fout <<" ambientIntensity " << material.m_ambientIntensity << std::endl;
\r
172 fout <<" specularColor " << material.m_specularColor.X() << " "
\r
173 << material.m_specularColor.Y() << " "
\r
174 << material.m_specularColor.Z() << std::endl;
\r
175 fout <<" emissiveColor " << material.m_emissiveColor.X() << " "
\r
176 << material.m_emissiveColor.Y() << " "
\r
177 << material.m_emissiveColor.Z() << std::endl;
\r
178 fout <<" shininess " << material.m_shininess << std::endl;
\r
179 fout <<" transparency " << material.m_transparency << std::endl;
\r
180 fout <<" }" << std::endl;
\r
181 fout <<" }" << std::endl;
\r
182 fout <<" geometry IndexedFaceSet {" << std::endl;
\r
183 fout <<" ccw TRUE" << std::endl;
\r
184 fout <<" solid TRUE" << std::endl;
\r
185 fout <<" convex TRUE" << std::endl;
\r
186 if (GetNVertices() > 0) {
\r
187 fout <<" coord DEF co Coordinate {" << std::endl;
\r
188 fout <<" point [" << std::endl;
\r
189 for(size_t v = 0; v < nV; v++)
\r
191 TMMVertex & currentVertex = m_vertices.GetData();
\r
192 fout <<" " << currentVertex.m_pos.X() << " "
\r
193 << currentVertex.m_pos.Y() << " "
\r
194 << currentVertex.m_pos.Z() << "," << std::endl;
\r
195 currentVertex.m_id = v;
\r
198 fout <<" ]" << std::endl;
\r
199 fout <<" }" << std::endl;
\r
201 if (GetNTriangles() > 0) {
\r
202 fout <<" coordIndex [ " << std::endl;
\r
203 for(size_t f = 0; f < nT; f++)
\r
205 TMMTriangle & currentTriangle = m_triangles.GetData();
\r
206 fout <<" " << currentTriangle.m_vertices[0]->GetData().m_id << ", "
\r
207 << currentTriangle.m_vertices[1]->GetData().m_id << ", "
\r
208 << currentTriangle.m_vertices[2]->GetData().m_id << ", -1," << std::endl;
\r
209 m_triangles.Next();
\r
211 fout <<" ]" << std::endl;
\r
213 fout <<" }" << std::endl;
\r
214 fout <<" }" << std::endl;
\r
215 fout <<" ]" << std::endl;
\r
216 fout <<"}" << std::endl;
\r
220 void TMMesh::GetIFS(Vec3<Real> * const points, Vec3<long> * const triangles)
\r
222 size_t nV = m_vertices.GetSize();
\r
223 size_t nT = m_triangles.GetSize();
\r
225 for(size_t v = 0; v < nV; v++)
\r
227 points[v] = m_vertices.GetData().m_pos;
\r
228 m_vertices.GetData().m_id = v;
\r
231 for(size_t f = 0; f < nT; f++)
\r
233 TMMTriangle & currentTriangle = m_triangles.GetData();
\r
234 triangles[f].X() = static_cast<long>(currentTriangle.m_vertices[0]->GetData().m_id);
\r
235 triangles[f].Y() = static_cast<long>(currentTriangle.m_vertices[1]->GetData().m_id);
\r
236 triangles[f].Z() = static_cast<long>(currentTriangle.m_vertices[2]->GetData().m_id);
\r
237 m_triangles.Next();
\r
240 void TMMesh::Clear()
\r
242 m_vertices.Clear();
\r
244 m_triangles.Clear();
\r
246 void TMMesh::Copy(TMMesh & mesh)
\r
249 // updating the id's
\r
250 size_t nV = mesh.m_vertices.GetSize();
\r
251 size_t nE = mesh. m_edges.GetSize();
\r
252 size_t nT = mesh.m_triangles.GetSize();
\r
253 for(size_t v = 0; v < nV; v++)
\r
255 mesh.m_vertices.GetData().m_id = v;
\r
256 mesh.m_vertices.Next();
\r
258 for(size_t e = 0; e < nE; e++)
\r
260 mesh.m_edges.GetData().m_id = e;
\r
261 mesh.m_edges.Next();
\r
264 for(size_t f = 0; f < nT; f++)
\r
266 mesh.m_triangles.GetData().m_id = f;
\r
267 mesh.m_triangles.Next();
\r
270 m_vertices = mesh.m_vertices;
\r
271 m_edges = mesh.m_edges;
\r
272 m_triangles = mesh.m_triangles;
\r
274 // generating mapping
\r
275 CircularListElement<TMMVertex> ** vertexMap = new CircularListElement<TMMVertex> * [nV];
\r
276 CircularListElement<TMMEdge> ** edgeMap = new CircularListElement<TMMEdge> * [nE];
\r
277 CircularListElement<TMMTriangle> ** triangleMap = new CircularListElement<TMMTriangle> * [nT];
\r
278 for(size_t v = 0; v < nV; v++)
\r
280 vertexMap[v] = m_vertices.GetHead();
\r
281 m_vertices.Next();
\r
283 for(size_t e = 0; e < nE; e++)
\r
285 edgeMap[e] = m_edges.GetHead();
\r
288 for(size_t f = 0; f < nT; f++)
\r
290 triangleMap[f] = m_triangles.GetHead();
\r
291 m_triangles.Next();
\r
294 // updating pointers
\r
295 for(size_t v = 0; v < nV; v++)
\r
297 if (vertexMap[v]->GetData().m_duplicate)
\r
299 vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
\r
302 for(size_t e = 0; e < nE; e++)
\r
304 if (edgeMap[e]->GetData().m_newFace)
\r
306 edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
\r
310 for(int f = 0; f < 2; f++)
\r
312 if (edgeMap[e]->GetData().m_triangles[f])
\r
314 edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
\r
318 for(int v = 0; v < 2; v++)
\r
320 if (edgeMap[e]->GetData().m_vertices[v])
\r
322 edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
\r
326 for(size_t f = 0; f < nT; f++)
\r
330 for(int e = 0; e < 3; e++)
\r
332 if (triangleMap[f]->GetData().m_edges[e])
\r
334 triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
\r
338 for(int v = 0; v < 3; v++)
\r
340 if (triangleMap[f]->GetData().m_vertices[v])
\r
342 triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
\r
346 delete [] vertexMap;
\r
348 delete [] triangleMap;
\r
351 long IntersectRayTriangle(const Vec3<double> & P0, const Vec3<double> & dir,
\r
352 const Vec3<double> & V0, const Vec3<double> & V1,
\r
353 const Vec3<double> & V2, double &t)
\r
355 Vec3<double> edge1, edge2, edge3;
\r
356 double det, invDet;
\r
359 Vec3<double> pvec = dir ^ edge2;
\r
360 det = edge1 * pvec;
\r
364 Vec3<double> tvec = P0 - V0;
\r
365 Vec3<double> qvec = tvec ^ edge1;
\r
366 t = (edge2 * qvec) * invDet;
\r
372 Vec3<double> I(P0 + t * dir);
\r
373 Vec3<double> s0 = (I-V0) ^ edge3;
\r
374 Vec3<double> s1 = (I-V1) ^ edge1;
\r
375 Vec3<double> s2 = (I-V2) ^ edge2;
\r
376 if (s0*s1 > -1e-9 && s2*s1 > -1e-9)
\r
383 bool IntersectLineLine(const Vec3<double> & p1, const Vec3<double> & p2,
\r
384 const Vec3<double> & p3, const Vec3<double> & p4,
\r
385 Vec3<double> & pa, Vec3<double> & pb,
\r
386 double & mua, double & mub)
\r
388 Vec3<double> p13,p43,p21;
\r
389 double d1343,d4321,d1321,d4343,d2121;
\r
390 double numer,denom;
\r
392 p13.X() = p1.X() - p3.X();
\r
393 p13.Y() = p1.Y() - p3.Y();
\r
394 p13.Z() = p1.Z() - p3.Z();
\r
395 p43.X() = p4.X() - p3.X();
\r
396 p43.Y() = p4.Y() - p3.Y();
\r
397 p43.Z() = p4.Z() - p3.Z();
\r
398 if (p43.X()==0.0 && p43.Y()==0.0 && p43.Z()==0.0)
\r
400 p21.X() = p2.X() - p1.X();
\r
401 p21.Y() = p2.Y() - p1.Y();
\r
402 p21.Z() = p2.Z() - p1.Z();
\r
403 if (p21.X()==0.0 && p21.Y()==0.0 && p21.Z()==0.0)
\r
406 d1343 = p13.X() * p43.X() + p13.Y() * p43.Y() + p13.Z() * p43.Z();
\r
407 d4321 = p43.X() * p21.X() + p43.Y() * p21.Y() + p43.Z() * p21.Z();
\r
408 d1321 = p13.X() * p21.X() + p13.Y() * p21.Y() + p13.Z() * p21.Z();
\r
409 d4343 = p43.X() * p43.X() + p43.Y() * p43.Y() + p43.Z() * p43.Z();
\r
410 d2121 = p21.X() * p21.X() + p21.Y() * p21.Y() + p21.Z() * p21.Z();
\r
412 denom = d2121 * d4343 - d4321 * d4321;
\r
415 numer = d1343 * d4321 - d1321 * d4343;
\r
417 mua = numer / denom;
\r
418 mub = (d1343 + d4321 * (mua)) / d4343;
\r
420 pa.X() = p1.X() + mua * p21.X();
\r
421 pa.Y() = p1.Y() + mua * p21.Y();
\r
422 pa.Z() = p1.Z() + mua * p21.Z();
\r
423 pb.X() = p3.X() + mub * p43.X();
\r
424 pb.Y() = p3.Y() + mub * p43.Y();
\r
425 pb.Z() = p3.Z() + mub * p43.Z();
\r
430 long IntersectRayTriangle2(const Vec3<double> & P0, const Vec3<double> & dir,
\r
431 const Vec3<double> & V0, const Vec3<double> & V1,
\r
432 const Vec3<double> & V2, double &r)
\r
434 Vec3<double> u, v, n; // triangle vectors
\r
435 Vec3<double> w0, w; // ray vectors
\r
436 double a, b; // params to calc ray-plane intersect
\r
438 // get triangle edge vectors and plane normal
\r
441 n = u ^ v; // cross product
\r
442 if (n.GetNorm() == 0.0) // triangle is degenerate
\r
443 return -1; // do not deal with this case
\r
448 if (fabs(b) <= 0.0) { // ray is parallel to triangle plane
\r
449 if (a == 0.0) // ray lies in triangle plane
\r
451 else return 0; // ray disjoint from plane
\r
454 // get intersect point of ray with triangle plane
\r
456 if (r < 0.0) // ray goes away from triangle
\r
457 return 0; // => no intersect
\r
458 // for a segment, also test if (r > 1.0) => no intersect
\r
460 Vec3<double> I = P0 + r * dir; // intersect point of ray and plane
\r
463 double uu, uv, vv, wu, wv, D;
\r
470 D = uv * uv - uu * vv;
\r
472 // get and test parametric coords
\r
474 s = (uv * wv - vv * wu) / D;
\r
475 if (s < 0.0 || s > 1.0) // I is outside T
\r
477 t = (uv * wu - uu * wv) / D;
\r
478 if (t < 0.0 || (s + t) > 1.0) // I is outside T
\r
480 return 1; // I is in T
\r
484 bool TMMesh::CheckConsistancy()
\r
486 size_t nE = m_edges.GetSize();
\r
487 size_t nT = m_triangles.GetSize();
\r
488 for(size_t e = 0; e < nE; e++)
\r
490 for(int f = 0; f < 2; f++)
\r
492 if (!m_edges.GetHead()->GetData().m_triangles[f])
\r
500 for(size_t f = 0; f < nT; f++)
\r
502 for(int e = 0; e < 3; e++)
\r
505 for(int k = 0; k < 2; k++)
\r
507 if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead())
\r
517 m_triangles.Next();
\r
522 bool TMMesh::Normalize()
\r
524 size_t nV = m_vertices.GetSize();
\r
529 m_barycenter = m_vertices.GetHead()->GetData().m_pos;
\r
530 Vec3<Real> min = m_barycenter;
\r
531 Vec3<Real> max = m_barycenter;
\r
533 for(size_t v = 1; v < nV; v++)
\r
535 m_barycenter += m_vertices.GetHead()->GetData().m_pos;
\r
536 x = m_vertices.GetHead()->GetData().m_pos.X();
\r
537 y = m_vertices.GetHead()->GetData().m_pos.Y();
\r
538 z = m_vertices.GetHead()->GetData().m_pos.Z();
\r
539 if ( x < min.X()) min.X() = x;
\r
540 else if ( x > max.X()) max.X() = x;
\r
541 if ( y < min.Y()) min.Y() = y;
\r
542 else if ( y > max.Y()) max.Y() = y;
\r
543 if ( z < min.Z()) min.Z() = z;
\r
544 else if ( z > max.Z()) max.Z() = z;
\r
547 m_barycenter /= static_cast<Real>(nV);
\r
548 m_diag = static_cast<Real>(0.001 * (max-min).GetNorm());
\r
549 const Real invDiag = static_cast<Real>(1.0 / m_diag);
\r
552 for(size_t v = 0; v < nV; v++)
\r
554 m_vertices.GetHead()->GetData().m_pos = (m_vertices.GetHead()->GetData().m_pos - m_barycenter) * invDiag;
\r
560 bool TMMesh::Denormalize()
\r
562 size_t nV = m_vertices.GetSize();
\r
569 for(size_t v = 0; v < nV; v++)
\r
571 m_vertices.GetHead()->GetData().m_pos = m_vertices.GetHead()->GetData().m_pos * m_diag + m_barycenter;
\r