Subversion Repositories gelsvn

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
595 jab 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
362 jab 7
#include <map>
8
#include <algorithm>
9
#include <queue>
10
 
11
#include "Util/Grid2D.h"
12
#include "CGLA/Vec3f.h"
13
#include "CGLA/Vec2f.h"
14
 
15
#include "tessellate.h"
16
 
17
using namespace std;
18
using namespace CGLA;
19
using namespace Util;
20
 
21
namespace Geometry
22
{
23
 
24
	float MAX_ERR = 5;
25
	float MAX_DIST = 5;
26
	int  ADAPTIVE = false;
27
 
28
#define mymax(x,y) ((x)>(y)?(x):(y))
29
 
30
	// Test surfaces ---
31
 
32
 
33
	// ----------- CONSTANTS AND GLOBALS ------------
34
 
35
	namespace
36
	{
37
		float maximum_edge_error=0;
38
 
39
		IndexedFaceSet* face_set_ptr = 0;
40
		ParSurf* the_surf = 0;
41
 
42
		class TreeNode;
43
		typedef TreeNode* TreeNodePtr;
44
 
45
		vector<TreeNode*> root_nodes;
46
 
47
		class Point 
48
		{
49
			friend class Edge;
50
			friend float subdiv(int level, const Point&, const Point&, TreeNodePtr&);
51
			friend float compute_mid_pt_err(const Point&, const Point&, Point&);
52
 
53
 
54
			Vec2f ppos;
55
			Vec3f pos;
56
			mutable int vertex_idx;
57
 
58
public:
59
 
60
				Point(const Vec2f& _ppos, const Vec3f& _pos): 
61
				ppos(_ppos), pos(_pos), vertex_idx(-1)
62
			{
63
			}
64
 
65
			Point() {}
66
 
67
			void create_vertex() const
68
			{
69
				if(vertex_idx == -1) 
70
					vertex_idx = face_set_ptr->add_vertex(pos);
71
			}
72
		};
73
 
74
 
75
 
76
		inline const Point create_point(float u, float v)
77
		{
78
			Vec2f ppos(u,v);
79
			Vec3f pos = (*the_surf)(u,v);
80
			return Point(ppos, pos);
81
		}
82
 
83
		float subdiv(int level, const Point& lp, const Point& rp, TreeNodePtr& node);
84
 
85
		class TreeNode
86
		{
87
			friend class Edge;
88
			friend float subdiv(int level, const Point&, const Point&, TreeNodePtr&);
89
 
90
			const Point p;
91
			const float error;
92
 
93
			const TreeNodePtr left;
94
			const TreeNodePtr right;
95
 
96
public:
97
 
98
				TreeNode(const Point& _p, float _error,
99
						 TreeNodePtr _left, TreeNodePtr _right):
100
				p(_p), error(_error), left(_left), right(_right)  {}
101
 
102
			~TreeNode() 
103
			{
104
				if(left)
105
					delete left; 
106
 
107
				if(right)
108
					delete right;
109
			}
110
 
111
		};
112
 
113
		class Edge
114
		{
115
			friend Edge create_edge(const Point&, const Point&, bool);
116
 
117
			Edge(const Point& _left_point, 
118
				 const Point& _right_point, 
119
				 TreeNodePtr _root,
120
				 bool _cw): 
121
				left_point(_left_point), right_point(_right_point), root(_root), cw(_cw)
122
			{
123
			}
124
 
125
 
126
			Point left_point;
127
			Point right_point;
128
			TreeNodePtr root;
129
			bool cw;
130
 
131
public:
132
 
133
				Edge() {}
134
 
135
			float get_error() const
136
			{
137
				if(root)
138
					return root->error;
139
				return 0.0f;
140
			}
141
 
142
			float get_length() const
143
			{
144
				return (left_point.pos-right_point.pos).length();
145
			}
146
 
147
			bool is_simple() const 
148
			{
149
				if(root->left==0)
150
				{
151
					assert(root->left==0);
152
					assert(root->right==0);
153
					return true;
154
				}
155
				return false;
156
			}
157
 
158
			const Edge get_sub_edge(int edge_no) const
159
			{
160
				assert(edge_no == 0 || edge_no == 1);
161
				assert(!is_simple());
162
 
163
				if(!cw) edge_no = 1-edge_no;
164
 
165
				if(edge_no ==0)
166
					return Edge(left_point, root->p, root->left, cw);
167
				else
168
					return Edge(root->p, right_point, root->right, cw);
169
			}
170
 
171
			const Edge get_opp_edge() const
172
			{
173
				return Edge(left_point, right_point, root, !cw);
174
			}
175
 
176
 
177
			const Point& get_split_point() const
178
			{
179
				assert(!is_simple());
180
				return root->p;
181
			}
182
 
183
			const Point& get_point(int i) const
184
			{
185
				assert(i==0 || i==1);
186
				if(!cw) i=1-i;
187
				if(i == 0) 
188
					return left_point;
189
				return right_point;
190
			}
191
 
192
			int get_point_idx(int i) const
193
			{
194
				assert(i==0 || i==1);
195
				if(!cw) i=1-i;
196
				if(i == 0) 
197
					return left_point.vertex_idx;
198
				return right_point.vertex_idx;
199
			}
200
 
201
		};
202
 
203
 
204
		float compute_mid_pt_err(const Point&, const Point&, Point&);
205
 
206
		Edge create_edge(const Point& left_point, const Point& right_point, 
207
						 bool cw=true)
208
		{
209
			TreeNodePtr root=0;
210
			if(ADAPTIVE)
211
				subdiv(0, left_point,right_point,root);
212
			else
213
			{
214
				Point mid_point;
215
				float err = compute_mid_pt_err(left_point, right_point, mid_point);
216
				root = new TreeNode(mid_point,err,0,0);
217
			}
218
			if(root)
219
				root_nodes.push_back(root);
220
 
221
			return Edge(left_point, right_point, root, cw);
222
		}
223
 
224
		class Triangle
225
		{
226
			Edge a,b,c;
227
public:
228
			Triangle(const Edge& _a, const Edge& _b, const Edge& _c):
229
			a(_a),  b(_b), c(_c) {}
230
 
231
			const Edge& operator[](int i) const
232
		{
233
			switch(i)
234
			{
235
				case 0: return a;
236
				case 1: return b;
237
				case 2: return c;
238
			}
239
			return c;
240
		}
241
 
242
		};
243
 
244
		float compute_mid_pt_err(const Point& lp, const Point& rp, 
245
								 Point& mid_point)
246
		{
247
			Vec3f m = (lp.pos - rp.pos)/2.0f + rp.pos;
248
			Vec2f uvm = (lp.ppos -rp.ppos)/2.0f + rp.ppos;
249
 
250
			mid_point = create_point(uvm[0], uvm[1]);
251
			Vec3f diff = mid_point.pos - m;
252
			return diff.length();
253
		}
254
 
255
		float subdiv(int level, const Point& lp, const Point& rp, TreeNodePtr& node)
256
		{
257
			Point mid_point;
258
			float err = compute_mid_pt_err(lp,rp,mid_point);
259
 
595 jab 260
//			Vec3f dist = lp.pos-rp.pos;
362 jab 261
			if (level>10) 
262
			{
263
				node = new TreeNode(mid_point,err,0,0);
264
				return err;
265
			}
266
 
267
			TreeNodePtr lnode;
268
			float lerr = subdiv(level+1,lp, mid_point, lnode);
269
 
270
			TreeNodePtr rnode;
271
			float rerr = subdiv(level+1,mid_point, rp, rnode);
272
 
273
			float max_err = mymax(err, mymax(lerr,rerr));
274
 
275
			if(max_err < MAX_ERR)
276
			{
277
				if(lnode) delete lnode;
278
				if(rnode) delete rnode;
279
 
280
				node = new TreeNode(mid_point, max_err, 0,0);
281
			}
282
			else
283
			{
284
				mid_point.create_vertex();
285
				node = new TreeNode(mid_point, max_err, lnode,rnode);
286
			}
287
 
288
			return max_err;
289
		}
290
 
291
 
292
 
293
		void split(const Triangle orig_tri)
294
		{
295
			queue<Triangle> tri_queue;
296
			tri_queue.push(orig_tri);
297
 
298
 
299
			while(!tri_queue.empty())
300
			{
301
				const Triangle tri = tri_queue.front();
302
				tri_queue.pop();
303
 
304
				int no_split_edges = 0;
305
 
306
				for(int i=0;i<3;++i)
307
					if(!tri[i].is_simple())
308
						++no_split_edges;
309
 
310
				if(no_split_edges==0 /* || level > 2000*/) 
311
				{
312
					int a = tri[0].get_point_idx(0);
313
					int b = tri[1].get_point_idx(0);
314
					int c = tri[2].get_point_idx(0);
315
					face_set_ptr->add_face(Vec3i(a,b,c));
316
					maximum_edge_error = mymax(mymax(tri[0].get_error(),
317
													 tri[1].get_error()),
318
											   tri[2].get_error());
319
				}
320
				else if(no_split_edges==3)
321
				{
322
					const Point& p0 = tri[0].get_point(0);
323
					const Point& p1 = tri[1].get_point(0);
324
					const Point& p2 = tri[2].get_point(0);
325
 
326
					const Point sp[3] = {tri[0].get_split_point(),
327
						tri[1].get_split_point(),
328
						tri[2].get_split_point()};
329
 
330
					Edge sp_edg[3] = {create_edge(sp[0],p2),
331
						create_edge(sp[1],p0),
332
						create_edge(sp[2],p1)};
333
 
334
					int i_min=0;
335
					float l_min = sp_edg[0].get_length();
336
					int i;
337
					for(i=1;i<3;++i)
338
					{
339
						float len = sp_edg[i].get_length();
340
						if(len<l_min) 
341
						{
342
							l_min = len;
343
							i_min = i;
344
						}
345
					}
346
 
347
					i = i_min;
348
					int j = (i+1)%3;
349
					int k = (i+2)%3;
350
 
351
					Edge spi_spj = create_edge(sp[i],sp[j]);
352
					Edge spi_spk = create_edge(sp[i],sp[k]);
353
 
354
					Triangle tri0(tri[i].get_sub_edge(1),
355
								  tri[j].get_sub_edge(0),
356
								  spi_spj.get_opp_edge());
357
					Triangle tri1(spi_spj,
358
								  tri[j].get_sub_edge(1),
359
								  sp_edg[i].get_opp_edge());
360
					Triangle tri2(sp_edg[i],
361
								  tri[k].get_sub_edge(0),
362
								  spi_spk.get_opp_edge());
363
					Triangle tri3(spi_spk,
364
								  tri[k].get_sub_edge(1),
365
								  tri[i].get_sub_edge(0));
366
 
367
					tri_queue.push(tri0);
368
					tri_queue.push(tri1);
369
					tri_queue.push(tri2);
370
					tri_queue.push(tri3);
371
				}
372
				else if(no_split_edges==2)
373
				{
374
					int i;
375
					if(tri[2].is_simple()) i = 0;
376
					else if(tri[1].is_simple()) i=2;
377
					else i = 1;
378
 
379
					int j = (i+1)%3;
380
					int k = (i+2)%3;
381
 
382
					const Point& spi = tri[i].get_split_point();
383
					const Point& spj = tri[j].get_split_point();
384
 
385
					const Point& pi = tri[i].get_point(0);
386
					const Point& pk = tri[k].get_point(0);
387
 
388
					Edge spi_spj = create_edge(spi, spj);
389
					Edge pi_spj = create_edge(pi, spj);
390
					Edge pk_spi = create_edge(pk, spi);
391
 
392
					Triangle tri0(tri[i].get_sub_edge(1),
393
								  tri[j].get_sub_edge(0),
394
								  spi_spj.get_opp_edge());
395
 
396
 
397
					if(pi_spj.get_length() < pk_spi.get_length())
398
					{
399
						Triangle tri1(spi_spj,
400
									  pi_spj.get_opp_edge(),
401
									  tri[i].get_sub_edge(0));
402
						Triangle tri2(pi_spj,
403
									  tri[j].get_sub_edge(1),
404
									  tri[k]);
405
						tri_queue.push(tri1);					
406
						tri_queue.push(tri2);	
407
					}
408
					else
409
					{
410
						Triangle tri1(tri[i].get_sub_edge(0),
411
									  pk_spi.get_opp_edge(),
412
									  tri[k]);
413
						Triangle tri2(spi_spj,
414
									  tri[j].get_sub_edge(1),
415
									  pk_spi);
416
						tri_queue.push(tri1);					
417
						tri_queue.push(tri2);
418
					}
419
					tri_queue.push(tri0);
420
				}
421
				else if(no_split_edges==1)
422
				{
423
					int i;
424
					if(!tri[0].is_simple()) i=0;
425
					else if(!tri[1].is_simple()) i=1;
426
					else i= 2;
427
 
428
					int j = (i+1)%3;
429
					int k = (i+2)%3;
430
 
431
					const Point& pk = tri[k].get_point(0);
432
					const Point& spi = tri[i].get_split_point();
433
 
434
					Edge spi_pk = create_edge(spi, pk);
435
 
436
					Triangle tri0(tri[i].get_sub_edge(1),
437
								  tri[j],
438
								  spi_pk.get_opp_edge());
439
 
440
					Triangle tri1(tri[i].get_sub_edge(0),
441
								  spi_pk,
442
								  tri[k]);
443
 
444
					tri_queue.push(tri0);
445
					tri_queue.push(tri1);
446
 
447
				}
448
			}
449
		}
450
	}
451
 
452
 
453
	void tessellate(IndexedFaceSet& face_set, ParSurf& s, Grid2D<Vec3f>& inigrid)
454
	{	
455
		face_set_ptr = &face_set;
456
		int i;
457
		int n=inigrid.get_xdim()-1;
458
		int m=inigrid.get_ydim()-1;
459
		the_surf = &s;
460
		Grid2D<Point> points(n+1,m+1);
461
		for(i=0;i<=n;++i)
462
			for(int j=0;j<=m;++j)
463
			{
464
				Vec3f p = inigrid(i,j);
465
				points(i,j) = create_point(p[0], p[1]);
466
				points(i,j).create_vertex();
467
			}
468
 
469
 
470
				Grid2D<Edge> h_edges(n,m+1);
471
		Grid2D<Edge> v_edges(n+1,m);
472
		for(i=0;i<=n;++i)
473
			for(int j=0;j<=m;++j)
474
			{
475
				if(i<n)
476
					h_edges(i,j) = create_edge(points(i,j), points(i+1,j));
477
				if(j<m)
478
					v_edges(i,j) = create_edge(points(i,j), points(i,j+1));
479
			}
480
 
481
				for(i=0;i<n;++i)
482
					for(int j=0;j<m;++j)
483
					{
484
						Edge diag = create_edge(points(i,j), points(i+1,j+1));
485
						Triangle tri0(h_edges(i,j), v_edges(i+1,j), diag.get_opp_edge());
486
						Triangle tri1(diag, h_edges(i,j+1).get_opp_edge(), 
487
									  v_edges(i,j).get_opp_edge());
488
						split(tri0);
489
						split(tri1);
490
					}
373 jrf 491
						for(i=0;i<static_cast<int>(root_nodes.size());++i)
362 jab 492
						{
493
							if(root_nodes[i])
494
							{
495
								delete root_nodes[i];
496
							}
497
						}
498
						root_nodes.clear();
499
		maximum_edge_error=0;
500
		the_surf = 0;
501
	}
502
 
503
 
504
	void tessellate(IndexedFaceSet& face_set, ParSurf& s,
505
					float u_min, float u_max, float v_min, float v_max, 
506
					int n, int m)
507
	{	
508
		face_set_ptr = &face_set;
509
		int i;
510
		the_surf = &s;
511
		Grid2D<Point> points(n+1,m+1);
512
		float step_x = (u_max-u_min)/float(n);
513
		float step_y = (v_max-v_min)/float(m);
514
		for(i=0;i<=n;++i)
515
			for(int j=0;j<=m;++j)
516
			{
517
				points(i,j) = create_point(u_min+i*step_x,v_min+j*step_y);
518
				points(i,j).create_vertex();
519
			}
520
 
521
 
522
				Grid2D<Edge> h_edges(n,m+1);
523
		Grid2D<Edge> v_edges(n+1,m);
524
		for(i=0;i<=n;++i)
525
			for(int j=0;j<=m;++j)
526
			{
527
				if(i<n)
528
					h_edges(i,j) = create_edge(points(i,j), points(i+1,j));
529
				if(j<m)
530
					v_edges(i,j) = create_edge(points(i,j), points(i,j+1));
531
			}
532
 
533
				for(i=0;i<n;++i)
534
					for(int j=0;j<m;++j)
535
					{
536
						Edge diag = create_edge(points(i,j), points(i+1,j+1));
537
						Triangle tri0(h_edges(i,j), v_edges(i+1,j), diag.get_opp_edge());
538
						Triangle tri1(diag, h_edges(i,j+1).get_opp_edge(), 
539
									  v_edges(i,j).get_opp_edge());
540
						split(tri0);
541
						split(tri1);
542
					}
373 jrf 543
						for(i=0;i<static_cast<int>(root_nodes.size());++i)
362 jab 544
						{
545
							if(root_nodes[i])
546
							{
547
								delete root_nodes[i];
548
							}
549
						}
550
						root_nodes.clear();
551
		maximum_edge_error=0;
552
		the_surf = 0;
553
	}
554
 
555
 
556
	/** The Edge2VertexMap is a simple database class.
557
		The database stores integer values referenced by keys formed by
558
		a pair of indices. The intended use is to let the key be a pair
559
		of vertices sharing an edge and the value be a new vertex inserted on
560
		that edge. */
561
	class EdgeMap
562
	{
563
		typedef pair<int,int>      VertPair;
564
		typedef map<VertPair, Edge> E2VMap;
565
		typedef E2VMap::iterator   E2VIter;
566
 
567
		E2VMap edge_to_vertex;
568
 
569
public:
570
 
571
			void set_edge(int ind0, int ind1, const Edge& new_edge)
572
		{
573
				edge_to_vertex[VertPair(ind0,ind1)] = new_edge;
574
		}
575
 
576
		bool find_edge(int ind0, int ind1, Edge& edg)
577
		{
578
			E2VIter iter = edge_to_vertex.find(VertPair(ind0,ind1));
579
 
580
			if(iter == edge_to_vertex.end())
581
				return false;
582
 
583
			edg = iter->second;
584
			return true;
585
		}
586
 
587
	};
588
 
589
	void tessellate(IndexedFaceSet& face_set, ParSurf& s, 
590
					std::vector<Vec2f> uv_points,
591
					std::vector<Vec3i> triangles)
592
	{		
593
		face_set_ptr = &face_set;
594
		int i;
595
		the_surf = &s;
595 jab 596
		size_t N = uv_points.size();
362 jab 597
		vector<Point> points(N);
598
		for(i=0;i<N;++i)
599
		{
600
			points[i] = create_point(uv_points[i][0], uv_points[i][1]);
601
			points[i].create_vertex();
602
		}
603
		EdgeMap edges;
604
		vector<Triangle> tris;
373 jrf 605
		for(size_t j=0;j<triangles.size();++j)
362 jab 606
		{
607
			Edge e[3];
608
			int v[3];
609
 
610
			v[0] = triangles[j][0];
611
			v[1] = triangles[j][1];
612
			v[2] = triangles[j][2];
613
 
614
			for(int i=0;i<3;++i)
615
			{
616
				int k = (i+1)%3;
617
				if(!edges.find_edge(v[i],v[k],e[i]))
618
				{
619
					e[i] = create_edge(points[v[i]], points[v[k]]);
620
					edges.set_edge(v[k],v[i],e[i].get_opp_edge());
621
				}
622
			}
623
			split(Triangle(e[0],e[1],e[2]));
624
 
625
		}
373 jrf 626
		for(i=0;i<static_cast<int>(root_nodes.size());++i)
362 jab 627
		{
628
			if(root_nodes[i])
629
			{
630
				delete root_nodes[i];
631
			}
632
		}
633
		root_nodes.clear();
634
		maximum_edge_error=0;
635
		the_surf = 0;
636
	}
637
 
638
}