2 * Original code in the public domain -- castanyo@yahoo.es
4 * Modifications copyright (c) 2011, Blender Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "subd_build.h"
32 #include "subd_edge.h"
33 #include "subd_face.h"
34 #include "subd_mesh.h"
35 #include "subd_patch.h"
36 #include "subd_split.h"
37 #include "subd_vert.h"
39 #include "util_debug.h"
40 #include "util_foreach.h"
50 pair<Key, SubdEdge*> em;
52 foreach(SubdVert *vertex, verts)
56 foreach(SubdFace *face, faces)
65 SubdVert *SubdMesh::add_vert(const float3& co)
67 SubdVert *v = new SubdVert(verts.size());
74 SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
76 int index[3] = {v0, v1, v2};
77 return add_face(index, 3);
80 SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
82 int index[4] = {v0, v1, v2, v3};
83 return add_face(index, 4);
86 SubdFace *SubdMesh::add_face(int *index, int num)
88 /* test non-manifold cases */
89 if(!can_add_face(index, num)) {
90 /* we could try to add face in opposite winding instead .. */
91 fprintf(stderr, "Warning: non manifold mesh, invalid face '%lu'.\n", faces.size());
95 SubdFace *f = new SubdFace(faces.size());
97 SubdEdge *first_edge = NULL;
98 SubdEdge *last = NULL;
99 SubdEdge *current = NULL;
102 for(int i = 0; i < num-1; i++) {
103 current = add_edge(index[i], index[i+1]);
104 assert(current != NULL);
109 last->next = current;
110 current->prev = last;
113 first_edge = current;
118 current = add_edge(index[num-1], index[0]);
119 assert(current != NULL);
123 last->next = current;
124 current->prev = last;
126 current->next = first_edge;
127 first_edge->prev = current;
129 f->edge = first_edge;
135 bool SubdMesh::can_add_face(int *index, int num)
138 for(int i = 0; i < num-1; i++)
139 if(!can_add_edge(index[i], index[i+1]))
142 return can_add_edge(index[num-1], index[0]);
145 bool SubdMesh::can_add_edge(int i, int j)
147 /* check for degenerate edge */
151 /* make sure edge has not been added yet. */
152 return find_edge(i, j) == NULL;
155 SubdEdge *SubdMesh::add_edge(int i, int j)
160 SubdEdge *pair = find_edge(j, i);
163 /* create edge with same id */
164 edge = new SubdEdge(pair->id + 1);
166 /* link edge pairs */
170 /* not sure this is necessary? */
171 pair->vert->edge = pair;
175 edge = new SubdEdge(2*edges.size());
177 /* add only unpaired edges */
178 edges.push_back(edge);
181 /* assign vertex and put into map */
182 edge->vert = verts[i];
183 edge_map[Key(i, j)] = edge;
185 /* face and next are set by add_face */
190 SubdEdge *SubdMesh::find_edge(int i, int j)
192 map<Key, SubdEdge*>::const_iterator it = edge_map.find(Key(i, j));
194 return (it == edge_map.end())? NULL: it->second;
197 bool SubdMesh::link_boundary()
199 /* link boundary edges once the mesh has been created */
202 /* create boundary edges */
203 int num_edges = edges.size();
205 for(int e = 0; e < num_edges; e++) {
206 SubdEdge *edge = edges[e];
208 if(edge->pair == NULL) {
209 SubdEdge *pair = new SubdEdge(edge->id + 1);
211 int i = edge->from()->id;
212 int j = edge->to()->id;
214 assert(edge_map.find(Key(j, i)) == edge_map.end());
216 pair->vert = verts[j];
217 edge_map[Key(j, i)] = pair;
226 /* link boundary edges */
227 for(int e = 0; e < num_edges; e++) {
228 SubdEdge *edge = edges[e];
230 if(edge->pair->face == NULL)
231 link_boundary_edge(edge->pair);
234 /* detect boundary intersections */
235 int boundaryIntersections = 0;
236 int num_verts = verts.size();
238 for(int v = 0; v < num_verts; v++) {
239 SubdVert *vertex = verts[v];
241 int boundarySubdEdges = 0;
242 for(SubdVert::EdgeIterator it(vertex->edges()); !it.isDone(); it.advance())
243 if(it.current()->is_boundary())
246 if(boundarySubdEdges > 2) {
247 assert((boundarySubdEdges & 1) == 0);
248 boundaryIntersections++;
252 if(boundaryIntersections != 0) {
253 fprintf(stderr, "Invalid mesh, boundary intersections found!\n");
260 void SubdMesh::link_boundary_edge(SubdEdge *edge)
262 /* link this boundary edge. */
264 /* make sure next pointer has not been set. */
265 assert(edge->face == NULL);
266 assert(edge->next == NULL);
268 SubdEdge *next = edge;
270 while(next->pair->face != NULL) {
272 SubdEdge *e = next->pair->next;
274 while(e->next != next->pair)
280 edge->next = next->pair;
281 next->pair->prev = edge;
283 /* adjust vertex edge, so that it's the boundary edge. (required for is_boundary()) */
284 if(edge->vert->edge != edge)
285 edge->vert->edge = edge;
288 void SubdMesh::tesselate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
290 SubdBuilder *builder = SubdBuilder::create(linear);
291 int num_faces = faces.size();
293 for(int f = 0; f < num_faces; f++) {
294 SubdFace *face = faces[f];
295 Patch *patch = builder->run(face);
297 if(patch->is_triangle())
298 split->split_triangle(mesh, patch, shader, smooth);
300 split->split_quad(mesh, patch, shader, smooth);