ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/cvmesh.c
Revision: 2.1
Committed: Tue Mar 11 17:08:55 2003 UTC (21 years ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
First working version of new "mesh" primitive, obj2mesh converter

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     ourmesh->uvlim[0][0] = ourmesh->uvlim[1][0] = FHUGE;
61     ourmesh->uvlim[0][1] = ourmesh->uvlim[1][1] = -FHUGE;
62     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     cvpoly(n, vp, vn, vc) /* convert a polygon to extended triangles */
73     int n;
74     FVECT *vp;
75     FVECT *vn;
76     FLOAT (*vc)[2];
77     {
78     int tcnt = 0;
79     int flags;
80     FLOAT *tn[3], *tc[3];
81     int *ord;
82     int i, j;
83    
84     if (n < 3) /* degenerate face */
85     return(0);
86     flags = MT_V;
87     if (vn != NULL) {
88     tn[0] = vn[0]; tn[1] = vn[1]; tn[2] = vn[2];
89     flags |= MT_N;
90     } else {
91     tn[0] = tn[1] = tn[2] = NULL;
92     }
93     if (vc != NULL) {
94     tc[0] = vc[0]; tc[1] = vc[1]; tc[2] = vc[2];
95     flags |= MT_UV;
96     } else {
97     tc[0] = tc[1] = tc[2] = NULL;
98     }
99     if (n == 3) /* output single triangle */
100     return(cvtri(vp[0], vp[1], vp[2],
101     tn[0], tn[1], tn[2],
102     tc[0], tc[1], tc[2]));
103    
104     /* decimate polygon (assumes convex) */
105     ord = (int *)malloc(n*sizeof(int));
106     if (ord == NULL)
107     error(SYSTEM, "out of memory in cvpoly");
108     for (i = n; i--; )
109     ord[i] = i;
110     while (n >= 3) {
111     if (flags & MT_N)
112     for (i = 3; i--; )
113     tn[i] = vn[ord[i]];
114     if (flags & MT_UV)
115     for (i = 3; i--; )
116     tc[i] = vc[ord[i]];
117     i = cvtri(vp[ord[0]], vp[ord[1]], vp[ord[2]],
118     tn[0], tn[1], tn[2],
119     tc[0], tc[1], tc[2]);
120     if (i < 0)
121     return(i);
122     tcnt += i;
123     /* remove vertex and rotate */
124     n--;
125     j = ord[0];
126     for (i = 0; i < n-1; i++)
127     ord[i] = ord[i+2];
128     ord[i] = j;
129     }
130     free((void *)ord);
131     return(tcnt);
132     }
133    
134    
135     static void
136     add2bounds(vp, vc) /* add point and uv coordinate to bounds */
137     FVECT vp;
138     FLOAT vc[2];
139     {
140     register int j;
141    
142     for (j = 3; j--; ) {
143     if (vp[j] < meshbounds[0][j])
144     meshbounds[0][j] = vp[j];
145     if (vp[j] > meshbounds[1][j])
146     meshbounds[1][j] = vp[j];
147     }
148     if (vc == NULL)
149     return;
150     for (j = 2; j--; ) {
151     if (vc[j] < ourmesh->uvlim[0][j])
152     ourmesh->uvlim[0][j] = vc[j];
153     if (vc[j] > ourmesh->uvlim[1][j])
154     ourmesh->uvlim[1][j] = vc[j];
155     }
156     }
157    
158    
159     int /* create an extended triangle */
160     cvtri(vp1, vp2, vp3, vn1, vn2, vn3, vc1, vc2, vc3)
161     FVECT vp1, vp2, vp3;
162     FVECT vn1, vn2, vn3;
163     FLOAT vc1[2], vc2[2], vc3[2];
164     {
165     char buf[32];
166     int flags;
167     TRIDATA *ts;
168     OBJECT fobj;
169     FACE *f;
170     OBJREC *fop;
171     int j;
172    
173     flags = MT_V;
174     if (vn1 != NULL && vn2 != NULL && vn3 != NULL)
175     flags |= MT_N;
176     if (vc1 != NULL && vc2 != NULL && vc3 != NULL)
177     flags |= MT_UV;
178     /* create extended triangle */
179     fobj = newobject();
180     if (fobj == OVOID)
181     return(-1);
182     fop = objptr(fobj);
183     fop->omod = OVOID;
184     fop->otype = OBJ_FACE;
185     sprintf(buf, "t%d", fobj);
186     fop->oname = savqstr(buf);
187     fop->oargs.nfargs = 9;
188     fop->oargs.farg = (FLOAT *)malloc(9*sizeof(FLOAT));
189     if (fop->oargs.farg == NULL)
190     goto nomem;
191     for (j = 3; j--; ) {
192     fop->oargs.farg[j] = vp1[j];
193     fop->oargs.farg[3+j] = vp2[j];
194     fop->oargs.farg[6+j] = vp3[j];
195     }
196     /* create face record */
197     if ((f = getface(fop)) == NULL || f->area == 0.) {
198     freeobjects(fobj, 1);
199     return(0);
200     }
201     if (fop->os != (char *)f)
202     error(CONSISTENCY, "code error in cvtri");
203     /* follow with auxliary data */
204     f = (FACE *)realloc((void *)f, sizeof(FACE)+tdsize(flags));
205     if (f == NULL)
206     goto nomem;
207     fop->os = (char *)f;
208     ts = (TRIDATA *)(f+1);
209     ts->fl = flags;
210     ts->obj = OVOID;
211     if (flags & MT_N)
212     for (j = 3; j--; ) {
213     ts->vn[0][j] = vn1[j];
214     ts->vn[1][j] = vn2[j];
215     ts->vn[2][j] = vn3[j];
216     }
217     if (flags & MT_UV)
218     for (j = 2; j--; ) {
219     ts->vc[0][j] = vc1[j];
220     ts->vc[1][j] = vc2[j];
221     ts->vc[2][j] = vc3[j];
222     }
223     else
224     vc1 = vc2 = vc3 = NULL;
225     /* update bounds */
226     add2bounds(vp1, vc1);
227     add2bounds(vp2, vc2);
228     add2bounds(vp3, vc3);
229     return(1);
230     nomem:
231     error(SYSTEM, "out of memory in cvtri");
232     return(0);
233     }
234    
235    
236     static OBJECT
237     cvmeshtri(obj) /* add an extended triangle to our mesh */
238     OBJECT obj;
239     {
240     OBJREC *o = objptr(obj);
241     TRIDATA *ts;
242     MESHVERT vert[3];
243     int i, j;
244    
245     if (o->otype != OBJ_FACE)
246     error(CONSISTENCY, "non-face in mesh");
247     if (o->oargs.nfargs != 9)
248     error(CONSISTENCY, "non-triangle in mesh");
249     if (o->os == NULL)
250     error(CONSISTENCY, "missing face record in cvmeshtri");
251     ts = (TRIDATA *)((FACE *)o->os + 1);
252     if (ts->obj != OVOID) /* already added? */
253     return(ts->obj);
254     vert[0].fl = vert[1].fl = vert[2].fl = ts->fl;
255     for (i = 3; i--; )
256     for (j = 3; j--; )
257     vert[i].v[j] = o->oargs.farg[3*i+j];
258     if (ts->fl & MT_N)
259     for (i = 3; i--; )
260     for (j = 3; j--; )
261     vert[i].n[j] = ts->vn[i][j];
262     if (ts->fl & MT_UV)
263     for (i = 3; i--; )
264     for (j = 2; j--; )
265     vert[i].uv[j] = ts->vc[i][j];
266     ts->obj = addmeshtri(ourmesh, vert);
267     if (ts->obj == OVOID)
268     error(INTERNAL, "addmeshtri failed");
269     return(ts->obj);
270     }
271    
272    
273     void
274     cvmeshbounds() /* set mesh boundaries */
275     {
276     int i;
277    
278     if (ourmesh == NULL)
279     return;
280     /* fix coordinate bounds */
281     for (i = 0; i < 3; i++) {
282     if (meshbounds[0][i] >= meshbounds[1][i])
283     error(USER, "no polygons in mesh");
284     meshbounds[0][i] -= OMARGIN;
285     meshbounds[1][i] += OMARGIN;
286     if (meshbounds[1][i]-meshbounds[0][i] > ourmesh->mcube.cusize)
287     ourmesh->mcube.cusize = meshbounds[1][i] -
288     meshbounds[0][i];
289     }
290     for (i = 0; i < 3; i++)
291     ourmesh->mcube.cuorg[i] = (meshbounds[1][i]+meshbounds[0][i] -
292     ourmesh->mcube.cusize)*.5;
293     if (ourmesh->uvlim[0][0] >= ourmesh->uvlim[1][0]) {
294     ourmesh->uvlim[0][0] = ourmesh->uvlim[0][1] = 0.;
295     ourmesh->uvlim[1][0] = ourmesh->uvlim[1][1] = 0.;
296     } else {
297     for (i = 0; i < 2; i++) {
298     double marg;
299     marg = 1e-6*(ourmesh->uvlim[1][i] -
300     ourmesh->uvlim[0][i]);
301     ourmesh->uvlim[0][i] -= marg;
302     ourmesh->uvlim[1][i] += marg;
303     }
304     }
305     ourmesh->ldflags |= IO_BOUNDS;
306     }
307    
308    
309     static OCTREE
310     cvmeshoct(ot) /* convert triangles in subtree */
311     OCTREE ot;
312     {
313     int i;
314    
315     if (isempty(ot))
316     return(EMPTY);
317    
318     if (isfull(ot)) {
319     OBJECT oset1[MAXSET+1];
320     OBJECT oset2[MAXSET+1];
321     objset(oset1, ot);
322     oset2[0] = 0;
323     for (i = oset1[0]; i > 0; i--)
324     insertelem(oset2, cvmeshtri(oset1[i]));
325     return(fullnode(oset2));
326     }
327    
328     for (i = 8; i--; )
329     octkid(ot, i) = cvmeshoct(octkid(ot, i));
330     return(ot);
331     }
332    
333    
334     MESH *
335     cvmesh() /* convert mesh and octree leaf nodes */
336     {
337     if (ourmesh == NULL)
338     return(NULL);
339     /* convert triangles in octree nodes */
340     ourmesh->mcube.cutree = cvmeshoct(ourmesh->mcube.cutree);
341     ourmesh->ldflags |= IO_SCENE|IO_TREE;
342    
343     return(ourmesh);
344     }