ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/cvmesh.c
Revision: 2.3
Committed: Fri Mar 14 21:27:46 2003 UTC (21 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.2: +37 -31 lines
Log Message:
Added -a option to obj2mesh to incorporate materials in mesh

File Contents

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