ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/cvmesh.c
Revision: 2.12
Committed: Fri Jan 24 01:26:44 2014 UTC (10 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R2P1, rad5R3, HEAD
Changes since 2.11: +1 -64 lines
Log Message:
Hopeful fix to triangulation code for obj2mesh with N-sided polygons

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id: cvmesh.c,v 2.11 2011/02/18 19:00:43 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Radiance triangle mesh conversion routines
6     */
7    
8     #include "copyright.h"
9     #include "standard.h"
10     #include "cvmesh.h"
11     #include "otypes.h"
12     #include "face.h"
13 greg 2.8 #include "tmesh.h"
14 greg 2.1
15     /*
16     * We need to divide faces into triangles and record auxiliary information
17     * if given (surface normal and uv coordinates). We do this by extending
18     * the face structure linked to the OBJREC os member and putting our
19     * auxiliary after it -- a bit sly, but it works.
20     */
21    
22     /* Auxiliary data for triangle */
23     typedef struct {
24     int fl; /* flags of what we're storing */
25     OBJECT obj; /* mesh triangle ID */
26     FVECT vn[3]; /* normals */
27 schorsch 2.6 RREAL vc[3][2]; /* uv coords. */
28 greg 2.1 } TRIDATA;
29    
30     #define tdsize(fl) ((fl)&MT_UV ? sizeof(TRIDATA) : \
31 schorsch 2.6 (fl)&MT_N ? sizeof(TRIDATA)-6*sizeof(RREAL) : \
32 greg 2.1 sizeof(int)+sizeof(OBJECT))
33    
34     #define OMARGIN (10*FTINY) /* margin around global cube */
35    
36     MESH *ourmesh = NULL; /* our global mesh data structure */
37    
38     FVECT meshbounds[2]; /* mesh bounding box */
39    
40 schorsch 2.9 static void add2bounds(FVECT vp, RREAL vc[2]);
41     static OBJECT cvmeshtri(OBJECT obj);
42     static OCTREE cvmeshoct(OCTREE ot);
43    
44    
45 greg 2.1
46     MESH *
47 schorsch 2.9 cvinit( /* initialize empty mesh */
48     char *nm
49     )
50 greg 2.1 {
51     /* free old mesh, first */
52     if (ourmesh != NULL) {
53     freemesh(ourmesh);
54     ourmesh = NULL;
55     freeobjects(0, nobjects);
56     donesets();
57     }
58     if (nm == NULL)
59     return(NULL);
60     ourmesh = (MESH *)calloc(1, sizeof(MESH));
61     if (ourmesh == NULL)
62     goto nomem;
63     ourmesh->name = savestr(nm);
64     ourmesh->nref = 1;
65     ourmesh->ldflags = 0;
66     ourmesh->mcube.cutree = EMPTY;
67 greg 2.2 ourmesh->uvlim[0][0] = ourmesh->uvlim[0][1] = FHUGE;
68     ourmesh->uvlim[1][0] = ourmesh->uvlim[1][1] = -FHUGE;
69 greg 2.1 meshbounds[0][0] = meshbounds[0][1] = meshbounds[0][2] = FHUGE;
70     meshbounds[1][0] = meshbounds[1][1] = meshbounds[1][2] = -FHUGE;
71     return(ourmesh);
72     nomem:
73     error(SYSTEM, "out of memory in cvinit");
74     return(NULL);
75     }
76    
77    
78     static void
79 schorsch 2.9 add2bounds( /* add point and uv coordinate to bounds */
80     FVECT vp,
81     RREAL vc[2]
82     )
83 greg 2.1 {
84     register int j;
85    
86     for (j = 3; j--; ) {
87     if (vp[j] < meshbounds[0][j])
88     meshbounds[0][j] = vp[j];
89     if (vp[j] > meshbounds[1][j])
90     meshbounds[1][j] = vp[j];
91     }
92     if (vc == NULL)
93     return;
94     for (j = 2; j--; ) {
95     if (vc[j] < ourmesh->uvlim[0][j])
96     ourmesh->uvlim[0][j] = vc[j];
97     if (vc[j] > ourmesh->uvlim[1][j])
98     ourmesh->uvlim[1][j] = vc[j];
99     }
100     }
101    
102    
103     int /* create an extended triangle */
104 schorsch 2.9 cvtri(
105     OBJECT mo,
106     FVECT vp1,
107     FVECT vp2,
108     FVECT vp3,
109     FVECT vn1,
110     FVECT vn2,
111     FVECT vn3,
112     RREAL vc1[2],
113     RREAL vc2[2],
114     RREAL vc3[2]
115     )
116 greg 2.1 {
117 greg 2.3 static OBJECT fobj = OVOID;
118     char buf[32];
119     int flags;
120     TRIDATA *ts;
121     FACE *f;
122     OBJREC *fop;
123     int j;
124 greg 2.1
125 greg 2.8 flags = MT_V; /* check what we have */
126     if (vn1 != NULL && vn2 != NULL && vn3 != NULL) {
127     RREAL *rp;
128     switch (flat_tri(vp1, vp2, vp3, vn1, vn2, vn3)) {
129     case ISBENT:
130     flags |= MT_N;
131     /* fall through */
132     case ISFLAT:
133     break;
134     case RVBENT:
135     flags |= MT_N;
136     rp = vn1; vn1 = vn3; vn3 = rp;
137     /* fall through */
138     case RVFLAT:
139     rp = vp1; vp1 = vp3; vp3 = rp;
140     rp = vc1; vc1 = vc3; vc3 = rp;
141     break;
142     case DEGEN:
143     error(WARNING, "degenerate triangle");
144     return(0);
145     default:
146     error(INTERNAL, "bad return from flat_tri()");
147     }
148     }
149 greg 2.1 if (vc1 != NULL && vc2 != NULL && vc3 != NULL)
150     flags |= MT_UV;
151 greg 2.3 if (fobj == OVOID) { /* create new triangle object */
152     fobj = newobject();
153     if (fobj == OVOID)
154     goto nomem;
155     fop = objptr(fobj);
156     fop->omod = mo;
157     fop->otype = OBJ_FACE;
158 greg 2.11 sprintf(buf, "t%ld", (long)fobj);
159 greg 2.3 fop->oname = savqstr(buf);
160     fop->oargs.nfargs = 9;
161 schorsch 2.6 fop->oargs.farg = (RREAL *)malloc(9*sizeof(RREAL));
162 greg 2.3 if (fop->oargs.farg == NULL)
163     goto nomem;
164     } else { /* else reuse failed one */
165     fop = objptr(fobj);
166     if (fop->otype != OBJ_FACE || fop->oargs.nfargs != 9)
167     error(CONSISTENCY, "code error 1 in cvtri");
168     }
169 greg 2.1 for (j = 3; j--; ) {
170     fop->oargs.farg[j] = vp1[j];
171     fop->oargs.farg[3+j] = vp2[j];
172     fop->oargs.farg[6+j] = vp3[j];
173     }
174     /* create face record */
175 greg 2.3 f = getface(fop);
176     if (f->area == 0.) {
177     free_os(fop);
178 greg 2.1 return(0);
179     }
180     if (fop->os != (char *)f)
181 greg 2.3 error(CONSISTENCY, "code error 2 in cvtri");
182 greg 2.1 /* follow with auxliary data */
183     f = (FACE *)realloc((void *)f, sizeof(FACE)+tdsize(flags));
184     if (f == NULL)
185     goto nomem;
186     fop->os = (char *)f;
187     ts = (TRIDATA *)(f+1);
188     ts->fl = flags;
189     ts->obj = OVOID;
190     if (flags & MT_N)
191     for (j = 3; j--; ) {
192     ts->vn[0][j] = vn1[j];
193     ts->vn[1][j] = vn2[j];
194     ts->vn[2][j] = vn3[j];
195     }
196     if (flags & MT_UV)
197     for (j = 2; j--; ) {
198     ts->vc[0][j] = vc1[j];
199     ts->vc[1][j] = vc2[j];
200     ts->vc[2][j] = vc3[j];
201     }
202     else
203     vc1 = vc2 = vc3 = NULL;
204     /* update bounds */
205     add2bounds(vp1, vc1);
206     add2bounds(vp2, vc2);
207     add2bounds(vp3, vc3);
208 greg 2.3 fobj = OVOID; /* we used this one */
209 greg 2.1 return(1);
210     nomem:
211     error(SYSTEM, "out of memory in cvtri");
212     return(0);
213     }
214    
215    
216     static OBJECT
217 schorsch 2.9 cvmeshtri( /* add an extended triangle to our mesh */
218     OBJECT obj
219     )
220 greg 2.1 {
221     OBJREC *o = objptr(obj);
222     TRIDATA *ts;
223     MESHVERT vert[3];
224     int i, j;
225    
226     if (o->otype != OBJ_FACE)
227     error(CONSISTENCY, "non-face in mesh");
228     if (o->oargs.nfargs != 9)
229     error(CONSISTENCY, "non-triangle in mesh");
230     if (o->os == NULL)
231     error(CONSISTENCY, "missing face record in cvmeshtri");
232     ts = (TRIDATA *)((FACE *)o->os + 1);
233     if (ts->obj != OVOID) /* already added? */
234     return(ts->obj);
235     vert[0].fl = vert[1].fl = vert[2].fl = ts->fl;
236     for (i = 3; i--; )
237     for (j = 3; j--; )
238     vert[i].v[j] = o->oargs.farg[3*i+j];
239     if (ts->fl & MT_N)
240     for (i = 3; i--; )
241     for (j = 3; j--; )
242     vert[i].n[j] = ts->vn[i][j];
243     if (ts->fl & MT_UV)
244     for (i = 3; i--; )
245     for (j = 2; j--; )
246     vert[i].uv[j] = ts->vc[i][j];
247 greg 2.3 ts->obj = addmeshtri(ourmesh, vert, o->omod);
248 greg 2.1 if (ts->obj == OVOID)
249     error(INTERNAL, "addmeshtri failed");
250     return(ts->obj);
251     }
252    
253    
254     void
255 schorsch 2.9 cvmeshbounds(void) /* set mesh boundaries */
256 greg 2.1 {
257     int i;
258    
259     if (ourmesh == NULL)
260     return;
261     /* fix coordinate bounds */
262     for (i = 0; i < 3; i++) {
263 greg 2.5 if (meshbounds[0][i] > meshbounds[1][i])
264 greg 2.1 error(USER, "no polygons in mesh");
265     meshbounds[0][i] -= OMARGIN;
266     meshbounds[1][i] += OMARGIN;
267     if (meshbounds[1][i]-meshbounds[0][i] > ourmesh->mcube.cusize)
268     ourmesh->mcube.cusize = meshbounds[1][i] -
269     meshbounds[0][i];
270     }
271     for (i = 0; i < 3; i++)
272     ourmesh->mcube.cuorg[i] = (meshbounds[1][i]+meshbounds[0][i] -
273     ourmesh->mcube.cusize)*.5;
274 greg 2.2 if (ourmesh->uvlim[0][0] > ourmesh->uvlim[1][0]) {
275 greg 2.1 ourmesh->uvlim[0][0] = ourmesh->uvlim[0][1] = 0.;
276     ourmesh->uvlim[1][0] = ourmesh->uvlim[1][1] = 0.;
277     } else {
278     for (i = 0; i < 2; i++) {
279 greg 2.7 double marg; /* expand past endpoints */
280     marg = (2./(1L<<(8*sizeof(uint16)))) *
281     (ourmesh->uvlim[1][i] -
282 greg 2.10 ourmesh->uvlim[0][i]) + FTINY;
283 greg 2.1 ourmesh->uvlim[0][i] -= marg;
284     ourmesh->uvlim[1][i] += marg;
285     }
286     }
287     ourmesh->ldflags |= IO_BOUNDS;
288     }
289    
290    
291     static OCTREE
292 schorsch 2.9 cvmeshoct( /* convert triangles in subtree */
293     OCTREE ot
294     )
295 greg 2.1 {
296     int i;
297    
298     if (isempty(ot))
299     return(EMPTY);
300    
301     if (isfull(ot)) {
302     OBJECT oset1[MAXSET+1];
303     OBJECT oset2[MAXSET+1];
304     objset(oset1, ot);
305     oset2[0] = 0;
306     for (i = oset1[0]; i > 0; i--)
307     insertelem(oset2, cvmeshtri(oset1[i]));
308     return(fullnode(oset2));
309     }
310    
311     for (i = 8; i--; )
312     octkid(ot, i) = cvmeshoct(octkid(ot, i));
313     return(ot);
314     }
315    
316    
317     MESH *
318 schorsch 2.9 cvmesh(void) /* convert mesh and octree leaf nodes */
319 greg 2.1 {
320     if (ourmesh == NULL)
321     return(NULL);
322     /* convert triangles in octree nodes */
323     ourmesh->mcube.cutree = cvmeshoct(ourmesh->mcube.cutree);
324     ourmesh->ldflags |= IO_SCENE|IO_TREE;
325    
326     return(ourmesh);
327     }