library of assembled shared sources

http://lass.cocamware.com

triangle_mesh_3d.inl

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 
00044 
00045 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_TRIANGLE_MESH_3D_INL
00046 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_TRIANGLE_MESH_3D_INL
00047 
00048 #include "prim_common.h"
00049 #include "triangle_mesh_3d.h"
00050 #include "../stde/range_algorithm.h"
00051 #include "../stde/extended_iterator.h"
00052 #include "point_3dh.h"
00053 #include "point_2dh.h"
00054 #include <algorithm>
00055 
00056 namespace lass
00057 {
00058 namespace prim
00059 {
00060 
00061 // --- public --------------------------------------------------------------------------------------
00062 
00063 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00064 TriangleMesh3D<T, BHV, SH>::TriangleMesh3D()
00065 {
00066 }
00067 
00068 
00069 
00070 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00071 template 
00072 <
00073     typename VertexInputRange, typename IndexTriangleInputRange
00074 >
00075 TriangleMesh3D<T, BHV, SH>::TriangleMesh3D(
00076         const VertexInputRange& vertices, const IndexTriangleInputRange& triangles):
00077     vertices_(vertices.begin(), vertices.end()),
00078     normals_(),
00079     uvs_()
00080 {
00081     buildMesh(triangles);
00082 }
00083 
00084 
00085 
00086 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00087 template 
00088 <
00089     typename VertexInputRange, typename NormalInputRange,
00090     typename UvInputRange, typename IndexTriangleInputRange
00091 >
00092 TriangleMesh3D<T, BHV, SH>::TriangleMesh3D(
00093         const VertexInputRange& vertices, const NormalInputRange& normals, 
00094         const UvInputRange& uvs, const IndexTriangleInputRange& triangles):
00095     vertices_(vertices.begin(), vertices.end()),
00096     normals_(normals.begin(), normals.end()),
00097     uvs_(uvs.begin(), uvs.end())
00098 {
00099     buildMesh(triangles);
00100 }
00101 
00102 
00103 
00104 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00105 const typename TriangleMesh3D<T, BHV, SH>::TTriangles&
00106 TriangleMesh3D<T, BHV, SH>::triangles() const
00107 {
00108     return triangles_;
00109 }
00110 
00111 
00112 
00113 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00114 const typename TriangleMesh3D<T, BHV, SH>::TVertices&
00115 TriangleMesh3D<T, BHV, SH>::vertices() const
00116 {
00117     return vertices_;
00118 }
00119 
00120 
00121 
00122 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00123 const typename TriangleMesh3D<T, BHV, SH>::TNormals&
00124 TriangleMesh3D<T, BHV, SH>::normals() const
00125 {
00126     return normals_;
00127 }
00128 
00129 
00130 
00131 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00132 const typename TriangleMesh3D<T, BHV, SH>::TUvs&
00133 TriangleMesh3D<T, BHV, SH>::uvs() const
00134 {
00135     return uvs_;
00136 }
00137 
00138 
00139 
00140 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00141 template <typename OutputIterator> 
00142 OutputIterator TriangleMesh3D<T, BHV, SH>::indexTriangles(OutputIterator triangles) const
00143 {
00144     typename TTriangles::const_iterator triangle;
00145     for (triangle = triangles_.begin(); triangle != triangles_.end(); ++triangle)
00146     {
00147         TIndexTriangle indexTriangle;
00148         for (std::size_t k = 0; k < 3; ++k)
00149         {
00150             LASS_ASSERT(triangle->vertices[k]);
00151             indexTriangle.vertices[k] = triangle->vertices[k] - &vertices_.front();
00152             indexTriangle.normals[k] = triangle->normals[k] ?
00153                 triangle->normals[k] - &normals_.front() : IndexTriangle::null();
00154             indexTriangle.uvs[k] = triangle->uvs[k] ?
00155                 triangle->uvs[k] - &uvs_.front() : IndexTriangle::null();
00156         }
00157         *triangles++ = indexTriangle;
00158     }
00159     return triangles;
00160 }
00161 
00162 
00163 
00164 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00165 const typename TriangleMesh3D<T, BHV, SH>::TAabb
00166 TriangleMesh3D<T, BHV, SH>::aabb() const
00167 {
00168     LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
00169     return tree_.aabb();
00170 }
00171 
00172 
00173 
00174 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00175 const typename TriangleMesh3D<T, BHV, SH>::TValue
00176 TriangleMesh3D<T, BHV, SH>::area() const
00177 {
00178     TValue result = 0;
00179 
00180     typename TTriangles::const_iterator triangle;
00181     for (triangle = triangles_.begin(); triangle != triangles_.end(); ++triangle)
00182     {
00183         const TVector a = *triangle->vertices[1] - *triangle->vertices[0];
00184         const TVector b = *triangle->vertices[2] - *triangle->vertices[0];
00185         const TVector n = cross(a, b);
00186         result += n.norm() / 2;
00187     }
00188 
00189     return result;
00190 }
00191 
00192 
00193 
00194 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00195 void TriangleMesh3D<T, BHV, SH>::smoothNormals(TParam maxAngleInRadians)
00196 {
00197     const std::size_t numTriangles = triangles_.size();
00198     const std::size_t numVertices = vertices_.size();
00199     const TValue minDot = num::cos(maxAngleInRadians);
00200 
00201     // first pass: determine possible vertex normals
00202     //
00203     TNormals faceNormals(numTriangles);
00204     TNormals vertexNormals(numVertices);
00205     for (std::size_t i = 0; i < numTriangles; ++i)
00206     {
00207         const Triangle& triangle = triangles_[i];
00208 
00209         bool isDegenerated = false;
00210         for (std::size_t prevK = 2, k = 0; k < 3; prevK = k++)
00211         {
00212             isDegenerated |= (*triangle.vertices[k] == *triangle.vertices[prevK]);
00213         }
00214         if (isDegenerated)
00215         {
00216             faceNormals[i] = TVector();
00217             continue;
00218         }
00219 
00220         const TVector edges[3] =
00221         {
00222             (*triangle.vertices[1] - *triangle.vertices[0]).normal(),
00223             (*triangle.vertices[2] - *triangle.vertices[1]).normal(),
00224             (*triangle.vertices[0] - *triangle.vertices[2]).normal()
00225         };
00226         
00227         const TVector n = cross(edges[0], edges[1]).normal();
00228         faceNormals[i] = n;
00229 
00230         if (!n.isZero() && !n.isNaN())
00231         {
00232             for (std::size_t prevK = 2, k = 0; k < 3; prevK = k++)
00233             {
00234                 const std::size_t j = triangle.vertices[k] - &vertices_.front();
00235                 vertexNormals[j] += n * num::acos(-dot(edges[prevK], edges[k]));
00236             }
00237         }
00238     }
00239     stde::for_each_r(vertexNormals, std::mem_fun_ref(&TVector::normalize));
00240 
00241     // 2nd pass: determine wether to use vertex or face normal
00242     //
00243     std::vector<std::size_t> usedVertexNormals(vertices_.size(), IndexTriangle::null());
00244     std::vector<std::size_t> usedFaceNormals(triangles_.size(), IndexTriangle::null());
00245     std::size_t normalCount = 0;
00246     for (std::size_t i = 0; i < numTriangles; ++i)
00247     {
00248         const Triangle& triangle = triangles_[i];
00249         for (std::size_t k = 0; k < 3; ++k)
00250         {
00251             const std::size_t j = triangle.vertices[k] - &vertices_.front();
00252             if (dot(faceNormals[i], vertexNormals[j]) >= minDot)
00253             {
00254                 if (usedVertexNormals[j] == IndexTriangle::null())
00255                 {
00256                     usedVertexNormals[j] = normalCount++;
00257                 }
00258             }
00259             else
00260             {
00261                 if (usedFaceNormals[i] == IndexTriangle::null())
00262                 {
00263                     usedFaceNormals[i] = normalCount++;
00264                 }
00265             }
00266         }
00267     }
00268 
00269     // 2nd pass and a half: collect selected normals in normals_
00270     normals_.resize(normalCount);
00271     for (std::size_t i = 0; i < numTriangles; ++i)
00272     {
00273         if (usedFaceNormals[i] != IndexTriangle::null())
00274         {
00275             normals_[usedFaceNormals[i]] = faceNormals[i];
00276         }
00277     }
00278     for (std::size_t i = 0; i < numVertices; ++i)
00279     {
00280         if (usedVertexNormals[i] != IndexTriangle::null())
00281         {
00282             normals_[usedVertexNormals[i]] = vertexNormals[i];
00283         }
00284     }
00285 
00286     // 3rd pass: assign pointers to normals!
00287     //
00288     for (std::size_t i = 0; i < numTriangles; ++i)
00289     {
00290         Triangle& triangle = triangles_[i];
00291         for (std::size_t k = 0; k < 3; ++k)
00292         {
00293             const std::size_t j = triangle.vertices[k] - &vertices_.front();
00294             if (dot(faceNormals[i], vertexNormals[j]) >= minDot)
00295             {
00296                 LASS_ASSERT(usedVertexNormals[j] != IndexTriangle::null());
00297                 triangle.normals[k] = &normals_[usedVertexNormals[j]];
00298             }
00299             else
00300             {
00301                 LASS_ASSERT(usedFaceNormals[i] != IndexTriangle::null());
00302                 triangle.normals[k] = &normals_[usedFaceNormals[i]];
00303             }
00304         }
00305     }
00306 }
00307 
00308 
00309 
00310 /** remove all normals, so that faces become flat
00311  */
00312 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00313 void TriangleMesh3D<T, BHV, SH>::flatFaces()
00314 {
00315     normals_.clear();
00316     for (typename TTriangles::iterator triangle = triangles_.begin(); 
00317         triangle != triangles_.end(); ++triangle)
00318     {
00319         std::fill(triangle->normals, triangle->normals + 3, static_cast<TVector*>(0));
00320     }
00321 }
00322 
00323 
00324 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00325 void TriangleMesh3D<T, BHV, SH>::loopSubdivision(unsigned level)
00326 {
00327 #pragma LASS_TODO("refactor this function [Bramz]")
00328     if (triangles_.empty())
00329     {
00330         return;
00331     }
00332 
00333     while (level-- > 0)
00334     {
00335         // step I: subdivide triangles with simple interpolation
00336         //
00337         subdivide();
00338 
00339         // copying should "reduce" the extra reserve we don't need
00340         TVertices newVertices = vertices_;
00341         TNormals newNormals = normals_;
00342         TUvs newUvs = uvs_;
00343         const TPoint* const firstVertex = &vertices_[0];
00344         const TVector* const firstNormal = &normals_[0];
00345         const TUv* const firstUv = &uvs_[0];
00346 
00347         // step II: smooth mesh
00348         //
00349         //*
00350         TVertexTriangles vertexTriangles;
00351         findVertexTriangles(vertexTriangles);
00352         TVertexRing ring;
00353         TVertexRing creases;
00354         TNormalRing normalRing;
00355         TUvRing uvRing;
00356         const size_t numVertices = vertices_.size();
00357         for (size_t i = 0; i < numVertices; ++i)
00358         {
00359             if (const Triangle* const vertexTriangle = vertexTriangles[i])
00360             {
00361                 const TPoint& vertex = vertices_[i];    
00362                 findVertexRing(vertex, vertexTriangle, ring, creases, normalRing, uvRing);
00363                 const size_t nRing = ring.size();
00364                 const size_t nCreases = creases.size();
00365                 LASS_ASSERT(nRing >= 2);
00366                 if (nCreases == 2)
00367                 {
00368                     // crease or boundary (boundary edges count as creases)
00369                     newVertices[i] = TPoint(.75f * vertex.position() + .125f * (creases[0].position() + creases[1].position()));
00370                 }
00371                 else if (nRing > 2 && nCreases == 0)
00372                 {
00373                     // interior vertex
00374                     const TValue beta = nRing == 6 ? 
00375                         .125f : 2 * (.625f - num::sqr(.375f + .25f * num::cos(2 * TNumTraits::pi / nRing))) / nRing;
00376                     TVector newVertex = (1 - nRing * beta) * vertex.position();
00377                     for (size_t j = 0; j < nRing; ++j)
00378                     {
00379                         newVertex += beta * ring[j].position();
00380                     }
00381                     newVertices[i] = TPoint(newVertex);
00382                     if (!uvRing.empty())
00383                     {
00384                         LASS_ASSERT(uvRing.size() == nRing);
00385                         const size_t k = vertexTriangle->side(&vertex);
00386                         LASS_ASSERT(k < 3 && vertexTriangle->uvs[k]);
00387                         const TUv& uv = *vertexTriangle->uvs[k];
00388                         typename TUv::TVector newUv = (1 - nRing * beta) * uv.position();
00389                         for (size_t j = 0; j < nRing; ++j)
00390                         {
00391                             newUv += beta * uvRing[j].position();
00392                         }
00393                         newUvs[&uv - firstUv] = TUv(newUv);
00394                     }
00395                 }
00396             }
00397         }
00398         /**/
00399 
00400         // step III: adjust pointers and decrease crease levels
00401         //
00402         for (typename TTriangles::iterator triangle = triangles_.begin();
00403             triangle != triangles_.end(); ++triangle)
00404         {
00405             for (size_t k = 0; k < 3; ++k)
00406             {
00407                 triangle->vertices[k] = &newVertices[triangle->vertices[k] - firstVertex];
00408                 triangle->normals[k] = triangle->normals[k] ? &newNormals[triangle->normals[k] - firstNormal] : 0;
00409                 triangle->uvs[k] = triangle->uvs[k] ? &newUvs[triangle->uvs[k] - firstUv] : 0;
00410                 triangle->creaseLevel[k] = triangle->creaseLevel[k] > 0 ? triangle->creaseLevel[k] - 1 : 0;
00411             }
00412         }
00413         vertices_.swap(newVertices);
00414         normals_.swap(newNormals);
00415         uvs_.swap(newUvs);
00416     }
00417     tree_.reset(triangles_.begin(), triangles_.end());
00418 }
00419     
00420 
00421 
00422 /** automatically sews (unconnected) triangles by comparing geometrical vertices and normals
00423  */
00424 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00425 void TriangleMesh3D<T, BHV, SH>::autoSew()
00426 {
00427     typedef std::vector<PositionalEdge> TEdges;
00428 
00429     // I. make list of all boundary edges
00430     //
00431     const size_t numTriangles = triangles_.size();
00432     TEdges edges;
00433     edges.reserve(numBoundaryEdges_);
00434     for (size_t i = 0; i < numTriangles; ++i)
00435     {
00436         Triangle& triangle = triangles_[i];
00437         for (size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
00438         {
00439             if (triangle.others[k1] == 0)
00440             {
00441                 edges.push_back(PositionalEdge(&triangle, k1, k2));
00442             }
00443         }
00444     }
00445     LASS_ASSERT(edges.size() == numBoundaryEdges_);
00446     std::sort(edges.begin(), edges.end());
00447 
00448     // II. go over all boundary edges, and search one to sew with ...
00449     //
00450     for (size_t i = 0; i < numTriangles; ++i)
00451     {
00452         Triangle& triangle = triangles_[i];
00453         for (size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
00454         {
00455             if (triangle.others[k1] == 0)
00456             {
00457                 const PositionalEdge bait(&triangle, k2, k1); // reversed edge
00458                 const typename TEdges::const_iterator haul = 
00459                     std::lower_bound(edges.begin(), edges.end(), bait);
00460                 if (haul != edges.end() && !(bait < *haul) && 
00461                     haul->triangle->others[haul->k1] == 0)
00462                 {
00463                     triangle.others[k1] = haul->triangle;
00464                     haul->triangle->others[haul->k1] = &triangle;
00465                     LASS_ASSERT(numBoundaryEdges_ >= 2);
00466                     numBoundaryEdges_ -= 2;
00467                     for (size_t s = 1; s <= 2; ++s)
00468                     {
00469                         // turn right/left, and replace all otherV by v
00470                         Triangle* other = haul->triangle;
00471                         size_t k = s == 1 ? haul->k2 : haul->k1;
00472                         const TPoint* const v = 
00473                             triangle.vertices[s == 1 ? k1 : k2];
00474                         const TPoint* const otherV = other->vertices[k];
00475                         LASS_ASSERT(*v == *otherV);
00476                         if (v != otherV)
00477                         {
00478                             do 
00479                             {
00480                                 LASS_ASSERT(other->vertices[k] == otherV);
00481                                 other->vertices[k] = v;
00482                                 other = other->others[
00483                                     (k + (s == 1 ? 0 : 2)) % 3];
00484                                 k = other ? other->side(otherV) : 3;
00485                             }
00486                             while (other && k < 3);
00487                         }
00488                     }
00489                 }
00490             }
00491         }
00492     }
00493 }
00494 
00495 
00496 
00497 /** automatically assign crease levels to edges with discontinued normals
00498  */
00499 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00500 void TriangleMesh3D<T, BHV, SH>::autoCrease(unsigned level)
00501 {
00502     const size_t numTriangles = triangles_.size();
00503     for (size_t i = 0; i < numTriangles; ++i)
00504     {
00505         Triangle& triangle = triangles_[i];
00506         for (size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
00507         {
00508             triangle.creaseLevel[k1] = 0;
00509             if (Triangle* other = triangle.others[k1])
00510             {
00511                 const size_t otherK1 = other->side(triangle.vertices[k1]);
00512                 const size_t otherK2 = (otherK1 + 2) % 3;
00513                 LASS_ASSERT(otherK1 < 3 && otherK2 == other->side(triangle.vertices[k2]));
00514                 const bool hasNormals =
00515                     triangle.normals[k1] && triangle.normals[k2] && 
00516                     other->normals[otherK1] && other->normals[otherK2];
00517                 const bool isCrease = !hasNormals ||
00518                     *triangle.normals[k1] != *other->normals[otherK1] ||
00519                     *triangle.normals[k2] != *other->normals[otherK2];
00520                 triangle.creaseLevel[k1] = isCrease ? level : 0;
00521             }
00522         }
00523     }
00524 }
00525 
00526 
00527 
00528 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00529 const Result TriangleMesh3D<T, BHV, SH>::intersect(const TRay& ray, TTriangleIterator& triangle,
00530         TReference t, TParam tMin, IntersectionContext* context) const
00531 {
00532     LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
00533     const TTriangleIterator candidate =  tree_.intersect(ray, t, tMin);
00534     if (candidate == triangles_.end())
00535     {
00536         return rNone;
00537     }
00538     triangle = candidate;
00539     
00540     if (context)
00541     {
00542         TValue temp;
00543         const Result r = triangle->intersect(ray, temp, tMin, context);
00544         LASS_ASSERT(r == rOne && t == temp);
00545     }
00546 
00547     return rOne;
00548 }
00549 
00550 
00551 
00552 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00553 const bool TriangleMesh3D<T, BHV, SH>::intersects(const TRay& ray, TParam tMin, TParam tMax) const
00554 {
00555     LASS_ASSERT(tree_.isEmpty() == triangles_.empty());
00556     return tree_.intersects(ray, tMin, tMax);
00557 }
00558 
00559 
00560 
00561 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00562 void TriangleMesh3D<T, BHV, SH>::swap(TSelf& other)
00563 {
00564     tree_.swap(other.tree_);
00565     triangles_.swap(other.trtriangles_ee_);
00566     vertices_.swap(other.vertices_);
00567     normals_.swap(other.normals_);
00568     uvs_.swap(other.uvs_);
00569 }
00570 
00571 
00572 
00573 // --- Triangle ------------------------------------------------------------------------------------
00574 
00575 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00576 const Result TriangleMesh3D<T, BHV, SH>::Triangle::intersect(const TRay& ray, 
00577         TReference t, TParam tMin, IntersectionContext* context) const
00578 {
00579     LASS_ASSERT(vertices[0] && vertices[1] && vertices[2]);
00580     const TPoint point0 = *vertices[0];
00581     const TVector dPoint_dR = *vertices[1] - point0;
00582     const TVector dPoint_dS = *vertices[2] - point0;
00583 
00584     TValue r, s;
00585     const Result hit = impl::intersectTriangle3D(
00586         point0, dPoint_dR, dPoint_dS, ray.support(), ray.direction(), r, s, t, tMin);
00587     if (hit != rOne)
00588     {
00589         return hit;
00590     }
00591 
00592     if (context)
00593     {
00594         TUv dRs_dU(1, 0);
00595         TUv dRs_dV(0, 1);
00596         if (uvs[0])
00597         {
00598             LASS_ASSERT(uvs[1] && uvs[2]);
00599             const TUv uv0 = *uvs[0];
00600             const typename TUv::TVector dUv_dR = *uvs[1] - uv0;
00601             const typename TUv::TVector dUv_dS = *uvs[2] - uv0;
00602             context->uv = uv0 + r * dUv_dR + s * dUv_dS;
00603         
00604             const TValue matrix[4] = { dUv_dR.x, dUv_dS.x, dUv_dR.y, dUv_dS.y };
00605             TValue solution[4] = { 1, 0, 0, 1 };
00606             num::impl::cramer2<TValue>(matrix, solution, solution + 4);
00607             dRs_dU = TUv(solution[0], solution[2]);
00608             dRs_dV = TUv(solution[1], solution[3]);
00609             context->dPoint_dU = dPoint_dR * dRs_dU.x + dPoint_dS * dRs_dU.y;
00610             context->dPoint_dV = dPoint_dR * dRs_dV.x + dPoint_dS * dRs_dV.y;
00611         }
00612         else
00613         {
00614             context->uv = TUv(r, s);
00615             context->dPoint_dU = dPoint_dR;
00616             context->dPoint_dV = dPoint_dS;
00617         }
00618 
00619         context->geometricNormal = cross(dPoint_dR, dPoint_dS).normal();
00620         if (normals[0])
00621         {
00622             LASS_ASSERT(normals[1] && normals[2]);
00623             const TVector normal0 = *normals[0];
00624             const TVector dNormal_dR = *normals[1] - normal0;
00625             const TVector dNormal_dS = *normals[2] - normal0;
00626             context->normal = (normal0 + r * dNormal_dR + s * dNormal_dS).normal();
00627             context->dNormal_dU = dNormal_dR * dRs_dU.x + dNormal_dS * dRs_dU.y;
00628             context->dNormal_dV = dNormal_dR * dRs_dV.x + dNormal_dS * dRs_dV.y;
00629         }
00630         else
00631         {
00632             context->normal = context->geometricNormal;
00633             context->dNormal_dU = TVector();
00634             context->dNormal_dV = TVector();
00635         }
00636     }
00637     return rOne;
00638 }
00639 
00640 
00641 
00642 template <typename T, template <typename, typename, typename> class BHV, typename SH> inline
00643 const size_t TriangleMesh3D<T, BHV, SH>::Triangle::side(const TPoint* vertex) const 
00644 { 
00645     return vertices[0] == vertex ? 0 : (vertices[1] == vertex ? 1 : (vertices[2] == vertex ? 2 : size_t(-1))); 
00646 }
00647 
00648 
00649 
00650 // --- private -------------------------------------------------------------------------------------
00651 
00652 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00653 template <typename IndexTriangleInputRange>
00654 void TriangleMesh3D<T, BHV, SH>::buildMesh(const IndexTriangleInputRange& triangles)
00655 {
00656     const std::size_t sizeVertices = vertices_.size();
00657     const std::size_t sizeNormals = normals_.size();
00658     const std::size_t sizeUvs = uvs_.size();
00659 
00660     for (typename IndexTriangleInputRange::const_iterator i = triangles.begin(); i != triangles.end(); ++i)
00661     {
00662         TTriangle triangle;
00663         size_t numNormals = 0;
00664         size_t numUvs = 0;
00665         for (std::size_t k = 0; k < 3; ++k)
00666         {
00667             triangle.others[k] = 0;
00668             triangle.creaseLevel[k] = 0;
00669 
00670             const std::size_t vertex = i->vertices[k];
00671             triangle.vertices[k] = &vertices_[LASS_ENFORCE_INDEX(vertex, sizeVertices)];
00672 
00673             const std::size_t normal = i->normals[k];
00674             if (normal != IndexTriangle::null())
00675             {               
00676                 triangle.normals[k] = &normals_[LASS_ENFORCE_INDEX(normal, sizeNormals)];
00677                 ++numNormals;
00678             }
00679             else
00680             {
00681                 triangle.normals[k] = 0;
00682             }
00683 
00684             const std::size_t uv = i->uvs[k];
00685             if (uv != IndexTriangle::null())
00686             {
00687                 triangle.uvs[k] = &uvs_.begin()[LASS_ENFORCE_INDEX(uv, sizeUvs)];
00688                 ++numUvs;
00689             }
00690             else
00691             {
00692                 triangle.uvs[k] = 0;
00693             }
00694         }
00695 
00696         if (!(numNormals == 0 || numNormals == 3))
00697         {
00698             LASS_THROW("Each triangle must have either zero or three normals vectors");
00699         }
00700         if (!(numUvs == 0 || numUvs == 3))
00701         {
00702             LASS_THROW("Each triangle must have either zero or three uv coordinates");
00703         }
00704 
00705         triangles_.push_back(triangle);
00706     }
00707 
00708     connectTriangles();
00709     tree_.reset(triangles_.begin(), triangles_.end());
00710 }
00711 
00712 
00713 
00714 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00715 void TriangleMesh3D<T, BHV, SH>::findVertexTriangles(TVertexTriangles& vertexTriangles) const
00716 {
00717     TVertexTriangles result(vertices_.size(), 0);
00718     const TPoint* const firstVertex = &vertices_[0];
00719     for (typename TTriangles::const_iterator i = triangles_.begin(); i != triangles_.end(); ++i)
00720     {
00721         const Triangle& triangle = *i;
00722         for (size_t k = 0; k < 3; ++k)
00723         {
00724             const size_t j = triangle.vertices[k] - firstVertex;
00725             LASS_ASSERT(j < result.size());
00726             result[j] = &triangle;
00727         }
00728     }
00729     vertexTriangles.swap(result);
00730 }
00731 
00732 
00733 
00734 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00735 void TriangleMesh3D<T, BHV, SH>::connectTriangles()
00736 {
00737     typedef std::vector<LogicalEdge> TEdges;
00738 
00739     numBoundaryEdges_ = 0;
00740     const size_t numTriangles = triangles_.size();
00741     if (numTriangles == 0)
00742     {
00743         return;
00744     }
00745 
00746     // step 1: build list of edges and sort.
00747     //
00748     TEdges edges;
00749     edges.reserve(3 * numTriangles);
00750     for (size_t i = 0; i < numTriangles; ++i)
00751     {
00752         Triangle& triangle = triangles_[i];
00753         for (std::size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
00754         {
00755             edges.push_back(LogicalEdge(
00756                 &triangle, triangle.vertices[k1], triangle.vertices[k2]));
00757         }
00758     }
00759     std::sort(edges.begin(), edges.end());
00760 
00761     // step 2: build topological information of triangles
00762     //
00763     for (size_t i = 0; i < numTriangles; ++i)
00764     {
00765         Triangle& triangle = triangles_[i];
00766         for (std::size_t k1 = 2, k2 = 0; k2 < 3; k1 = k2++)
00767         {
00768             const LogicalEdge bait(
00769                 0, triangle.vertices[k2], triangle.vertices[k1]); // reversed edge
00770             const typename TEdges::const_iterator haul = std::lower_bound(
00771                 edges.begin(), edges.end(), bait);
00772             if (haul != edges.end() && !(bait < *haul))
00773             {
00774                 triangle.others[k1] = haul->triangle;
00775             }
00776             else
00777             {
00778                 triangle.others[k1] = 0;
00779                 ++numBoundaryEdges_;
00780             }
00781         }
00782     }
00783 }
00784 
00785 
00786 
00787 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00788 void TriangleMesh3D<T, BHV, SH>::findVertexRing(
00789         const TPoint& vertex, const Triangle* vertexTriangle, TVertexRing& ring, 
00790         TVertexRing& creases, TNormalRing& normals, TUvRing& uvs) const
00791 {
00792     ring.resize(0); // normaly, this should not shrink memory (*)
00793     creases.resize(0);
00794     normals.resize(0);
00795     uvs.resize(0);
00796 
00797     bool hasUvRing = true;
00798     const TUv* vertexUv = 0;
00799     const Triangle* triangle = vertexTriangle;
00800     do
00801     {
00802         const size_t k = triangle->side(&vertex);
00803         LASS_ASSERT(k < 3);
00804         const size_t kCcw = (k + 2) % 3;
00805         const TPoint& neighbour = *triangle->vertices[kCcw];
00806         const Triangle* const other = triangle->others[kCcw];
00807         if (triangle->creaseLevel[kCcw] > 0 || !other)
00808         {
00809             //LASS_ASSERT(triangle->others[kCcw]);
00810             creases.push_back(neighbour);
00811         }
00812 
00813         if (!vertexUv)
00814         {
00815             vertexUv = triangle->uvs[k];
00816         }
00817         hasUvRing &= vertexUv != 0 && vertexUv == triangle->uvs[k];
00818         if (hasUvRing)
00819         {
00820             LASS_ASSERT(triangle->uvs[kCcw]);
00821             uvs.push_back(*triangle->uvs[kCcw]);
00822         }
00823 
00824         if (!other) 
00825         {
00826             // we've hit a boundary edge, turn back to other "end".
00827             // ring will only consist of that one + this neighbour
00828             //
00829             const Triangle* triangle2 = vertexTriangle;
00830             const TPoint* neighbour2 = 0;
00831             while (triangle2)
00832             {
00833                 const size_t k = triangle2->side(&vertex);
00834                 LASS_ASSERT(k < 3);
00835                 const size_t kCw = (k + 1) % 3;
00836                 neighbour2 = triangle2->vertices[kCw];
00837                 const Triangle* other2 = triangle2->others[k];
00838                 if (triangle2->creaseLevel[kCw] > 0 || !other2)
00839                 {
00840                     //LASS_ASSERT(triangle2->others[kCw]);
00841                     creases.push_back(*neighbour2);
00842                 }
00843                 triangle2 = other2;
00844             }
00845             ring.resize(1, *neighbour2);
00846             hasUvRing = false;
00847         }
00848         ring.push_back(neighbour);
00849         triangle = other;
00850     }
00851     while (triangle && triangle != vertexTriangle);
00852 
00853     if (!hasUvRing)
00854     {
00855         uvs.resize(0);
00856     }
00857     // (*) so says the standard, as as we all know, _every_ compiler follows the standard, don't they?
00858 }
00859 
00860 
00861 
00862 /** subdivide every triangle in 4 new ones by splitting the edges
00863  *  @warning tree_ will be reset and must be recreated manually after calling this function!
00864  */
00865 template <typename T, template <typename, typename, typename> class BHV, typename SH>
00866 void TriangleMesh3D<T, BHV, SH>::subdivide()
00867 {
00868     if (triangles_.empty())
00869     {
00870         return;
00871     }
00872 
00873     const size_t numTriangles = triangles_.size();
00874     const size_t numVertices = vertices_.size();
00875     const size_t numUvs = uvs_.size();
00876     const size_t numNormals = normals_.size();
00877     LASS_ASSERT((3 * numTriangles + numBoundaryEdges_) % 2 == 0);
00878     const size_t numOddVertices = (3 * numTriangles + numBoundaryEdges_) / 2;
00879 
00880     TTriangles newTriangles(4 * numTriangles);
00881     TVertices newVertices = vertices_;
00882     TNormals newNormals = normals_;
00883     TUvs newUvs = uvs_;
00884     newVertices.reserve(numVertices + numOddVertices);
00885     newNormals.reserve(numNormals + 3 * numTriangles);
00886     newUvs.reserve(numUvs + 3 * numTriangles);
00887 
00888     const Triangle* const firstTriangle = &triangles_[0];
00889     const TPoint* const firstVertex = &vertices_[0];
00890     const TVector* const firstNormal = &normals_[0];
00891     const TUv* const firstUv = &uvs_[0];
00892 
00893     //            2             - original vertex numbers are on outside
00894     //            *             - new vertex numbers are on inside
00895     //           /2\            - triangle numbers are between braces: (#)
00896     //          /   \           - as always everything is counter clockwise
00897     //         / (2) \          - number of edges (for 'others'): same number as it tail.
00898     //        /0     1\         - triangle (3) is called the oddTriangle
00899     //       *---------*
00900     //      /2\2     1/2\
00901     //     /   \ (3) /   \
00902     //    / (0) \   / (1) \
00903     //   /0     1\0/0     1\
00904     //  *---------*---------*
00905     // 0                     1
00906     //
00907     for (size_t i = 0; i < numTriangles; ++i)
00908     {
00909         const Triangle& triangle = triangles_[i];
00910         Triangle* const newTris = &newTriangles[4 * i];
00911         Triangle& oddTriangle = newTris[3];
00912     
00913         // compute new vertices, normals and Uvs, and store in odd triangle
00914         //
00915         for (size_t k0 = 2, k1 = 0; k1 < 3; k0 = k1++)
00916         {
00917             const Triangle* const other = triangle.others[k0];
00918             Triangle* const oddOther = other ? &newTriangles[4 * (other - firstTriangle) + 3] : 0;
00919             const size_t h0 = other ? other->side(triangle.vertices[k1]) : size_t(-1);
00920             const size_t h1 = other ? other->side(triangle.vertices[k0]) : size_t(-1);
00921             LASS_ASSERT(h0 < 3 && h1 == (h0 + 1) % 3 || other == 0);
00922 
00923             if (!oddTriangle.vertices[k0])
00924             {   
00925                 LASS_ASSERT(newVertices.size() < newVertices.capacity());
00926                 newVertices.push_back(TPoint(.5 * (triangle.vertices[k0]->position() + triangle.vertices[k1]->position())));
00927                 oddTriangle.vertices[k0] = &newVertices.back();
00928                 if (other)
00929                 {
00930                     oddOther->vertices[h0] = &newVertices.back();
00931                 }
00932             }
00933             if (triangle.normals[k0] && !oddTriangle.normals[k0])
00934             {
00935                 LASS_ASSERT(triangle.normals[k1]);
00936                 LASS_ASSERT(newNormals.size() < newNormals.capacity());
00937                 newNormals.push_back(.5 * (*triangle.normals[k0] + *triangle.normals[k1]));
00938                 oddTriangle.normals[k0] = &newNormals.back();
00939                 if (other && triangle.normals[k0] == other->normals[h1] && triangle.normals[k1] == other->normals[h0])
00940                 {
00941                     oddOther->normals[h0] = &newNormals.back();
00942                 }
00943             }       
00944             if (triangle.uvs[k0] && !oddTriangle.uvs[k0])
00945             {
00946                 LASS_ASSERT(newUvs.size() < newUvs.capacity());
00947                 LASS_ASSERT(triangle.uvs[k1]);
00948                 newUvs.push_back(TUv(.5 * (triangle.uvs[k0]->position() + triangle.uvs[k1]->position())));
00949                 oddTriangle.uvs[k0] = &newUvs.back();
00950                 if (other && triangle.uvs[k0] == other->uvs[h1] && triangle.uvs[k1] == other->uvs[h0])
00951                 {
00952                     oddOther->uvs[h0] = &newUvs.back();
00953                 }
00954             }       
00955             oddTriangle.others[k0] = &newTris[k1];
00956             oddTriangle.creaseLevel[k0] = 0;
00957         }
00958 
00959         // connect other triangles
00960         //
00961         for (size_t k0 = 0, k1 = 1, k2 = 2; k0 < 3; k1 = k2, k2 = k0, ++k0)
00962         {
00963             Triangle& newTriangle = newTris[k0];
00964             newTriangle.vertices[k0] = &newVertices[triangle.vertices[k0] - firstVertex];
00965             newTriangle.vertices[k1] = oddTriangle.vertices[k0];
00966             newTriangle.vertices[k2] = oddTriangle.vertices[k2];
00967             newTriangle.normals[k0] = triangle.normals[k0] ? &newNormals[triangle.normals[k0] - firstNormal] : 0;
00968             newTriangle.normals[k1] = oddTriangle.normals[k0];
00969             newTriangle.normals[k2] = oddTriangle.normals[k2];
00970             newTriangle.uvs[k0] = triangle.uvs[k0] ? &newUvs[triangle.uvs[k0] - firstUv] : 0;
00971             newTriangle.uvs[k1] = oddTriangle.uvs[k0];
00972             newTriangle.uvs[k2] = oddTriangle.uvs[k2];
00973             if (const Triangle* other0 = triangle.others[k0])
00974             {
00975                 const size_t j = other0 - firstTriangle;
00976                 const size_t h = other0->side(triangle.vertices[k0]);
00977                 LASS_ASSERT(h < 3);
00978                 Triangle& newOther = newTriangles[4 * j + h];
00979                 LASS_ASSERT(newOther.others[(h + 2) % 3] == 0 || newOther.others[(h + 2) % 3] == &newTriangle);
00980                 newTriangle.others[k0] = &newOther;
00981             }
00982             newTriangle.others[k1] = &oddTriangle;
00983             if (const Triangle* other2 = triangle.others[k2])
00984             {
00985                 const size_t j = other2 - firstTriangle;
00986                 const size_t h = other2->side(triangle.vertices[k0]);
00987                 LASS_ASSERT(h < 3);
00988                 Triangle& newOther = newTriangles[4 * j + h];
00989                 LASS_ASSERT(newOther.others[h] == 0 || newOther.others[h] == &newTriangle);
00990                 newTriangle.others[k2] = &newOther;
00991             }
00992             newTriangle.creaseLevel[k0] = triangle.creaseLevel[k0];
00993             newTriangle.creaseLevel[k1] = 0;
00994             newTriangle.creaseLevel[k2] = triangle.creaseLevel[k2];
00995         }
00996     }
00997 
00998     triangles_.swap(newTriangles);
00999     vertices_.swap(newVertices);
01000     normals_.swap(newNormals);
01001     uvs_.swap(newUvs);
01002     tree_.reset();
01003     numBoundaryEdges_ *= 2;
01004 }
01005 
01006 
01007 
01008 // --- free ----------------------------------------------------------------------------------------
01009 
01010 
01011 
01012 }
01013 
01014 }
01015 
01016 #endif
01017 
01018 // EOF

Generated on Mon Nov 10 14:22:01 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo