221 typename TTriangles::const_iterator triangle;
222 for (triangle = triangles_.begin(); triangle != triangles_.end(); ++triangle)
224 TIndexTriangle indexTriangle;
225 for (std::size_t k = 0; k < 3; ++k)
227 LASS_ASSERT(triangle->vertices[k]);
228 indexTriangle.vertices[k] =
static_cast<size_t>(triangle->vertices[k] - &vertices_.front());
229 indexTriangle.normals[k] = triangle->normals[k] ?
static_cast<size_t>(triangle->normals[k] - &normals_.front()) : IndexTriangle::null();
230 indexTriangle.uvs[k] = triangle->uvs[k] ?
static_cast<size_t>(triangle->uvs[k] - &uvs_.front()) : IndexTriangle::null();
232 *triangles++ = indexTriangle;
239template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
240const typename TriangleMesh3D<T, BHV, SH>::TAabb
241TriangleMesh3D<T, BHV, SH>::aabb()
const
243 LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
249template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
250const typename TriangleMesh3D<T, BHV, SH>::TValue
251TriangleMesh3D<T, BHV, SH>::area()
const
254 typename TTriangles::const_iterator triangle;
255 for (triangle = triangles_.begin(); triangle != triangles_.end(); ++triangle)
257 result += triangle->area();
264 template <
typename HalfEdgeType>
265 typename HalfEdgeType::TVector computeWeightedNormal(
const HalfEdgeType& edge)
267 typedef typename HalfEdgeType::TVector TVector;
268 const TVector a = edge.vector();
269 const TVector b = -edge.oPrev().vector();
270 const TVector n = cross(a, b);
271 if (n.isZero() || n.isNaN())
275 return n.normal() * num::acos(dot(a.normal(), b.normal()));
280template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
281void TriangleMesh3D<T, BHV, SH>::smoothNormals()
283 const size_t numTriangles = triangles_.size();
285 for (
size_t i = 0; i < numTriangles; ++i)
287 std::fill_n(triangles_[i].normals, 3,
static_cast<TVector*
>(0));
290 normals_.reserve(3 * triangles_.size());
292 for (
size_t i = 0; i < numTriangles; ++i)
294 Triangle& triangle = triangles_[i];
295 for (
size_t k = 0; k < 3; ++k)
297 HalfEdge edge(&triangle, k);
304 LASS_ENFORCE(normals_.size() < normals_.capacity());
305 normals_.push_back(impl::computeWeightedNormal(edge));
306 TVector& normal = normals_.back();
307 edge.setNormal(&normal);
311 for (HalfEdge left = edge.rNext(); left && !left.normal() && !left.creaseLevel(); left = left.rNext())
313 normal += impl::computeWeightedNormal(left);
314 left.setNormal(&normal);
318 for (HalfEdge right = edge.rPrev(); right && !right.normal() && !right.oPrev().creaseLevel(); right = right.rPrev())
320 normal += impl::computeWeightedNormal(right);
321 right.setNormal(&normal);
333template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
337 for (
typename TTriangles::iterator triangle = triangles_.begin();
338 triangle != triangles_.end(); ++triangle)
340 std::fill(triangle->normals, triangle->normals + 3,
static_cast<TVector*
>(0));
345template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
346void TriangleMesh3D<T, BHV, SH>::loopSubdivision(
unsigned level)
348 if (triangles_.empty())
360 TVertices newVertices = vertices_;
361 TNormals newNormals = normals_;
363 const TPoint*
const firstVertex = &vertices_[0];
364 const TVector*
const firstNormal = normals_.empty() ? 0 : &normals_[0];
365 const TUv*
const firstUv = uvs_.empty() ? 0 : &uvs_[0];
370 TVertexTriangles vertexTriangles;
371 findVertexTriangles(vertexTriangles);
375 const size_t numVertices = vertices_.size();
376 for (
size_t i = 0; i < numVertices; ++i)
378 const Triangle*
const vertexTriangle = vertexTriangles[i];
383 const TPoint& vertex = vertices_[i];
384 findVertexRing(vertex, vertexTriangle, ring, creases, uvRing);
385 const size_t nRing = ring.size();
386 const size_t nCreases = creases.size();
387 LASS_ASSERT(nRing >= 2);
391 newVertices[i] = TPoint(.75f * vertex.position() + .125f * (creases[0]->position() + creases[1]->position()));
393 else if (nRing > 2 && nCreases == 0)
396 const TValue alpha = num::inv(
static_cast<TValue
>(nRing));
397 const TValue beta = nRing == 6
399 : 2.f * (.625f - num::sqr(.375f + .25f * num::cos(2.f * TNumTraits::pi * alpha))) * alpha;
400 TVector newVertex = (1.f -
static_cast<TValue
>(nRing) * beta) * vertex.position();
401 for (
size_t j = 0; j < nRing; ++j)
403 newVertex += beta * ring[j]->position();
405 newVertices[i] = TPoint(newVertex);
408 LASS_ASSERT(uvRing.size() == nRing);
409 const size_t k = vertexTriangle->side(&vertex);
410 LASS_ASSERT(k < 3 && vertexTriangle->uvs[k]);
411 const TUv& uv = *vertexTriangle->uvs[k];
412 typename TUv::TVector newUv = (1.f -
static_cast<TValue
>(nRing) * beta) * uv.position();
413 for (
size_t j = 0; j < nRing; ++j)
415 newUv += beta * uvRing[j]->position();
417 newUvs[
static_cast<size_t>(&uv - firstUv)] = TUv(newUv);
425 for (
typename TTriangles::iterator triangle = triangles_.begin();
426 triangle != triangles_.end(); ++triangle)
428 for (
size_t k = 0; k < 3; ++k)
430 triangle->vertices[k] = &newVertices[
static_cast<size_t>(triangle->vertices[k] - firstVertex)];
431 triangle->normals[k] = triangle->normals[k] ? &newNormals[
static_cast<size_t>(triangle->normals[k] - firstNormal)] : 0;
432 triangle->uvs[k] = triangle->uvs[k] ? &newUvs[
static_cast<size_t>(triangle->uvs[k] - firstUv)] : 0;
433 triangle->creaseLevel[k] = triangle->creaseLevel[k] > 0 ? triangle->creaseLevel[k] - 1 : 0;
436 vertices_.swap(newVertices);
437 normals_.swap(newNormals);
440 tree_.reset(triangles_.begin(), triangles_.end());
448template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
449template <
typename Func>
452 if (triangles_.empty())
465 TOddVertexWings oddVertexWings;
466 const size_t numTriangles = triangles_.size();
467 for (
size_t i = 3; i < numTriangles; i += 4)
469 Triangle& oddTriangle = triangles_[i];
470 for (
size_t k = 0; k < 3; ++k)
472 const TPoint* oddVertex = oddTriangle.vertices[k];
473 typename TOddVertexWings::iterator w = oddVertexWings.find(oddVertex);
474 if (w == oddVertexWings.end())
476 oddVertexWings[oddVertex] = std::make_pair(&oddTriangle, (Triangle*) 0);
480 TWing& wing = w->second;
481 LASS_ASSERT(wing.first && !wing.second);
482 wing.second = &oddTriangle;
491 for (
typename TOddVertexWings::const_iterator i = oddVertexWings.begin(), end = oddVertexWings.end(); i != end; ++i)
493 const TPoint* vertex = i->first;
494 const Triangle* wing1 = i->second.first;
495 const Triangle* wing2 = i->second.second;
497 const size_t k1 = wing1->side(vertex);
498 const size_t k2 = wing2 ? wing2->side(vertex) : IndexTriangle::null();
508 *
const_cast<TPoint*
>(vertex),
509 const_cast<TVector*
>(wing1->normals[k1]),
const_cast<TVector*
>(wing2 ? wing2->normals[k2] : 0),
510 const_cast<TUv*
>(wing1->uvs[k1]),
const_cast<TUv*
>(wing2 ? wing2->uvs[k2] : 0),
511 &(wing1->attribute), wing2 ? &(wing2->attribute) : 0);
517template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
518template <
typename Func>
521 if (triangles_.empty())
526 TOddVertexWings oddVertexWings;
531 subdivide(selected, oddVertexWings);
537 for (
typename TOddVertexWings::const_iterator i = oddVertexWings.begin(), end = oddVertexWings.end(); i != end; ++i)
539 const TPoint* vertex = i->first;
540 const Triangle* wing1 = i->second.first;
541 const Triangle* wing2 = i->second.second;
543 const size_t k1 = wing1->side(vertex);
544 const size_t k2 = wing2 ? wing2->side(vertex) : IndexTriangle::null();
554 *
const_cast<TPoint*
>(vertex),
555 const_cast<TVector*
>(wing1->normals[k1]),
const_cast<TVector*
>(wing2 ? wing2->normals[k2] : 0),
556 const_cast<TUv*
>(wing1->uvs[k1]),
const_cast<TUv*
>(wing2 ? wing2->uvs[k2] : 0),
557 &(wing1->attribute), wing2 ? &(wing2->attribute) : 0);
565template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
568 typedef std::vector<PositionalEdge> TEdges;
572 const size_t numTriangles = triangles_.size();
574 edges.reserve(numBoundaryEdges_);
575 for (
size_t i = 0; i < numTriangles; ++i)
577 Triangle& triangle = triangles_[i];
578 for (
size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
580 if (triangle.others[k1] == 0)
582 edges.push_back(PositionalEdge(&triangle, k1, k2));
586 LASS_ASSERT(edges.size() == numBoundaryEdges_);
587 std::sort(edges.begin(), edges.end());
591 for (
size_t i = 0; i < numTriangles; ++i)
593 Triangle& triangle = triangles_[i];
594 for (
size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
596 if (triangle.others[k1] == 0)
598 const PositionalEdge bait(&triangle, k2, k1);
599 const typename TEdges::const_iterator haul = std::lower_bound(edges.begin(), edges.end(), bait);
600 if (haul != edges.end() && !(bait < *haul) && haul->triangle->others[haul->k1] == 0)
602 triangle.others[k1] = haul->triangle;
603 haul->triangle->others[haul->k1] = ▵
604 LASS_ASSERT(numBoundaryEdges_ >= 2);
605 numBoundaryEdges_ -= 2;
606 for (
size_t s = 1; s <= 2; ++s)
609 Triangle* other = haul->triangle;
610 size_t k = s == 1 ? haul->k2 : haul->k1;
611 const TPoint*
const v =
612 triangle.vertices[s == 1 ? k1 : k2];
613 const TPoint*
const otherV = other->vertices[k];
614 LASS_ASSERT(*v == *otherV);
619 LASS_ASSERT(other->vertices[k] == otherV);
620 other->vertices[k] = v;
621 other = other->others[
622 (k + (s == 1 ? 0 : 2)) % 3];
623 k = other ? other->side(otherV) : 3;
625 while (other && k < 3);
637 template <
typename TriangleType>
638 typename TriangleType::TVector computeFaceNormal(
const TriangleType& triangle)
640 typedef typename TriangleType::TVector TVector;
641 const TVector a = *triangle.vertices[1] - *triangle.vertices[0];
642 const TVector b = *triangle.vertices[2] - *triangle.vertices[0];
643 const TVector n = cross(a, b);
644 if (n.isZero() || n.isNaN())
654template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
655void TriangleMesh3D<T, BHV, SH>::autoCrease(
unsigned level, TParam maxAngleInRadians)
657 const TValue minDot = num::cos(maxAngleInRadians);
658 const size_t numTriangles = triangles_.size();
659 for (
size_t i = 0; i < numTriangles; ++i)
661 Triangle& triangle = triangles_[i];
662 const TVector faceNormal = impl::computeFaceNormal(triangle);
663 for (
size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
665 triangle.creaseLevel[k1] = level;
667 Triangle* other = triangle.others[k1];
672 const size_t otherK1 = other->side(triangle.vertices[k1]);
673 const size_t otherK2 = (otherK1 + 2) % 3;
674 LASS_ASSERT(otherK1 < 3 && otherK2 == other->side(triangle.vertices[k2]));
675 const TVector otherNormal = impl::computeFaceNormal(*other);
677 const TVector a1 = (triangle.normals[k1] ? *triangle.normals[k1] : faceNormal).normal();
678 const TVector a2 = (triangle.normals[k2] ? *triangle.normals[k2] : faceNormal).normal();
679 const TVector b1 = (other->normals[otherK1] ? *other->normals[otherK1] : otherNormal).normal();
680 const TVector b2 = (other->normals[otherK2] ? *other->normals[otherK2] : otherNormal).normal();
682 if (maxAngleInRadians == 0)
684 if (a1 == b1 && a2 == b2)
686 triangle.creaseLevel[k1] = 0;
691 if (dot(a1, b1) >= minDot && dot(a2, b2) >= minDot)
693 triangle.creaseLevel[k1] = 0;
717template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
719 const TRay& ray, TTriangleIterator& triangle,
720 TReference t, TParam tMin, IntersectionContext* context)
const
743template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
745 const TRay& ray, TTriangleIterator& triangle,
746 TReference t, TParam tMin, TFilter filter, IntersectionContext* context)
const
748 LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
750 IntersectInfo info(ray, filter);
751 const TTriangleIterator candidate = tree_.intersect(ray, t, tMin, &info);
752 if (candidate == triangles_.end())
756 triangle = candidate;
761 [[maybe_unused]]
const Result r = triangle->intersect(info.woop, temp, tMin, context);
762 LASS_ASSERT(r ==
rOne && t == temp);
778template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
800template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
803 LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
804 IntersectInfo info(ray, filter);
805 return tree_.intersects(ray, tMin, tMax, &info);
810template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
811void TriangleMesh3D<T, BHV, SH>::swap(TSelf& other)
813 tree_.swap(other.tree_);
814 triangles_.swap(other.triangles_);
815 vertices_.swap(other.vertices_);
816 normals_.swap(other.normals_);
817 uvs_.swap(other.uvs_);
818 std::swap(numBoundaryEdges_, other.numBoundaryEdges_);
825template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
826Result TriangleMesh3D<T, BHV, SH>::Triangle::intersect(
const TRay& ray,
827 TReference t, TParam tMin, IntersectionContext* context)
const
829 const TIntersectTriangleWoop intersectWoop(ray.support(), ray.direction());
830 return intersect(intersectWoop, t, tMin, context);
835template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
836Result TriangleMesh3D<T, BHV, SH>::Triangle::intersect(
837 const TIntersectTriangleWoop& intersectWoop,
838 TReference t, TParam tMin, IntersectionContext* context)
const
840 LASS_ASSERT(vertices[0] && vertices[1] && vertices[2]);
841 const TPoint point0 = *vertices[0];
842 const TPoint point1 = *vertices[1];
843 const TPoint point2 = *vertices[2];
846 const Result hit = intersectWoop(point0, point1, point2, b, t, tMin);
854 LASS_ASSERT(b[0] >= 0 && b[1] >= 0 && b[2] >= 0 && num::abs(b[0] + b[1] + b[2] - 1) < TNumTraits::gamma(10));
855 context->point = TPoint(b[0] * point0.position() + b[1] * point1.position() + b[2] * point2.position());
857 const TVector dPoint_dR = *vertices[1] - point0;
858 const TVector dPoint_dS = *vertices[2] - point0;
859 const TValue r = b[1];
860 const TValue s = b[2];
865 LASS_ASSERT(uvs[1] && uvs[2]);
866 const TUv uv0 = *uvs[0];
867 const TUv uv1 = *uvs[1];
868 const TUv uv2 = *uvs[2];
869 context->uv = TUv(b[0] * uv0.position() + b[1] * uv1.position() + b[2] * uv2.position());
877 const typename TUv::TVector dUv_dR = uv1 - uv0;
878 const typename TUv::TVector dUv_dS = uv2 - uv0;
879 const TValue matrix[4] = { dUv_dR.x, dUv_dS.x, dUv_dR.y, dUv_dS.y };
880 TValue solution[4] = { 1, 0, 0, 1 };
881 num::impl::cramer2<TValue>(matrix, solution, solution + 4);
882 dRs_dU = TUv(solution[0], solution[1]);
883 dRs_dV = TUv(solution[2], solution[3]);
885 context->dPoint_dU = dPoint_dR * dRs_dU.x + dPoint_dS * dRs_dU.y;
886 context->dPoint_dV = dPoint_dR * dRs_dV.x + dPoint_dS * dRs_dV.y;
890 context->uv = TUv(r, s);
891 context->dPoint_dU = dPoint_dR;
892 context->dPoint_dV = dPoint_dS;
895 context->geometricNormal = cross(dPoint_dR, dPoint_dS).normal();
898 LASS_ASSERT(normals[1] && normals[2]);
899 const TVector normal0 = *normals[0];
900 const TVector normal1 = *normals[1];
901 const TVector normal2 = *normals[2];
902 context->normal = (b[0] * normal0 + b[1] * normal1 + b[2] * normal2).normal();
903 const TVector dNormal_dR = normal1 - normal0;
904 const TVector dNormal_dS = normal2 - normal0;
905 context->dNormal_dU = dNormal_dR * dRs_dU.x + dNormal_dS * dRs_dU.y;
906 context->dNormal_dV = dNormal_dR * dRs_dV.x + dNormal_dS * dRs_dV.y;
910 context->normal = context->geometricNormal;
911 context->dNormal_dU = TVector();
912 context->dNormal_dV = TVector();
920template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
inline
921size_t TriangleMesh3D<T, BHV, SH>::Triangle::side(
const TPoint* vertex)
const
923 return vertices[0] == vertex ? 0 : (vertices[1] == vertex ? 1 : (vertices[2] == vertex ? 2 : size_t(-1)));
928template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
inline
929typename TriangleMesh3D<T, BHV, SH>::TValue TriangleMesh3D<T, BHV, SH>::Triangle::area()
const
931 const TVector a = *vertices[1] - *vertices[0];
932 const TVector b = *vertices[2] - *vertices[0];
933 const TVector n = cross(a, b);
939template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
inline
940typename TriangleMesh3D<T, BHV, SH>::TVector TriangleMesh3D<T, BHV, SH>::Triangle::geometricNormal()
const
942 const TVector a = *vertices[1] - *vertices[0];
943 const TVector b = *vertices[2] - *vertices[0];
944 const TVector n = cross(a, b);
952template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
953template <
typename IndexTriangleInputIterator>
954void TriangleMesh3D<T, BHV, SH>::buildMesh(IndexTriangleInputIterator first, IndexTriangleInputIterator last)
956 const size_t sizeVertices = vertices_.size();
957 const size_t sizeNormals = normals_.size();
958 const size_t sizeUvs = uvs_.size();
960 for (; first != last; ++first)
963 size_t numNormals = 0;
965 for (std::size_t k = 0; k < 3; ++k)
967 triangle.others[k] = 0;
968 triangle.creaseLevel[k] = 0;
970 const size_t vertex = first->vertices[k];
971 triangle.vertices[k] = &vertices_[LASS_ENFORCE_INDEX(vertex, sizeVertices)];
973 const size_t normal = first->normals[k];
974 if (normal != IndexTriangle::null())
976 triangle.normals[k] = &normals_[LASS_ENFORCE_INDEX(normal, sizeNormals)];
981 triangle.normals[k] = 0;
984 const size_t uv = first->uvs[k];
985 if (uv != IndexTriangle::null())
987 triangle.uvs[k] = &uvs_[LASS_ENFORCE_INDEX(uv, sizeUvs)];
996 if (!(numNormals == 0 || numNormals == 3))
998 LASS_THROW(
"Each triangle must have either zero or three normals vectors");
1000 if (!(numUvs == 0 || numUvs == 3))
1002 LASS_THROW(
"Each triangle must have either zero or three uv coordinates");
1005 triangles_.push_back(triangle);
1009 tree_.reset(triangles_.begin(), triangles_.end());
1014template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
1015void TriangleMesh3D<T, BHV, SH>::findVertexTriangles(TVertexTriangles& vertexTriangles)
const
1017 TVertexTriangles result(vertices_.size(), 0);
1018 const TPoint*
const firstVertex = &vertices_[0];
1019 for (
typename TTriangles::const_iterator i = triangles_.begin(); i != triangles_.end(); ++i)
1021 const Triangle& triangle = *i;
1022 for (
size_t k = 0; k < 3; ++k)
1024 const size_t j =
static_cast<size_t>(triangle.vertices[k] - firstVertex);
1025 LASS_ASSERT(j < result.size());
1026 result[j] = ▵
1029 vertexTriangles.swap(result);
1034template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
1035void TriangleMesh3D<T, BHV, SH>::connectTriangles()
1037 typedef std::vector<LogicalEdge> TEdges;
1039 numBoundaryEdges_ = 0;
1040 const size_t numTriangles = triangles_.size();
1041 if (numTriangles == 0)
1049 edges.reserve(3 * numTriangles);
1050 for (
size_t i = 0; i < numTriangles; ++i)
1052 Triangle& triangle = triangles_[i];
1053 for (std::size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
1055 edges.push_back(LogicalEdge(
1056 &triangle, triangle.vertices[k1], triangle.vertices[k2]));
1059 std::sort(edges.begin(), edges.end());
1063 for (
size_t i = 0; i < numTriangles; ++i)
1065 Triangle& triangle = triangles_[i];
1066 for (std::size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
1068 const LogicalEdge bait(0, triangle.vertices[k2], triangle.vertices[k1]);
1069 const typename TEdges::const_iterator haul = std::lower_bound(edges.begin(), edges.end(), bait);
1070 if (haul != edges.end() && *haul == bait)
1072 if (stde::next(haul) != edges.end() && *stde::next(haul) == bait)
1074 std::ostringstream buffer;
1075 buffer <<
"multiple half edges detected from " << *bait.tail <<
" to " << *bait.head <<
". Triangles:\n";
1076 const typename TEdges::const_iterator last = std::upper_bound(edges.begin(), edges.end(), bait);
1077 for (
typename TEdges::const_iterator e = haul; e != last; ++e)
1079 const Triangle& t = *e->triangle;
1080 buffer << *t.vertices[0] <<
", " << *t.vertices[1] <<
", " << *t.vertices[2] <<
"\n";
1082 LASS_THROW(buffer.str());
1084 triangle.others[k1] = haul->triangle;
1088 triangle.others[k1] = 0;
1089 ++numBoundaryEdges_;
1097template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
1098void TriangleMesh3D<T, BHV, SH>::findVertexRing(
1099 const TPoint& vertex,
const Triangle* vertexTriangle, TVertexRing& ring,
1100 TVertexRing& creases, TUvRing& uvs)
const
1106 bool hasUvRing =
true;
1107 const TUv* vertexUv = 0;
1108 const Triangle* triangle = vertexTriangle;
1111 const size_t k = triangle->side(&vertex);
1113 const size_t kCcw = (k + 2) % 3;
1114 const TPoint* neighbour = triangle->vertices[kCcw];
1115 const Triangle*
const other = triangle->others[kCcw];
1116 if (triangle->creaseLevel[kCcw] > 0 || !other)
1119 creases.push_back(neighbour);
1124 vertexUv = triangle->uvs[k];
1126 hasUvRing &= vertexUv && vertexUv == triangle->uvs[k];
1129 LASS_ASSERT(triangle->uvs[kCcw]);
1130 uvs.push_back(triangle->uvs[kCcw]);
1138 const Triangle* triangle2 = vertexTriangle;
1139 const TPoint* neighbour2 = 0;
1142 const size_t k2 = triangle2->side(&vertex);
1143 LASS_ASSERT(k2 < 3);
1144 const size_t k2Cw = (k2 + 1) % 3;
1145 neighbour2 = triangle2->vertices[k2Cw];
1146 const Triangle* other2 = triangle2->others[k2];
1147 if (triangle2->creaseLevel[k2Cw] > 0 || !other2)
1150 creases.push_back(neighbour2);
1154 ring.resize(1, neighbour2);
1157 ring.push_back(neighbour);
1160 while (triangle && triangle != vertexTriangle);
1174template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
1175void TriangleMesh3D<T, BHV, SH>::subdivide()
1177 if (triangles_.empty())
1182 const size_t numTriangles = triangles_.size();
1183 const size_t numVertices = vertices_.size();
1184 const size_t numNormals = normals_.size();
1185 const size_t numUvs = uvs_.size();
1186 LASS_ASSERT((3 * numTriangles + numBoundaryEdges_) % 2 == 0);
1187 const size_t numOddVertices = (3 * numTriangles + numBoundaryEdges_) / 2;
1191 size_t numOddNormals = 0;
1192 size_t numOddUvs = 0;
1193 if (numNormals || numUvs)
1195 for (
size_t i = 0; i < numTriangles; ++i)
1197 const Triangle& triangle = triangles_[i];
1198 for (
size_t k0 = 2, k1 = 0; k1 < 3; k0 = k1++)
1200 LASS_ASSERT((!triangle.normals[k0]) == (!triangle.normals[k1]));
1201 LASS_ASSERT((!triangle.uvs[k0]) == (!triangle.uvs[k1]));
1202 if (
const Triangle*
const other = triangle.others[k0])
1204 const size_t h0 = other->side(triangle.vertices[k1]);
1205 const size_t h1 = other->side(triangle.vertices[k0]);
1206 LASS_ASSERT(h0 < 3 && h1 == (h0 + 1) % 3);
1207 if (triangle.normals[k0])
1209 numOddNormals += other->normals[h0] == triangle.normals[k0] && other->normals[h1] == triangle.normals[k1] ? 1 : 2;
1211 if (triangle.uvs[k0])
1213 numOddUvs += other->uvs[h0] == triangle.uvs[k0] && other->uvs[h1] == triangle.uvs[k1] ? 1 : 2;
1218 numOddNormals += triangle.normals[k0] ? 2 : 0;
1219 numOddUvs += triangle.uvs[k0] ? 2 : 0;
1223 LASS_ASSERT((numOddNormals % 2) == 0 && (numOddUvs % 2) == 0);
1229 TTriangles newTriangles(4 * numTriangles);
1230 TVertices newVertices = vertices_;
1231 TNormals newNormals = normals_;
1233 newVertices.reserve(numVertices + numOddVertices);
1234 newNormals.reserve(numNormals + numOddNormals);
1235 newUvs.reserve(numUvs + numOddUvs);
1237 const Triangle*
const firstTriangle = &triangles_[0];
1238 const TPoint*
const firstVertex = &vertices_[0];
1239 const TVector*
const firstNormal = normals_.empty() ? 0 : &normals_[0];
1240 const TUv*
const firstUv = uvs_.empty() ? 0 : &uvs_[0];
1257 for (
size_t i = 0; i < numTriangles; ++i)
1259 const Triangle& triangle = triangles_[i];
1260 Triangle*
const newTris = &newTriangles[4 * i];
1261 Triangle& oddTriangle = newTris[3];
1265 for (
size_t k0 = 2, k1 = 0; k1 < 3; k0 = k1++)
1267 const Triangle*
const other = triangle.others[k0];
1268 Triangle*
const oddOther = other ? &newTriangles[4 *
static_cast<size_t>(other - firstTriangle) + 3] : 0;
1269 const size_t h0 = other ? other->side(triangle.vertices[k1]) : IndexTriangle::null();
1270 const size_t h1 = other ? other->side(triangle.vertices[k0]) : IndexTriangle::null();
1271 LASS_ASSERT((h0 < 3 && h1 == (h0 + 1) % 3) || other == 0);
1273 if (!oddTriangle.vertices[k0])
1275 LASS_ASSERT(newVertices.size() < newVertices.capacity());
1276 newVertices.push_back(TPoint(.5 * (triangle.vertices[k0]->position() + triangle.vertices[k1]->position())));
1277 oddTriangle.vertices[k0] = &newVertices.back();
1280 oddOther->vertices[h0] = &newVertices.back();
1283 if (triangle.normals[k0] && !oddTriangle.normals[k0])
1285 LASS_ASSERT(triangle.normals[k1]);
1286 LASS_ASSERT(newNormals.size() < newNormals.capacity());
1287 newNormals.push_back(.5 * (*triangle.normals[k0] + *triangle.normals[k1]));
1288 oddTriangle.normals[k0] = &newNormals.back();
1289 if (other && triangle.normals[k0] == other->normals[h1] && triangle.normals[k1] == other->normals[h0])
1291 oddOther->normals[h0] = &newNormals.back();
1294 if (triangle.uvs[k0] && !oddTriangle.uvs[k0])
1296 LASS_ASSERT(newUvs.size() < newUvs.capacity());
1297 LASS_ASSERT(triangle.uvs[k1]);
1298 newUvs.push_back(TUv(.5 * (triangle.uvs[k0]->position() + triangle.uvs[k1]->position())));
1299 oddTriangle.uvs[k0] = &newUvs.back();
1300 if (other && triangle.uvs[k0] == other->uvs[h1] && triangle.uvs[k1] == other->uvs[h0])
1302 oddOther->uvs[h0] = &newUvs.back();
1305 oddTriangle.others[k0] = &newTris[k1];
1306 oddTriangle.creaseLevel[k0] = 0;
1308 oddTriangle.attribute = triangle.attribute;
1312 for (
size_t k0 = 0, k1 = 1, k2 = 2; k0 < 3; k1 = k2, k2 = k0, ++k0)
1314 Triangle& newTriangle = newTris[k0];
1315 newTriangle.vertices[k0] = &newVertices.begin()[triangle.vertices[k0] - firstVertex];
1316 newTriangle.vertices[k1] = oddTriangle.vertices[k0];
1317 newTriangle.vertices[k2] = oddTriangle.vertices[k2];
1318 newTriangle.normals[k0] = triangle.normals[k0] ? &newNormals.begin()[triangle.normals[k0] - firstNormal] : 0;
1319 newTriangle.normals[k1] = oddTriangle.normals[k0];
1320 newTriangle.normals[k2] = oddTriangle.normals[k2];
1321 newTriangle.uvs[k0] = triangle.uvs[k0] ? &newUvs.begin()[triangle.uvs[k0] - firstUv] : 0;
1322 newTriangle.uvs[k1] = oddTriangle.uvs[k0];
1323 newTriangle.uvs[k2] = oddTriangle.uvs[k2];
1324 if (
const Triangle* other0 = triangle.others[k0])
1326 const size_t j =
static_cast<size_t>(other0 - firstTriangle);
1327 const size_t h = other0->side(triangle.vertices[k0]);
1329 Triangle& newOther = newTriangles[4 * j + h];
1330 LASS_ASSERT(newOther.others[(h + 2) % 3] == 0 || newOther.others[(h + 2) % 3] == &newTriangle);
1331 newTriangle.others[k0] = &newOther;
1333 newTriangle.others[k1] = &oddTriangle;
1334 if (
const Triangle* other2 = triangle.others[k2])
1336 const size_t j =
static_cast<size_t>(other2 - firstTriangle);
1337 const size_t h = other2->side(triangle.vertices[k0]);
1339 Triangle& newOther = newTriangles[4 * j + h];
1340 LASS_ASSERT(newOther.others[h] == 0 || newOther.others[h] == &newTriangle);
1341 newTriangle.others[k2] = &newOther;
1343 newTriangle.creaseLevel[k0] = triangle.creaseLevel[k0];
1344 newTriangle.creaseLevel[k1] = 0;
1345 newTriangle.creaseLevel[k2] = triangle.creaseLevel[k2];
1346 newTriangle.attribute = triangle.attribute;
1350 triangles_.swap(newTriangles);
1351 vertices_.swap(newVertices);
1352 normals_.swap(newNormals);
1355 numBoundaryEdges_ *= 2;
1363template <
typename T,
template <
typename,
typename,
typename>
class BHV,
typename SH>
1364void TriangleMesh3D<T, BHV, SH>::subdivide(TTriangleIterators& selected, TOddVertexWings& oddVertexWings)
1366 if (triangles_.empty())
1377 typedef std::vector<unsigned> TVertexTags;
1379 const Triangle*
const firstTriangle = &triangles_[0];
1380 const TPoint*
const firstVertex = &vertices_[0];
1381 const TVector*
const firstNormal = normals_.empty() ? 0 : &normals_[0];
1382 const TUv*
const firstUv = uvs_.empty() ? 0 : &uvs_[0];
1386 TVertexTags vertexTags(vertices_.size(), Unselected);
1387 const size_t numSelected = selected.size();
1388 for (
size_t i = 0; i < numSelected; ++i)
1390 const TTriangleIterator triangle = selected[i];
1391 for (
size_t k = 0; k < 3; ++k)
1393 const TPoint* vertex = triangle->vertices[k];
1394 vertexTags.begin()[vertex - firstVertex] = Selected;
1401 const size_t numTriangles = triangles_.size();
1402 std::vector<size_t> triangleSplits(numTriangles, 1);
1403 for (
size_t i = 0; i < numTriangles; ++i)
1405 const Triangle& triangle = triangles_[i];
1406 unsigned& tag0 = vertexTags.begin()[triangle.vertices[0] - firstVertex];
1407 unsigned& tag1 = vertexTags.begin()[triangle.vertices[1] - firstVertex];
1408 unsigned& tag2 = vertexTags.begin()[triangle.vertices[2] - firstVertex];
1409 if (tag0 == Selected || tag1 == Selected || tag2 == Selected)
1411 tag0 =
static_cast<VertexTag
>(tag0 | Progressive);
1412 tag1 =
static_cast<VertexTag
>(tag1 | Progressive);
1413 tag2 =
static_cast<VertexTag
>(tag2 | Progressive);
1420 std::vector<size_t> offspringCount(numTriangles, 4);
1421 for (
size_t i = 0; i < numTriangles; ++i)
1423 const Triangle& triangle = triangles_[i];
1424 for (
size_t k = 0; k < 3; ++k)
1426 if (vertexTags.begin()[triangle.vertices[k] - firstVertex] == Unselected)
1428 offspringCount[i] = 1;
1437 for (
size_t i = 0; i < numTriangles; ++i)
1439 if (offspringCount[i] == 4)
1443 const Triangle& triangle = triangles_[i];
1444 for (
size_t k = 0; k < 3; ++k)
1446 const Triangle* other = triangle.others[k];
1447 if (other && offspringCount.begin()[other - firstTriangle] == 4)
1450 const TPoint* v0 = triangle.vertices[k];
1451 const TPoint* v1 = triangle.vertices[(k + 1) % 3];
1452 const TPoint* v2 = triangle.vertices[(k + 2) % 3];
1453 LASS_ASSERT(other->side(v0) < 3 && other->side(v1) < 3);
1454 LASS_ASSERT(vertexTags.begin()[v0 - firstVertex] != Unselected && vertexTags.begin()[v1 - firstVertex] != Unselected);
1455 LASS_ASSERT(vertexTags.begin()[v2 - firstVertex] == Unselected);
1457 offspringCount[i] = 2;
1464 std::vector<size_t> newTriangleOffsets(numTriangles + 1, 0);
1465 std::partial_sum(offspringCount.begin(), offspringCount.end(), newTriangleOffsets.begin() + 1);
1466 const size_t numNewTriangles = newTriangleOffsets.back();
1470 size_t numOddVertices = 0;
1471 size_t numOddNormals = 0;
1472 size_t numOddUvs = 0;
1473 size_t numOddBoundaryEdges = 0;
1474 for (
size_t i = 0; i < numTriangles; ++i)
1476 if (offspringCount[i] != 4)
1480 const Triangle& triangle = triangles_[i];
1481 for (
size_t k = 0; k < 3; ++k)
1483 const HalfEdge edge1(&triangle, k);
1484 if (
const HalfEdge other1 = edge1.sym())
1486 const bool otherIsFourSplit = offspringCount.begin()[other1.triangle() - firstTriangle] == 4;
1487 numOddVertices += otherIsFourSplit ? 1 : 2;
1489 const HalfEdge edge2 = edge1.oNext();
1490 const HalfEdge other2 = other1.oNext();
1491 LASS_ASSERT(!edge1.normal() == !edge2.normal() && !edge1.uv() == !edge2.uv());
1492 LASS_ASSERT(!other1.normal() == !other2.normal() && !other1.uv() == !other2.uv());
1495 numOddNormals += (otherIsFourSplit && edge1.normal() == other2.normal() && edge2.normal() == other1.normal()) ? 1 : 2;
1499 numOddUvs += (otherIsFourSplit && edge1.uv() == other2.uv() && edge2.uv() == other1.uv()) ? 1 : 2;
1504 numOddVertices += 2;
1505 numOddNormals += edge1.normal() ? 2 : 0;
1506 numOddUvs += edge1.uv() ? 2 : 0;
1507 numOddBoundaryEdges += 1;
1511 LASS_ASSERT((numOddVertices % 2) == 0 && (numOddNormals % 2) == 0 && (numOddUvs % 2) == 0);
1512 numOddVertices /= 2;
1516 TTriangles newTriangles(numNewTriangles);
1517 TVertices newVertices = vertices_;
1518 TNormals newNormals = normals_;
1520 newVertices.reserve(vertices_.size() + numOddVertices);
1521 newNormals.reserve(normals_.size() + numOddNormals);
1522 newUvs.reserve(uvs_.size() + numOddUvs);
1523 oddVertexWings.clear();
1528 for (
size_t i = 0; i < numTriangles; ++i)
1530 if (offspringCount[i] != 4)
1534 const Triangle& triangle = triangles_[i];
1535 Triangle*
const newTris = &newTriangles[newTriangleOffsets[i]];
1537 Triangle& oddTriangle = newTris[3];
1541 for (
size_t k0 = 2, k1 = 0; k1 < 3; k0 = k1++)
1543 const Triangle*
const other = triangle.others[k0];
1544 const size_t j = other ?
static_cast<size_t>(other - firstTriangle) : IndexTriangle::null();
1545 const size_t h0 = other ? other->side(triangle.vertices[k1]) : IndexTriangle::null();
1546 const size_t h1 = other ? other->side(triangle.vertices[k0]) : IndexTriangle::null();
1547 LASS_ASSERT((h0 < 3 && h1 == (h0 + 1) % 3) || other == 0);
1548 Triangle*
const oddOther = (other && offspringCount[j] == 4) ? &newTriangles[newTriangleOffsets[j] + 3] : 0;
1550 if (!oddTriangle.vertices[k0])
1552 LASS_ASSERT(newVertices.size() < newVertices.capacity());
1553 newVertices.push_back(TPoint(.5 * (triangle.vertices[k0]->position() + triangle.vertices[k1]->position())));
1554 oddTriangle.vertices[k0] = &newVertices.back();
1557 oddOther->vertices[h0] = &newVertices.back();
1559 oddVertexWings[&newVertices.back()] = TWing(&oddTriangle,
const_cast<Triangle*
>(oddOther));
1561 if (triangle.normals[k0] && !oddTriangle.normals[k0])
1563 LASS_ASSERT(triangle.normals[k1]);
1564 LASS_ASSERT(newNormals.size() < newNormals.capacity());
1565 newNormals.push_back(.5 * (*triangle.normals[k0] + *triangle.normals[k1]));
1566 oddTriangle.normals[k0] = &newNormals.back();
1567 if (oddOther && triangle.normals[k0] == other->normals[h1] && triangle.normals[k1] == other->normals[h0])
1569 oddOther->normals[h0] = &newNormals.back();
1572 if (triangle.uvs[k0] && !oddTriangle.uvs[k0])
1574 LASS_ASSERT(newUvs.size() < newUvs.capacity());
1575 LASS_ASSERT(triangle.uvs[k1]);
1576 newUvs.push_back(TUv(.5 * (triangle.uvs[k0]->position() + triangle.uvs[k1]->position())));
1577 oddTriangle.uvs[k0] = &newUvs.back();
1578 if (oddOther && triangle.uvs[k0] == other->uvs[h1] && triangle.uvs[k1] == other->uvs[h0])
1580 oddOther->uvs[h0] = &newUvs.back();
1583 oddTriangle.others[k0] = &newTris[k1];
1584 oddTriangle.creaseLevel[k0] = 0;
1586 oddTriangle.attribute = triangle.attribute;
1590 for (
size_t k0 = 0, k1 = 1, k2 = 2; k0 < 3; k1 = k2, k2 = k0, ++k0)
1592 Triangle& newTriangle = newTris[k0];
1593 newTriangle.vertices[k0] = &newVertices.begin()[triangle.vertices[k0] - firstVertex];
1594 newTriangle.vertices[k1] = oddTriangle.vertices[k0];
1595 newTriangle.vertices[k2] = oddTriangle.vertices[k2];
1596 newTriangle.normals[k0] = triangle.normals[k0] ? &newNormals.begin()[triangle.normals[k0] - firstNormal] : 0;
1597 newTriangle.normals[k1] = oddTriangle.normals[k0];
1598 newTriangle.normals[k2] = oddTriangle.normals[k2];
1599 newTriangle.uvs[k0] = triangle.uvs[k0] ? &newUvs.begin()[triangle.uvs[k0] - firstUv] : 0;
1600 newTriangle.uvs[k1] = oddTriangle.uvs[k0];
1601 newTriangle.uvs[k2] = oddTriangle.uvs[k2];
1602 if (
const Triangle* other0 = triangle.others[k0])
1604 const size_t j =
static_cast<size_t>(other0 - firstTriangle);
1605 LASS_ASSERT(offspringCount[j] == 4 || offspringCount[j] == 2);
1606 if (offspringCount[j] == 4)
1608 const size_t h = other0->side(triangle.vertices[k0]);
1610 Triangle& newOther = newTriangles[newTriangleOffsets[j] + h];
1611 LASS_ASSERT(newOther.others[(h + 2) % 3] == 0 || newOther.others[(h + 2) % 3] == &newTriangle);
1612 newTriangle.others[k0] = &newOther;
1615 newTriangle.others[k1] = &oddTriangle;
1616 if (
const Triangle* other2 = triangle.others[k2])
1618 const size_t j =
static_cast<size_t>(other2 - firstTriangle);
1619 LASS_ASSERT(offspringCount[j] == 4 || offspringCount[j] == 2);
1620 if (offspringCount[j] == 4)
1622 const size_t h = other2->side(triangle.vertices[k0]);
1624 Triangle& newOther = newTriangles[newTriangleOffsets[j] + h];
1625 LASS_ASSERT(newOther.others[h] == 0 || newOther.others[h] == &newTriangle);
1626 newTriangle.others[k2] = &newOther;
1629 newTriangle.creaseLevel[k0] = triangle.creaseLevel[k0];
1630 newTriangle.creaseLevel[k1] = 0;
1631 newTriangle.creaseLevel[k2] = triangle.creaseLevel[k2];
1632 newTriangle.attribute = triangle.attribute;
1637 LASS_ASSERT(newVertices.size() == vertices_.size() + numOddVertices);
1638 LASS_ASSERT(newNormals.size() == normals_.size() + numOddNormals);
1639 LASS_ASSERT(newUvs.size() == uvs_.size() + numOddUvs);
1643 for (
size_t i = 0; i < numTriangles; ++i)
1645 const Triangle& triangle = triangles_[i];
1646 Triangle*
const newTris = &newTriangles[newTriangleOffsets[i]];
1648 switch (offspringCount[i])
1651 for (
size_t k = 0; k < 3; ++k)
1653 newTris[0].vertices[k] = &newVertices.begin()[triangle.vertices[k] - firstVertex];
1654 newTris[0].normals[k] = triangle.normals[k] ? &newNormals.begin()[triangle.normals[k] - firstNormal] : 0;
1655 newTris[0].uvs[k] = triangle.uvs[k] ? &newUvs.begin()[triangle.uvs[k] - firstUv] : 0;
1656 if (
const Triangle*
const other = triangle.others[k])
1658 const size_t j =
static_cast<size_t>(other - firstTriangle);
1659 LASS_ASSERT(offspringCount[j] == 1 || offspringCount[j] == 2);
1660 const size_t dj = (offspringCount[j] == 2 && vertexTags.begin()[triangle.vertices[k] - firstVertex] == Unselected) ? 1 : 0;
1661 newTris[0].others[k] = &newTriangles[newTriangleOffsets[j] + dj];
1665 newTris[0].others[k] = 0;
1668 newTris[0].attribute = triangle.attribute;
1673 size_t k1 = IndexTriangle::null(), k2 = IndexTriangle::null();
1674 for (
size_t k = 0; k < 3; ++k)
1676 newTris[0].vertices[k] = newTris[1].vertices[k] = &newVertices.begin()[triangle.vertices[k] - firstVertex];
1677 newTris[0].normals[k] = newTris[1].normals[k] = triangle.normals[k] ? &newNormals.begin()[triangle.normals[k] - firstNormal] : 0;
1678 newTris[0].uvs[k] = newTris[1].uvs[k] = triangle.uvs[k] ? &newUvs.begin()[triangle.uvs[k] - firstUv] : 0;
1679 if (
const Triangle*
const other = triangle.others[k])
1682 const size_t j =
static_cast<size_t>(other - firstTriangle);
1683 const size_t dj = (offspringCount[j] == 2 && vertexTags.begin()[triangle.vertices[k] - firstVertex] == Unselected) ? 1 : 0;
1684 newTris[0].others[k] = newTris[1].others[k] = &newTriangles[newTriangleOffsets[j] + dj];
1688 newTris[0].others[k] = newTris[1].others[k] = 0;
1690 if (vertexTags[
static_cast<size_t>(triangle.vertices[k] - firstVertex)] == Unselected)
1692 LASS_ASSERT(k1 == IndexTriangle::null() && k2 == IndexTriangle::null());
1695 LASS_ASSERT(vertexTags[
static_cast<size_t>(triangle.vertices[k1] - firstVertex)] != Unselected);
1696 LASS_ASSERT(vertexTags[
static_cast<size_t>(triangle.vertices[k2] - firstVertex)] != Unselected);
1697 newTris[1].others[k] = &newTris[0];
1700 LASS_ASSERT(k1 < 3 && k2 < 3);
1701 newTris[0].others[k2] = &newTris[1];
1703 const Triangle* other = triangle.others[k1];
1705 const size_t j =
static_cast<size_t>(other - firstTriangle);
1706 LASS_ASSERT(offspringCount[j] == 4);
1707 const size_t offJ = newTriangleOffsets[j];
1708 Triangle& oddOther = newTriangles[offJ + 3];
1709 const size_t h1 = other->side(triangle.vertices[k2]);
1710 const size_t h2 = other->side(triangle.vertices[k1]);
1711 LASS_ASSERT((h1 < 3 && h2 == (h1 + 1) % 3));
1712 Triangle& other1 = newTriangles[offJ + h1];
1713 Triangle& other2 = newTriangles[offJ + h2];
1715 newTris[0].vertices[k2] = newTris[1].vertices[k1] = oddOther.vertices[h1];
1716 newTris[0].normals[k2] = newTris[1].normals[k1] = oddOther.normals[h1];
1717 newTris[0].uvs[k2] = newTris[1].uvs[k1] = oddOther.uvs[h1];
1719 LASS_ASSERT(newTris[0].vertices[k1] == other2.vertices[h2] && newTris[0].vertices[k2] == other2.vertices[h1]);
1720 newTris[0].others[k1] = &other2;
1721 other2.others[h1] = &newTris[0];
1722 LASS_ASSERT(newTris[1].vertices[k1] == other1.vertices[h2] && newTris[1].vertices[k2] == other1.vertices[h1]);
1723 newTris[1].others[k1] = &other1;
1724 other1.others[h1] = &newTris[1];
1726 newTris[0].attribute = newTris[1].attribute = triangle.attribute;
1728 LASS_ASSERT(oddVertexWings.find(oddOther.vertices[h1]) != oddVertexWings.end());
1729 TWing& wing = oddVertexWings[oddOther.vertices[h1]];
1730 LASS_ASSERT(wing.first && !wing.second);
1731 wing.second = &newTris[1];
1736 LASS_ASSERT(offspringCount[i] == 4);
1741 std::vector<size_t> selectedIndices;
1742 selectedIndices.reserve(numSelected);
1743 for (
size_t i = 0; i < numSelected; ++i)
1745 selectedIndices.push_back(
static_cast<size_t>(selected[i] - triangles_.begin()));
1748 triangles_.swap(newTriangles);
1749 vertices_.swap(newVertices);
1750 normals_.swap(newNormals);
1753 numBoundaryEdges_ += numOddBoundaryEdges;
1755 TTriangleIterators newSelected;
1756 newSelected.reserve(4 * numSelected);
1757 for (
size_t i = 0; i < numSelected; ++i)
1759 const TTriangleIterator t = triangles_.begin() +
static_cast<std::ptrdiff_t
>(newTriangleOffsets[selectedIndices[i]]);
1760 for (
int dt = 0; dt < 4; ++dt)
1762 newSelected.push_back(t + dt);
1765 selected.swap(newSelected);