ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/cvmesh.c
Revision: 2.7
Committed: Thu Sep 18 16:53:53 2003 UTC (20 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +5 -4 lines
Log Message:
Reduced texture coordinate size to 16-bits/sample

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: cvmesh.c,v 2.6 2003/06/26 00:58:10 schorsch Exp $";
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 RREAL vc[3][2]; /* uv coords. */
27 } TRIDATA;
28
29 #define tdsize(fl) ((fl)&MT_UV ? sizeof(TRIDATA) : \
30 (fl)&MT_N ? sizeof(TRIDATA)-6*sizeof(RREAL) : \
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[0][1] = FHUGE;
61 ourmesh->uvlim[1][0] = 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(mo, n, vp, vn, vc) /* convert a polygon to extended triangles */
73 OBJECT mo;
74 int n;
75 FVECT *vp;
76 FVECT *vn;
77 RREAL (*vc)[2];
78 {
79 int tcnt = 0;
80 int flags;
81 RREAL *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 return(cvtri(mo, vp[0], vp[1], vp[2],
102 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 tcnt += cvtri(mo, vp[ord[0]], vp[ord[1]], vp[ord[2]],
119 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 RREAL 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 cvtri(mo, vp1, vp2, vp3, vn1, vn2, vn3, vc1, vc2, vc3)
159 OBJECT mo;
160 FVECT vp1, vp2, vp3;
161 FVECT vn1, vn2, vn3;
162 RREAL vc1[2], vc2[2], vc3[2];
163 {
164 static OBJECT fobj = OVOID;
165 char buf[32];
166 int flags;
167 TRIDATA *ts;
168 FACE *f;
169 OBJREC *fop;
170 int j;
171
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 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 = (RREAL *)malloc(9*sizeof(RREAL));
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 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 f = getface(fop);
202 if (f->area == 0.) {
203 free_os(fop);
204 return(0);
205 }
206 if (fop->os != (char *)f)
207 error(CONSISTENCY, "code error 2 in cvtri");
208 /* 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 fobj = OVOID; /* we used this one */
235 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 ts->obj = addmeshtri(ourmesh, vert, o->omod);
273 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 if (ourmesh->uvlim[0][0] > ourmesh->uvlim[1][0]) {
300 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; /* expand past endpoints */
305 marg = (2./(1L<<(8*sizeof(uint16)))) *
306 (ourmesh->uvlim[1][i] -
307 ourmesh->uvlim[0][i]);
308 ourmesh->uvlim[0][i] -= marg;
309 ourmesh->uvlim[1][i] += marg;
310 }
311 }
312 ourmesh->ldflags |= IO_BOUNDS;
313 }
314
315
316 static OCTREE
317 cvmeshoct(ot) /* convert triangles in subtree */
318 OCTREE ot;
319 {
320 int i;
321
322 if (isempty(ot))
323 return(EMPTY);
324
325 if (isfull(ot)) {
326 OBJECT oset1[MAXSET+1];
327 OBJECT oset2[MAXSET+1];
328 objset(oset1, ot);
329 oset2[0] = 0;
330 for (i = oset1[0]; i > 0; i--)
331 insertelem(oset2, cvmeshtri(oset1[i]));
332 return(fullnode(oset2));
333 }
334
335 for (i = 8; i--; )
336 octkid(ot, i) = cvmeshoct(octkid(ot, i));
337 return(ot);
338 }
339
340
341 MESH *
342 cvmesh() /* convert mesh and octree leaf nodes */
343 {
344 if (ourmesh == NULL)
345 return(NULL);
346 /* convert triangles in octree nodes */
347 ourmesh->mcube.cutree = cvmeshoct(ourmesh->mcube.cutree);
348 ourmesh->ldflags |= IO_SCENE|IO_TREE;
349
350 return(ourmesh);
351 }