3 |
#ifndef VOB_POLY_DICER_HXX |
#ifndef VOB_POLY_DICER_HXX |
4 |
#define VOB_POLY_DICER_HXX |
#define VOB_POLY_DICER_HXX |
5 |
|
|
6 |
|
#include <GL/gl.h> |
7 |
#include <algorithm> |
#include <algorithm> |
8 |
#include <set> |
#include <set> |
9 |
#include <map> |
#include <map> |
10 |
#include <vector> |
#include <vector> |
11 |
|
#include <list> |
12 |
#include <ext/slist> |
#include <ext/slist> |
13 |
|
|
14 |
namespace Vob { |
namespace Vob { |
16 |
|
|
17 |
PREDBGVAR(dbg); |
PREDBGVAR(dbg); |
18 |
|
|
19 |
|
template<class Verts> struct Triangles { |
20 |
|
Verts &verts; |
21 |
|
struct Tri { |
22 |
|
int v[3]; |
23 |
|
typename std::list<Tri>::iterator n[3]; |
24 |
|
}; |
25 |
|
std::list<Tri> tris; |
26 |
|
|
27 |
|
typedef typename std::list<Tri>::iterator Titer; |
28 |
|
vector<Titer> vertFirst; |
29 |
|
|
30 |
|
void remove(Titer x) { |
31 |
|
Tri &t = *x; |
32 |
|
DBG(dbg) << "Triangler: remove "<<t.v[0]<<" "<<t.v[1]<<" "<<t.v[2]<<"\n"; |
33 |
|
// Remove from the edge list |
34 |
|
for(int i=0; i<3; i++) { |
35 |
|
Titer v = vertFirst[t.v[i]]; |
36 |
|
DBG(dbg) << "Titer: "<<(*v).v[0]<<" "<<(*v).v[1]<<" "<<(*v).v[2]<<"\n"; |
37 |
|
if(v == x) { |
38 |
|
DBG(dbg) << "Was first\n"; |
39 |
|
vertFirst[t.v[i]] = t.n[i]; |
40 |
|
} else { |
41 |
|
Titer prev = v; |
42 |
|
int vind = 0; |
43 |
|
if((*v).v[0] == t.v[i]) vind = 0; |
44 |
|
if((*v).v[1] == t.v[i]) vind = 1; |
45 |
|
if((*v).v[2] == t.v[i]) vind = 2; |
46 |
|
v = (*v).n[vind]; |
47 |
|
while(v != tris.end()) { |
48 |
|
DBG(dbg) << "Titer: "<<(*v).v[0]<<" "<<(*v).v[1]<<" "<<(*v).v[2]<<"\n"; |
49 |
|
if(v == x) { |
50 |
|
(*prev).n[vind] = t.n[i]; |
51 |
|
break; |
52 |
|
} |
53 |
|
if((*v).v[0] == t.v[i]) vind = 0; |
54 |
|
if((*v).v[1] == t.v[i]) vind = 1; |
55 |
|
if((*v).v[2] == t.v[i]) vind = 2; |
56 |
|
prev = v; |
57 |
|
v = (*v).n[vind]; |
58 |
|
} |
59 |
|
} |
60 |
|
} |
61 |
|
DBG(dbg) << "Remove: realerase\n"; |
62 |
|
tris.erase(x); |
63 |
|
} |
64 |
|
|
65 |
|
void splitEdge(int v1, int v2) { |
66 |
|
DBG(dbg) << "Triangler: split "<<v1<<" "<<v2<<"\n"; |
67 |
|
vector<Titer> toremove; |
68 |
|
for(Titer x = vertFirst[v1]; x != tris.end(); ) { |
69 |
|
int vind = 0; |
70 |
|
if((*x).v[0] == v1) vind = 0; |
71 |
|
if((*x).v[1] == v1) vind = 1; |
72 |
|
if((*x).v[2] == v1) vind = 2; |
73 |
|
if((*x).v[0] == v2 || |
74 |
|
(*x).v[1] == v2 || |
75 |
|
(*x).v[2] == v2) toremove.push_back(x); |
76 |
|
x = (*x).n[vind]; |
77 |
|
} |
78 |
|
if(toremove.size() == 0) return; |
79 |
|
int nvert = verts(v1, v2, .5); |
80 |
|
DBG(dbg) << "Have new vert "<<nvert<<"\n"; |
81 |
|
for(unsigned i=0; i<toremove.size(); i++) { |
82 |
|
// Save to local |
83 |
|
Tri t = *toremove[i]; |
84 |
|
remove(toremove[i]); |
85 |
|
int i = (t.v[0] == v1 ? nvert : t.v[0]); |
86 |
|
int j = (t.v[1] == v1 ? nvert : t.v[1]); |
87 |
|
int k = (t.v[2] == v1 ? nvert : t.v[2]); |
88 |
|
add(i, j, k); |
89 |
|
i = (t.v[0] == v2 ? nvert : t.v[0]); |
90 |
|
j = (t.v[1] == v2 ? nvert : t.v[1]); |
91 |
|
k = (t.v[2] == v2 ? nvert : t.v[2]); |
92 |
|
add(i, j, k); |
93 |
|
} |
94 |
|
DBG(dbg) << "Split finished\n"; |
95 |
|
} |
96 |
|
|
97 |
|
public: |
98 |
|
void add(int i, int j, int k) { |
99 |
|
DBG(dbg) << "Triangler: add "<<i<<" "<<j<<" "<<k<<"\n"; |
100 |
|
Tri t; |
101 |
|
t.v[0] = i; |
102 |
|
t.v[1] = j; |
103 |
|
t.v[2] = k; |
104 |
|
if(vertFirst.size() != verts.size()) |
105 |
|
vertFirst.resize(verts.size(), tris.end()); |
106 |
|
t.n[0] = vertFirst[i]; |
107 |
|
t.n[1] = vertFirst[j]; |
108 |
|
t.n[2] = vertFirst[k]; |
109 |
|
vertFirst[i] = vertFirst[j] = vertFirst[k] = |
110 |
|
tris.insert(tris.begin(), t); |
111 |
|
} |
112 |
|
|
113 |
|
template <class F> void dice(F criterion) { |
114 |
|
DBG(dbg) << "Triangler: dice\n"; |
115 |
|
typedef std::pair<int, int> Edge; |
116 |
|
vector<Edge> tosplit; |
117 |
|
while(1) { |
118 |
|
DBG(dbg) << "Triangler: dice round\n"; |
119 |
|
for(Titer t = tris.begin(); t != tris.end(); t++) { |
120 |
|
Tri &tri = *t; |
121 |
|
int spl = criterion(tri.v[0], tri.v[1], tri.v[2]); |
122 |
|
if(spl >= 0) { |
123 |
|
tosplit.push_back( Edge( tri.v[spl], tri.v[(spl+1) % 3])); |
124 |
|
} |
125 |
|
} |
126 |
|
if(!tosplit.size()) return; |
127 |
|
for(unsigned i=0; i<tosplit.size(); i++) |
128 |
|
splitEdge(tosplit[i].first, tosplit[i].second); |
129 |
|
tosplit.clear(); |
130 |
|
} |
131 |
|
} |
132 |
|
void draw() { |
133 |
|
glBegin(GL_TRIANGLES); |
134 |
|
for(Titer x = tris.begin(); x != tris.end(); x++) { |
135 |
|
glArrayElement((*x).v[0]); |
136 |
|
glArrayElement((*x).v[1]); |
137 |
|
glArrayElement((*x).v[2]); |
138 |
|
} |
139 |
|
glEnd(); |
140 |
|
} |
141 |
|
Triangles(Verts &v) : verts(v) { |
142 |
|
} |
143 |
|
}; |
144 |
|
|
145 |
/** Dice a line to pieces satisfying Criterion. |
/** Dice a line to pieces satisfying Criterion. |
146 |
* This is a generic method to dice a given edge recursively. |
* This is a generic method to dice a given edge recursively. |
161 |
* @return Number of new vertices added to the edge. |
* @return Number of new vertices added to the edge. |
162 |
*/ |
*/ |
163 |
template<class Verts, class Edge, class Criterion> |
template<class Verts, class Edge, class Criterion> |
164 |
int dice_line(Verts &verts, Edge &edge, |
int dice_line2(Verts &verts, Edge &edge, |
165 |
typename Edge::iterator begin, typename Edge::iterator last, |
typename Edge::iterator begin, typename Edge::iterator last, |
166 |
Criterion split, int maxdepth, int depth=0) { |
Criterion split, int maxdepth, int depth=0) { |
167 |
DBG(dbg) << "dice_line "<<depth<<"\n"; |
DBG(dbg) << "dice_line "<<depth<<"\n"; |
189 |
return ret; |
return ret; |
190 |
} |
} |
191 |
|
|
192 |
|
template<class Verts, class Edge, class Criterion> |
193 |
|
int dice_line3_h(Verts &verts, Edge &edge, |
194 |
|
typename Edge::iterator begin, |
195 |
|
typename Edge::iterator half, |
196 |
|
typename Edge::iterator last, |
197 |
|
Criterion split, int maxdepth, int depth) { |
198 |
|
if(depth >= maxdepth) { |
199 |
|
DBG(dbg) << "dice_line3_h STOPDEPTH\n"; |
200 |
|
return 0; |
201 |
|
} |
202 |
|
int splitflag = split(*begin, *half, *last); |
203 |
|
int ret = 0; |
204 |
|
if(splitflag == 1) { |
205 |
|
int spv = verts(*begin, *half, .5); |
206 |
|
ret ++; |
207 |
|
typename Edge::iterator sp = edge.insert_after(begin, spv); |
208 |
|
ret += dice_line3_h(verts, edge, begin, sp, half, split, maxdepth, depth+1); |
209 |
|
} |
210 |
|
int esplitflag = split(*last, *half, *begin); |
211 |
|
if(esplitflag == 1) { |
212 |
|
int espv = verts(*half, *last, .5); |
213 |
|
ret ++; |
214 |
|
typename Edge::iterator esp = edge.insert_after(half, espv); |
215 |
|
ret += dice_line3_h(verts, edge, half, esp, last, split, maxdepth, depth+1); |
216 |
|
} |
217 |
|
return ret; |
218 |
|
|
219 |
|
} |
220 |
|
|
221 |
|
template<class Verts, class Edge, class Criterion> |
222 |
|
int dice_line3(Verts &verts, Edge &edge, |
223 |
|
typename Edge::iterator begin, typename Edge::iterator last, |
224 |
|
Criterion split, int maxdepth, int depth=0) { |
225 |
|
DBG(dbg) << "dice_line "<<depth<<"\n"; |
226 |
|
if(depth >= maxdepth) { |
227 |
|
DBG(dbg) << "dice_line STOPDEPTH\n"; |
228 |
|
return 0; |
229 |
|
} |
230 |
|
int halfv = verts(*begin, *last, .5); |
231 |
|
|
232 |
|
|
233 |
|
int splitflag = split(*begin, halfv, *last); |
234 |
|
if(splitflag == -1) { |
235 |
|
DBG(dbg) << "dice_line STOP FLAG\n"; |
236 |
|
return 0; |
237 |
|
} |
238 |
|
typename Edge::iterator half = edge.insert_after(begin, halfv); |
239 |
|
int ret = 1; |
240 |
|
ret += dice_line3_h(verts, edge, begin, half, last, split, maxdepth, depth + 1); |
241 |
|
|
242 |
|
DBG(dbg) << "RET dice_line "<<depth<<" "<<ret << "\n"; |
243 |
|
return ret; |
244 |
|
} |
245 |
|
|
246 |
|
|
247 |
/** A triangle whose edges have been diced. |
/** A triangle whose edges have been diced. |
248 |
*/ |
*/ |
249 |
template<class Edge> struct DicedTriangle { |
template<class Edge> struct DicedTriangle { |
300 |
DicedTriangle start; |
DicedTriangle start; |
301 |
start.ebegins[0] = newEdge.begin(); |
start.ebegins[0] = newEdge.begin(); |
302 |
start.elasts[0] = newEdge.begin(); start.elasts[0] ++; |
start.elasts[0] = newEdge.begin(); start.elasts[0] ++; |
303 |
start.n[0] = dice_line(verts, newEdge, start.ebegins[0], start.elasts[0], split, maxdepth, depth); |
start.n[0] = dice_line3(verts, newEdge, start.ebegins[0], start.elasts[0], split, maxdepth, depth); |
304 |
|
|
305 |
start.ebegins[1] = ebegins[thirdEdge]; |
start.ebegins[1] = ebegins[thirdEdge]; |
306 |
start.elasts[1] = elasts[thirdEdge]; |
start.elasts[1] = elasts[thirdEdge]; |
357 |
for(int i=0; i<3; i++) { |
for(int i=0; i<3; i++) { |
358 |
ebegins[i] = e[i].begin(); |
ebegins[i] = e[i].begin(); |
359 |
elasts[i] = ebegins[i]; elasts[i] ++; |
elasts[i] = ebegins[i]; elasts[i] ++; |
360 |
n[i] = dice_line(verts, e[i], ebegins[i], elasts[i], split, maxdepth); |
n[i] = dice_line3(verts, e[i], ebegins[i], elasts[i], split, maxdepth); |
361 |
} |
} |
362 |
} |
} |
363 |
}; |
}; |