1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef LoopBlinnLocalTriangulator_h 27 #define LoopBlinnLocalTriangulator_h 28 29 #include "FloatPoint.h" 30 #include "FloatPoint3D.h" 31 #include "LoopBlinnConstants.h" 32 #include <wtf/Assertions.h> 33 #include <wtf/Noncopyable.h> 34 35 namespace WebCore { 36 37 // Performs a localized triangulation of the triangle mesh 38 // corresponding to the four control point vertices of a cubic curve 39 // segment. 40 class LoopBlinnLocalTriangulator { 41 WTF_MAKE_NONCOPYABLE(LoopBlinnLocalTriangulator); 42 public: 43 // The vertices that the triangulator operates upon, containing both 44 // the position information as well as the cubic texture 45 // coordinates. 46 class Vertex { 47 WTF_MAKE_NONCOPYABLE(Vertex); 48 public: 49 Vertex() 50 { 51 resetFlags(); 52 } 53 54 const FloatPoint& xyCoordinates() const 55 { 56 return m_xyCoordinates; 57 } 58 59 const FloatPoint3D& klmCoordinates() const 60 { 61 return m_klmCoordinates; 62 } 63 64 // Sets the position and texture coordinates of the vertex. 65 void set(float x, float y, 66 float k, float l, float m) 67 { 68 m_xyCoordinates.set(x, y); 69 m_klmCoordinates.set(k, l, m); 70 } 71 72 // Flags for walking from the start vertex to the end vertex. 73 bool end() 74 { 75 return m_end; 76 } 77 78 void setEnd(bool end) 79 { 80 m_end = end; 81 } 82 83 bool marked() 84 { 85 return m_marked; 86 } 87 88 void setMarked(bool marked) 89 { 90 m_marked = marked; 91 } 92 93 bool interior() 94 { 95 return m_interior; 96 } 97 98 void setInterior(bool interior) 99 { 100 m_interior = interior; 101 } 102 103 void resetFlags() 104 { 105 m_end = false; 106 m_marked = false; 107 m_interior = false; 108 } 109 110 private: 111 // 2D coordinates of the vertex in the plane. 112 FloatPoint m_xyCoordinates; 113 // Cubic texture coordinates for rendering the curve. 114 FloatPoint3D m_klmCoordinates; 115 116 // Flags for walking from the start vertex to the end vertex. 117 bool m_end; 118 bool m_marked; 119 bool m_interior; 120 }; 121 122 // The triangles the Triangulator produces. 123 class Triangle { 124 public: 125 Triangle() 126 { 127 m_vertices[0] = 0; 128 m_vertices[1] = 0; 129 m_vertices[2] = 0; 130 } 131 132 // Gets the vertex at the given index, 0 <= index < 3. 133 Vertex* getVertex(int index) 134 { 135 ASSERT(index >= 0 && index < 3); 136 return m_vertices[index]; 137 } 138 139 // Returns true if this triangle contains the given vertex (by 140 // identity, not geometrically). 141 bool contains(Vertex* v); 142 143 // Returns the vertex following the current one in the specified 144 // direction, counterclockwise or clockwise. 145 Vertex* nextVertex(Vertex* current, bool traverseCounterClockwise); 146 147 // Sets the vertices of this triangle, potentially reordering them 148 // to produce a canonical orientation. 149 void setVertices(Vertex* v0, 150 Vertex* v1, 151 Vertex* v2) 152 { 153 m_vertices[0] = v0; 154 m_vertices[1] = v1; 155 m_vertices[2] = v2; 156 makeCounterClockwise(); 157 } 158 159 private: 160 // Returns the index [0..2] associated with the given vertex, or 161 // -1 if not found. 162 int indexForVertex(Vertex* vertex); 163 164 // Reorders the vertices in this triangle to make them 165 // counterclockwise when viewed in the 2D plane, in order to 166 // achieve a canonical ordering. 167 void makeCounterClockwise(); 168 169 // Note: these are raw pointers because they point to the 170 // m_vertices contained in the surrounding triangulator. 171 Vertex* m_vertices[3]; 172 }; 173 174 LoopBlinnLocalTriangulator(); 175 176 // Resets the triangulator's state. After each triangulation and 177 // before the next, call this to re-initialize the internal 178 // vertices' state. 179 void reset(); 180 181 // Returns a mutable vertex stored in the triangulator. Use this to 182 // set up the vertices before a triangulation. 183 Vertex* getVertex(int index) 184 { 185 ASSERT(index >= 0 && index < 4); 186 return &m_vertices[index]; 187 } 188 189 enum InsideEdgeComputation { 190 ComputeInsideEdges, 191 DontComputeInsideEdges 192 }; 193 194 // Once the vertices' contents have been set up, call triangulate() 195 // to recompute the triangles. 196 // 197 // If computeInsideEdges is ComputeInsideEdges, then sideToFill 198 // will be used to determine which side of the cubic curve defined 199 // by the four control points is to be filled. 200 // 201 // The triangulation obeys the following guarantees: 202 // - If the convex hull is a quadrilateral, then the shortest edge 203 // will be chosen for the cut into two triangles. 204 // - If one of the vertices is contained in the triangle spanned 205 // by the other three, three triangles will be produced. 206 void triangulate(InsideEdgeComputation computeInsideEdges, 207 LoopBlinnConstants::FillSide sideToFill); 208 209 // Number of triangles computed by triangulate(). 210 int numberOfTriangles() const 211 { 212 return m_numberOfTriangles; 213 } 214 215 // Returns the computed triangle at index, 0 <= index < numberOfTriangles(). 216 Triangle* getTriangle(int index) 217 { 218 ASSERT(index >= 0 && index < m_numberOfTriangles); 219 return &m_triangles[index]; 220 } 221 222 // Number of vertices facing the inside of the shape, if 223 // ComputeInsideEdges was passed when triangulate() was called. 224 int numberOfInteriorVertices() const 225 { 226 return m_numberOfInteriorVertices; 227 } 228 229 // Fetches the given interior vertex, 0 <= index < numberOfInteriorVertices(). 230 Vertex* getInteriorVertex(int index) 231 { 232 ASSERT(index >= 0 && index < m_numberOfInteriorVertices); 233 return m_interiorVertices[index]; 234 } 235 236 private: 237 void triangulateHelper(LoopBlinnConstants::FillSide sideToFill); 238 239 // Adds a triangle to the triangulation. 240 void addTriangle(Vertex* v0, Vertex* v1, Vertex* v2); 241 242 // Adds a vertex to the list of interior vertices. 243 void addInteriorVertex(Vertex* v); 244 245 // Indicates whether the edge between vertex v0 and v1 is shared 246 // between two or more triangles. 247 bool isSharedEdge(Vertex* v0, Vertex* v1); 248 249 // The vertices being triangulated. 250 Vertex m_vertices[4]; 251 252 // The vertices corresponding to the edges facing the inside of the 253 // shape, in order from the start vertex to the end vertex. The more 254 // general triangulation algorithm tessellates this interior region. 255 Vertex* m_interiorVertices[4]; 256 // The number of interior vertices that are valid for the current 257 // triangulation. 258 int m_numberOfInteriorVertices; 259 260 // There can be at most three triangles computed by this local 261 // algorithm, which occurs when one of the vertices is contained in 262 // the triangle spanned by the other three. Most of the time the 263 // algorithm computes two triangles. 264 Triangle m_triangles[3]; 265 int m_numberOfTriangles; 266 }; 267 268 } // namespace WebCore 269 270 #endif // LoopBlinnLocalTriangulator_h 271