ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_del.c
Revision: 3.7
Committed: Wed Nov 11 12:05:38 1998 UTC (25 years, 5 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.6: +211 -402 lines
Log Message:
new triangulation code
changed triangle vertex order to CCW
changed numbering of triangle neighbors to match quadtree
fixed tone-mapping bug
removed errant printf() statements
redid logic for adding and testing samples with new epsilon

File Contents

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * sm_del.c
9 */
10 #include "standard.h"
11 #include "sm_flag.h"
12 #include "sm_list.h"
13 #include "sm_geom.h"
14 #include "sm_qtree.h"
15 #include "sm_stree.h"
16 #include "sm.h"
17
18 static int Max_edges=200;
19 static EDGE *Edges=NULL;
20 static int Ecnt=0;
21
22 #define remove_tri_compress remove_tri
23 remove_tri(qtptr,fptr,tptr)
24 QUADTREE *qtptr;
25 int *fptr;
26 int *tptr;
27 {
28 int n;
29
30 if(QT_IS_EMPTY(*qtptr))
31 return;
32 if(QT_LEAF_IS_FLAG(*qtptr))
33 return;
34
35 n = QT_SET_CNT(qtqueryset(*qtptr))-1;
36 *qtptr = qtdelelem(*qtptr,*tptr);
37 if(n == 0)
38 (*fptr) |= QT_COMPRESS;
39 if(!QT_FLAG_FILL_TRI(*fptr))
40 (*fptr)++;
41 }
42
43
44 smLocator_remove_tri(sm,t_id,v0_id,v1_id,v2_id)
45 SM *sm;
46 int t_id;
47 int v0_id,v1_id,v2_id;
48 {
49 STREE *st;
50 FVECT v0,v1,v2;
51
52 st = SM_LOCATOR(sm);
53
54 VSUB(v0,SM_NTH_WV(sm,v0_id),SM_VIEW_CENTER(sm));
55 VSUB(v1,SM_NTH_WV(sm,v1_id),SM_VIEW_CENTER(sm));
56 VSUB(v2,SM_NTH_WV(sm,v2_id),SM_VIEW_CENTER(sm));
57
58 qtClearAllFlags();
59
60 stApply_to_tri(st,v0,v1,v2,remove_tri,remove_tri_compress,&t_id);
61
62 }
63
64 smFree_tri(sm,id)
65 SM *sm;
66 int id;
67 {
68 TRI *tri;
69
70 tri = SM_NTH_TRI(sm,id);
71 /* Add to the free_list */
72 T_NEXT_FREE(tri) = SM_FREE_TRIS(sm);
73 SM_FREE_TRIS(sm) = id;
74 T_VALID_FLAG(tri) = -1;
75 }
76
77 /* Assumes mesh pointers have been cleaned up appropriately: just deletes from
78 Point location and triangle data structure
79 */
80 smDelete_tri(sm,t_id)
81 SM *sm;
82 int t_id;
83 {
84
85 /* NOTE: Assumes that a new triangle adjacent to each vertex
86 has been added- before the deletion: replacing
87 the old tri- and therefore dont need to dereference any pointers
88 to id because the vertices can no longer
89 point to tri id as being the first triangle pointer
90 */
91 if(!SM_IS_NTH_T_BASE(sm,t_id))
92 {
93 SM_SAMPLE_TRIS(sm)--;
94 if(SM_IS_NTH_T_NEW(sm,t_id))
95 smNew_tri_cnt--;
96 }
97 smClear_tri_flags(sm,t_id);
98
99 smFree_tri(sm,t_id);
100 }
101
102
103 int
104 eNew_edge()
105 {
106 if(!Edges)
107 if(!(Edges = (EDGE *)realloc(NULL,(Max_edges+1)*sizeof(EDGE))))
108 goto memerr;
109
110 if(Ecnt >= Max_edges)
111 {
112 if(Max_edges > 10000)
113 error(CONSISTENCY,"Too many edges in vertex loop\n");
114 Max_edges += 100;
115 if(!(Edges = (EDGE *)realloc(Edges,(Max_edges+1)*sizeof(EDGE))))
116 goto memerr;
117 }
118 return(++Ecnt);
119
120 memerr:
121 error(SYSTEM,"eNew_edge(): Unable to allocate memory");
122 }
123
124 /* Return list of edges defining polygon formed by boundary of triangles
125 adjacent to id. Return set of triangles adjacent to id to delete in delptr
126 */
127 LIST
128 *smVertexPolygon(sm,id,delptr)
129 SM *sm;
130 int id;
131 QUADTREE *delptr;
132 {
133 TRI *tri,*t_next;
134 LIST *elist,*end;
135 int e,t_id,v_next,t_next_id,b_id,v_id;
136 OBJECT del_set[2];
137
138 eClear_edges();
139 elist = end = NULL;
140
141 /* Get the first triangle adjacent to vertex id */
142 t_id = SM_NTH_VERT(sm,id);
143 tri = SM_NTH_TRI(sm,t_id);
144
145 e = eNew_edge();
146 /* Get the next vertex on the polygon boundary */
147 v_id = T_WHICH_V(tri,id);
148 b_id = (v_id + 1)%3;
149 /* Create an edge */
150 SET_E_NTH_VERT(e,0,T_NTH_V(tri,b_id));
151 SET_E_NTH_TRI(e,0,INVALID);
152 SET_E_NTH_TRI(e,1,T_NTH_NBR(tri,v_id));
153 v_next = T_NTH_V(tri,(b_id+1)%3);
154 SET_E_NTH_VERT(e,1,v_next);
155 elist = add_data_to_circular_list(elist,&end,e);
156 t_next_id = t_id;
157 t_next = tri;
158
159 /* Create a set to hold all of the triangles for deletion later */
160 del_set[0] = 1; del_set[1] = t_id;
161 *delptr = qtnewleaf(del_set);
162
163 while((t_next_id = T_NTH_NBR(t_next,b_id)) != t_id)
164 {
165 e = eNew_edge();
166 t_next = SM_NTH_TRI(sm,t_next_id);
167 SET_E_NTH_VERT(e,0,v_next);
168 SET_E_NTH_TRI(e,0,INVALID);
169 v_id = T_WHICH_V(t_next,id);
170 b_id = (v_id + 1)%3;
171 SET_E_NTH_TRI(e,1,T_NTH_NBR(t_next,v_id));
172 v_next = T_NTH_V(t_next,(b_id+1)%3);
173 SET_E_NTH_VERT(e,1,v_next);
174 elist = add_data_to_circular_list(elist,&end,e);
175 qtaddelem(*delptr,t_next_id);
176 }
177 return(elist);
178 }
179
180
181 int
182 smTriangulate_add_tri(sm,id0,id1,id2,e0,e1,e2ptr)
183 SM *sm;
184 int id0,id1,id2,e0,e1,*e2ptr;
185 {
186 int t_id;
187 int e2;
188
189 #ifdef DEBUG
190 if(id0 == INVALID || id1==INVALID || id2==INVALID)
191 error(CONSISTENCY,"bad id- smTriangulate_add_tri()\n");
192 #endif
193 t_id = smAdd_tri(sm,id0,id1,id2);
194 if(*e2ptr == 0)
195 {
196 e2 = eNew_edge();
197 SET_E_NTH_VERT(e2,0,id2);
198 SET_E_NTH_VERT(e2,1,id0);
199 }
200 else
201 e2 = *e2ptr;
202 /* set appropriate tri for each edge*/
203 SET_E_NTH_TRI(e0,0,t_id);
204 SET_E_NTH_TRI(e1,0,t_id);
205 SET_E_NTH_TRI(e2,0,t_id);
206
207 *e2ptr = e2;
208 return(t_id);
209 }
210
211 int
212 smTriangulateConvex(sm,plist,add_ptr)
213 SM *sm;
214 LIST *plist,**add_ptr;
215 {
216 int t_id,e_id0,e_id1,e_id2;
217 int v_id0,v_id1,v_id2;
218 LIST *lptr;
219
220 lptr = plist;
221 e_id0 = (int)LIST_DATA(lptr);
222 v_id0 = E_NTH_VERT(e_id0,0);
223 lptr = LIST_NEXT(lptr);
224 while(LIST_NEXT(lptr) != plist)
225 {
226 e_id1 = (int)LIST_DATA(lptr);
227 v_id1 = E_NTH_VERT(e_id1,0);
228 v_id2 = E_NTH_VERT(e_id1,1);
229 lptr = LIST_NEXT(lptr);
230
231 if(LIST_NEXT(lptr) != plist)
232 e_id2 = 0;
233 else
234 e_id2 = (int)LIST_DATA(lptr);
235 t_id = smTriangulate_add_tri(sm,v_id0,v_id1,v_id2,e_id0,e_id1,&e_id2);
236 *add_ptr = push_data(*add_ptr,t_id);
237 e_id0 = -e_id2;
238 }
239 free_list(plist);
240 return(TRUE);
241 }
242 #ifdef TEST_DRIVER
243 FVECT Norm[500],B_V[500];
244 int Ncnt,Bcnt,Del=0;
245 #endif
246
247
248 /* Triangulate the polygon defined by plist, and generating vertex p_id.
249 Return list of added triangles in list add_ptr. Returns TRUE if
250 successful, FALSE otherwise. This is NOT a general triangulation routine,
251 assumes polygon star relative to id
252 */
253
254 int
255 smTriangulate(sm,id,plist,add_ptr)
256 SM *sm;
257 int id;
258 LIST *plist,**add_ptr;
259 {
260 LIST *l,*prev,*t;
261 FVECT v0,v1,v2,n,p;
262 int is_tri,is_convex,cut,t_id,id0,id1,id2,e2,e1,enew;
263 double dp;
264
265 VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
266 enew = 0;
267 is_convex = TRUE;
268 cut = is_tri= FALSE;
269 l = prev = plist;
270
271 /* get v0,v1 */
272 e1 = (int)LIST_DATA(l);
273 id0 = E_NTH_VERT(e1,0);
274 id1 = E_NTH_VERT(e1,1);
275 VSUB(v0,SM_NTH_WV(sm,id0),SM_VIEW_CENTER(sm));
276 VSUB(v1,SM_NTH_WV(sm,id1),SM_VIEW_CENTER(sm));
277 #ifdef TEST_DRIVER
278 Del = TRUE;
279 VCOPY(B_V[0],v0);
280 VCOPY(B_V[1],v1);
281 Bcnt = 2;
282 Ncnt = 0;
283 #endif
284 while(l)
285 {
286 l = LIST_NEXT(l);
287 /* Get v2 */
288 e2 = (int)LIST_DATA(l);
289 id2 = E_NTH_VERT(e2,1);
290 VSUB(v2,SM_NTH_WV(sm,id2),SM_VIEW_CENTER(sm));
291 #ifdef TEST_DRIVER
292 VCOPY(B_V[Bcnt++],v2);
293 #endif
294 if(LIST_NEXT(LIST_NEXT(l)) == prev)
295 {/* Check if have a triangle */
296 is_tri = TRUE;
297 break;
298 }
299
300 /* determine if v0-v1-v2 is convex:defined clockwise on the sphere-
301 so switch orientation
302 */
303 if(convex_angle(v2,v1,v0))
304 {
305 /* test if safe to cut off v0-v1-v2 by testing if p lies outside of
306 triangle v0-v1-v2: if so, because plist is the star polygon around p,
307 the new edge v2-v0 cannot intersect any existing edges
308 */
309 VCROSS(n,v0,v2);
310 dp = DOT(n,p);
311 if(dp <= 0.0)
312 {
313 /* remove edges e1,e2 and add triangle id0,id1,id2 */
314 enew = 0;
315 t_id = smTriangulate_add_tri(sm,id0,id1,id2,e1,e2,&enew);
316 cut = TRUE;
317 *add_ptr = push_data(*add_ptr,t_id);
318 /* Insert edge enew into the list, reuse prev list element */
319 LIST_NEXT(prev) = LIST_NEXT(l);
320 LIST_DATA(prev) = e1 = -enew;
321 /* If removing head of list- reset plist pointer */
322 if(l== plist)
323 plist = prev;
324 /* free list element for e2 */
325 LIST_NEXT(l)=NULL;
326 free_list(l);
327 l = prev;
328 VCOPY(v1,v2);
329 id1 = id2;
330 continue;
331 }
332 }
333 else
334 is_convex = FALSE;
335 VCOPY(v0,v1);
336 VCOPY(v1,v2);
337 id0 = id1;
338 id1 = id2;
339 e1 = e2;
340 /* check if gone around circular list without adding any
341 triangles: prevent infinite loop */
342 if(l == plist)
343 {
344 if(LIST_NEXT(LIST_NEXT(l)) == prev)
345 {/* Check if have a triangle */
346 is_tri = TRUE;
347 break;
348 }
349
350 if(is_convex)
351 break;
352 if(!cut)
353 {
354 #ifdef DEBUG
355 eputs("smTriangulate():Unable to triangulate\n");
356 #endif
357 free_list(l);
358 while(*add_ptr)
359 {
360 t_id = pop_list(add_ptr);
361 smDelete_tri(sm,t_id);
362 }
363 return(FALSE);
364 }
365 cut = FALSE;
366 is_convex = TRUE;
367 }
368 prev = l;
369 }
370 if(is_tri)
371 {
372 l = LIST_NEXT(l);
373 enew = (int)LIST_DATA(l);
374 t_id = smTriangulate_add_tri(sm,id0,id1,id2,e1,e2,&enew);
375 *add_ptr = push_data(*add_ptr,t_id);
376 free_list(l);
377 }
378 else
379 if(!smTriangulateConvex(sm,l,add_ptr))
380 return(FALSE);
381
382 /* Set triangle adjacencies based on edge adjacencies */
383 FOR_ALL_EDGES(enew)
384 {
385 id0 = E_NTH_TRI(enew,0);
386 id1 = E_NTH_TRI(enew,1);
387
388 e1 = (T_WHICH_V(SM_NTH_TRI(sm,id0),E_NTH_VERT(enew,0))+2)%3;
389 T_NTH_NBR(SM_NTH_TRI(sm,id0),e1) = id1;
390
391 e2 = (T_WHICH_V(SM_NTH_TRI(sm,id1),E_NTH_VERT(enew,1))+2)%3;
392 T_NTH_NBR(SM_NTH_TRI(sm,id1),e2) = id0;
393 }
394 return(TRUE);
395 }
396
397 eIn_tri(e,t)
398 int e;
399 TRI *t;
400 {
401
402 if(T_NTH_V(t,0)==E_NTH_VERT(e,0))
403 return(T_NTH_V(t,1)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
404 else
405 if(T_NTH_V(t,1)==E_NTH_VERT(e,0))
406 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,2)==E_NTH_VERT(e,1));
407 else if(T_NTH_V(t,2)==E_NTH_VERT(e,0))
408 return(T_NTH_V(t,0)==E_NTH_VERT(e,1)||T_NTH_V(t,1)==E_NTH_VERT(e,1));
409
410 return(FALSE);
411 }
412
413 /* Test the new set of triangles for Delaunay condition. 'Edges' contains
414 all of the new edges added. The CCW triangle assoc with each edge is
415 tested against the opposite vertex of the CW triangle. If the vertex
416 lies inside the circle defined by the CCW triangle- the edge is swapped
417 for the opposite diagonal
418 */
419 smFixEdges(sm,add_list,delptr)
420 SM *sm;
421 LIST *add_list;
422 QUADTREE *delptr;
423
424 {
425 int e,t0_id,t1_id,e_new,e0,e1,e0_next,e1_next;
426 int i,v0_id,v1_id,v2_id,p_id,t0_nid,t1_nid;
427 FVECT v0,v1,v2,p,np,v;
428 TRI *t0,*t1;
429
430 FOR_ALL_EDGES(e)
431 {
432 t0_id = E_NTH_TRI(e,0);
433 t1_id = E_NTH_TRI(e,1);
434 if((t0_id==INVALID) || (t1_id==INVALID))
435 {
436 #ifdef DEBUG
437 error(CONSISTENCY,"smFix_edges: Unassigned edge nbr\n");
438 #endif
439 }
440 t0 = SM_NTH_TRI(sm,t0_id);
441 t1 = SM_NTH_TRI(sm,t1_id);
442 e0 = T_NTH_NBR_PTR(t1_id,t0);
443 e1 = T_NTH_NBR_PTR(t0_id,t1);
444
445 v0_id = E_NTH_VERT(e,0);
446 v1_id = E_NTH_VERT(e,1);
447 v2_id = T_NTH_V(t0,e0);
448 p_id = T_NTH_V(t1,e1);
449
450 smDir_in_cone(sm,v0,v0_id);
451 smDir_in_cone(sm,v1,v1_id);
452 smDir_in_cone(sm,v2,v2_id);
453
454 VCOPY(p,SM_NTH_WV(sm,p_id));
455 VSUB(p,p,SM_VIEW_CENTER(sm));
456 if(point_in_cone(p,v0,v1,v2))
457 {
458 smTris_swap_edge(sm,t0_id,t1_id,e0,e1,&t0_nid,&t1_nid,&add_list,
459 delptr);
460
461 /* Adjust the triangle pointers of the remaining edges to be
462 processed
463 */
464 FOR_ALL_EDGES_FROM(e,i)
465 {
466 if(E_NTH_TRI(i,0)==t0_id || E_NTH_TRI(i,0)==t1_id)
467 {
468 if(eIn_tri(i,SM_NTH_TRI(sm,t0_nid)))
469 SET_E_NTH_TRI(i,0,t0_nid);
470 else
471 SET_E_NTH_TRI(i,0,t1_nid);
472 }
473
474 if(E_NTH_TRI(i,1)==t0_id || E_NTH_TRI(i,1)==t1_id)
475 {
476 if(eIn_tri(i,SM_NTH_TRI(sm,t0_nid)))
477 SET_E_NTH_TRI(i,1,t0_nid);
478 else
479 SET_E_NTH_TRI(i,1,t1_nid);
480 }
481 }
482 t0_id = t0_nid;
483 t1_id = t1_nid;
484 e_new = eNew_edge();
485 SET_E_NTH_VERT(e_new,0,p_id);
486 SET_E_NTH_VERT(e_new,1,v2_id);
487 SET_E_NTH_TRI(e_new,0,t0_id);
488 SET_E_NTH_TRI(e_new,1,t1_id);
489 }
490 }
491 /* Add/Delete the appropriate triangles from the stree */
492 smUpdate_locator(sm,add_list,qtqueryset(*delptr));
493
494 }
495
496 /* Remove vertex "id" from the mesh- and retriangulate the resulting
497 hole: Returns TRUE if successful, FALSE otherwise.
498 */
499 int
500 smRemoveVertex(sm,id)
501 SM *sm;
502 int id;
503 {
504 LIST *b_list,*add_list;
505 QUADTREE delnode=-1;
506 int t_id;
507
508 /* generate list of edges that form the boundary of the
509 polygon formed by the triangles adjacent to vertex 'id'
510 */
511 b_list = smVertexPolygon(sm,id,&delnode);
512
513 add_list = NULL;
514 /* Triangulate polygonal hole */
515 if(!smTriangulate(sm,id,b_list,&add_list))
516 {
517 qtfreeleaf(delnode);
518 return(FALSE);
519 }
520 /* Fix up new triangles to be Delaunay-delnode contains set of
521 triangles to delete,add_list is the set of new triangles to add
522 */
523 smFixEdges(sm,add_list,&delnode);
524
525
526 qtfreeleaf(delnode);
527 return(TRUE);
528 }
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543