ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/mesh.c
Revision: 2.20
Committed: Tue May 25 22:04:13 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 2.19: +3 -3 lines
Log Message:
Added const modifier to key and other parameters in lookup.h

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mesh.c,v 2.19 2004/03/28 20:33:12 schorsch Exp $";
3 #endif
4 /*
5 * Mesh support routines
6 */
7
8 #include <string.h>
9
10 #include "rtio.h"
11 #include "rtmath.h"
12 #include "rterror.h"
13 #include "paths.h"
14 #include "octree.h"
15 #include "object.h"
16 #include "otypes.h"
17 #include "mesh.h"
18
19 /* An encoded mesh vertex */
20 typedef struct {
21 int fl;
22 uint32 xyz[3];
23 int32 norm;
24 uint32 uv[2];
25 } MCVERT;
26
27 #define MPATCHBLKSIZ 128 /* patch allocation block size */
28
29 #define IO_LEGAL (IO_BOUNDS|IO_TREE|IO_SCENE)
30
31 static MESH *mlist = NULL; /* list of loaded meshes */
32
33 static lut_keycmpf_t cvcmp;
34 static lut_hashf_t cvhash;
35
36
37 static unsigned long
38 cvhash(p) /* hash an encoded vertex */
39 //MCVERT *cvp;
40 const void *p;
41 {
42 const MCVERT *cvp = (const MCVERT *)p;
43 unsigned long hval;
44
45 if (!(cvp->fl & MT_V))
46 return(0);
47 hval = cvp->xyz[0] ^ cvp->xyz[1] << 11 ^ cvp->xyz[2] << 22;
48 if (cvp->fl & MT_N)
49 hval ^= cvp->norm;
50 if (cvp->fl & MT_UV)
51 hval ^= cvp->uv[0] ^ cvp->uv[1] << 16;
52 return(hval);
53 }
54
55
56 static int
57 cvcmp(vv1, vv2) /* compare encoded vertices */
58 //register MCVERT *v1, *v2;
59 const void *vv1, *vv2;
60 {
61 const MCVERT *v1 = vv1, *v2 = vv2;
62 if (v1->fl != v2->fl)
63 return(1);
64 if (v1->xyz[0] != v2->xyz[0])
65 return(1);
66 if (v1->xyz[1] != v2->xyz[1])
67 return(1);
68 if (v1->xyz[2] != v2->xyz[2])
69 return(1);
70 if (v1->fl & MT_N && v1->norm != v2->norm)
71 return(1);
72 if (v1->fl & MT_UV) {
73 if (v1->uv[0] != v2->uv[0])
74 return(1);
75 if (v1->uv[1] != v2->uv[1])
76 return(1);
77 }
78 return(0);
79 }
80
81
82 MESH *
83 getmesh(mname, flags) /* get new mesh data reference */
84 char *mname;
85 int flags;
86 {
87 char *pathname;
88 register MESH *ms;
89
90 flags &= IO_LEGAL;
91 for (ms = mlist; ms != NULL; ms = ms->next)
92 if (!strcmp(mname, ms->name)) {
93 ms->nref++; /* increase reference count */
94 break;
95 }
96 if (ms == NULL) { /* load first time */
97 ms = (MESH *)calloc(1, sizeof(MESH));
98 if (ms == NULL)
99 error(SYSTEM, "out of memory in getmesh");
100 ms->name = savestr(mname);
101 ms->nref = 1;
102 ms->mcube.cutree = EMPTY;
103 ms->next = mlist;
104 mlist = ms;
105 }
106 if ((pathname = getpath(mname, getrlibpath(), R_OK)) == NULL) {
107 sprintf(errmsg, "cannot find mesh file \"%s\"", mname);
108 error(USER, errmsg);
109 }
110 flags &= ~ms->ldflags;
111 if (flags)
112 readmesh(ms, pathname, flags);
113 return(ms);
114 }
115
116
117 MESHINST *
118 getmeshinst(o, flags) /* create mesh instance */
119 OBJREC *o;
120 int flags;
121 {
122 register MESHINST *ins;
123
124 flags &= IO_LEGAL;
125 if ((ins = (MESHINST *)o->os) == NULL) {
126 if ((ins = (MESHINST *)malloc(sizeof(MESHINST))) == NULL)
127 error(SYSTEM, "out of memory in getmeshinst");
128 if (o->oargs.nsargs < 1)
129 objerror(o, USER, "bad # of arguments");
130 if (fullxf(&ins->x, o->oargs.nsargs-1,
131 o->oargs.sarg+1) != o->oargs.nsargs-1)
132 objerror(o, USER, "bad transform");
133 if (ins->x.f.sca < 0.0) {
134 ins->x.f.sca = -ins->x.f.sca;
135 ins->x.b.sca = -ins->x.b.sca;
136 }
137 ins->msh = NULL;
138 o->os = (char *)ins;
139 }
140 if (ins->msh == NULL)
141 ins->msh = getmesh(o->oargs.sarg[0], flags);
142 else if ((flags &= ~ins->msh->ldflags))
143 readmesh(ins->msh,
144 getpath(o->oargs.sarg[0], getrlibpath(), R_OK),
145 flags);
146 return(ins);
147 }
148
149
150 int
151 getmeshtrivid(tvid, mo, mp, ti) /* get triangle vertex ID's */
152 int32 tvid[3];
153 OBJECT *mo;
154 MESH *mp;
155 OBJECT ti;
156 {
157 int pn = ti >> 10;
158 MESHPATCH *pp;
159
160 if (pn >= mp->npatches)
161 return(0);
162 pp = &mp->patch[pn];
163 ti &= 0x3ff;
164 if (!(ti & 0x200)) { /* local triangle */
165 struct PTri *tp;
166 if (ti >= pp->ntris)
167 return(0);
168 tp = &pp->tri[ti];
169 tvid[0] = tvid[1] = tvid[2] = pn << 8;
170 tvid[0] |= tp->v1;
171 tvid[1] |= tp->v2;
172 tvid[2] |= tp->v3;
173 if (pp->trimat != NULL)
174 *mo = pp->trimat[ti];
175 else
176 *mo = pp->solemat;
177 if (*mo != OVOID)
178 *mo += mp->mat0;
179 return(1);
180 }
181 ti &= ~0x200;
182 if (!(ti & 0x100)) { /* single link vertex */
183 struct PJoin1 *tp1;
184 if (ti >= pp->nj1tris)
185 return(0);
186 tp1 = &pp->j1tri[ti];
187 tvid[0] = tp1->v1j;
188 tvid[1] = tvid[2] = pn << 8;
189 tvid[1] |= tp1->v2;
190 tvid[2] |= tp1->v3;
191 if ((*mo = tp1->mat) != OVOID)
192 *mo += mp->mat0;
193 return(1);
194 }
195 ti &= ~0x100;
196 { /* double link vertex */
197 struct PJoin2 *tp2;
198 if (ti >= pp->nj2tris)
199 return(0);
200 tp2 = &pp->j2tri[ti];
201 tvid[0] = tp2->v1j;
202 tvid[1] = tp2->v2j;
203 tvid[2] = pn << 8 | tp2->v3;
204 if ((*mo = tp2->mat) != OVOID)
205 *mo += mp->mat0;
206 }
207 return(1);
208 }
209
210
211 int
212 getmeshvert(vp, mp, vid, what) /* get triangle vertex from ID */
213 MESHVERT *vp;
214 MESH *mp;
215 int32 vid;
216 int what;
217 {
218 int pn = vid >> 8;
219 MESHPATCH *pp;
220 double vres;
221 register int i;
222
223 vp->fl = 0;
224 if (pn >= mp->npatches)
225 return(0);
226 pp = &mp->patch[pn];
227 vid &= 0xff;
228 if (vid >= pp->nverts)
229 return(0);
230 /* get location */
231 if (what & MT_V) {
232 vres = (1./4294967296.)*mp->mcube.cusize;
233 for (i = 0; i < 3; i++)
234 vp->v[i] = mp->mcube.cuorg[i] +
235 (pp->xyz[vid][i] + .5)*vres;
236 vp->fl |= MT_V;
237 }
238 /* get normal */
239 if (what & MT_N && pp->norm != NULL && pp->norm[vid]) {
240 decodedir(vp->n, pp->norm[vid]);
241 vp->fl |= MT_N;
242 }
243 /* get (u,v) */
244 if (what & MT_UV && pp->uv != NULL && pp->uv[vid][0]) {
245 for (i = 0; i < 2; i++)
246 vp->uv[i] = mp->uvlim[0][i] +
247 (mp->uvlim[1][i] - mp->uvlim[0][i])*
248 (pp->uv[vid][i] + .5)*(1./4294967296.);
249 vp->fl |= MT_UV;
250 }
251 return(vp->fl);
252 }
253
254
255 OBJREC *
256 getmeshpseudo(mp, mo) /* get mesh pseudo object for material */
257 MESH *mp;
258 OBJECT mo;
259 {
260 if (mo < mp->mat0 || mo >= mp->mat0 + mp->nmats)
261 error(INTERNAL, "modifier out of range in getmeshpseudo");
262 if (mp->pseudo == NULL) {
263 register int i;
264 mp->pseudo = (OBJREC *)calloc(mp->nmats, sizeof(OBJREC));
265 if (mp->pseudo == NULL)
266 error(SYSTEM, "out of memory in getmeshpseudo");
267 for (i = mp->nmats; i--; ) {
268 mp->pseudo[i].omod = mp->mat0 + i;
269 mp->pseudo[i].otype = OBJ_FACE;
270 mp->pseudo[i].oname = "M-Tri";
271 }
272 }
273 return(&mp->pseudo[mo - mp->mat0]);
274 }
275
276
277 int
278 getmeshtri(tv, mo, mp, ti, wha) /* get triangle vertices */
279 MESHVERT tv[3];
280 OBJECT *mo;
281 MESH *mp;
282 OBJECT ti;
283 int wha;
284 {
285 int32 tvid[3];
286
287 if (!getmeshtrivid(tvid, mo, mp, ti))
288 return(0);
289
290 getmeshvert(&tv[0], mp, tvid[0], wha);
291 getmeshvert(&tv[1], mp, tvid[1], wha);
292 getmeshvert(&tv[2], mp, tvid[2], wha);
293
294 return(tv[0].fl & tv[1].fl & tv[2].fl);
295 }
296
297
298 int32
299 addmeshvert(mp, vp) /* find/add a mesh vertex */
300 register MESH *mp;
301 MESHVERT *vp;
302 {
303 LUENT *lvp;
304 MCVERT cv;
305 register int i;
306
307 if (!(vp->fl & MT_V))
308 return(-1);
309 /* encode vertex */
310 for (i = 0; i < 3; i++) {
311 if (vp->v[i] < mp->mcube.cuorg[i])
312 return(-1);
313 if (vp->v[i] >= mp->mcube.cuorg[i] + mp->mcube.cusize)
314 return(-1);
315 cv.xyz[i] = (uint32)(4294967296. *
316 (vp->v[i] - mp->mcube.cuorg[i]) /
317 mp->mcube.cusize);
318 }
319 if (vp->fl & MT_N) /* assumes normalized! */
320 cv.norm = encodedir(vp->n);
321 if (vp->fl & MT_UV)
322 for (i = 0; i < 2; i++) {
323 if (vp->uv[i] <= mp->uvlim[0][i])
324 return(-1);
325 if (vp->uv[i] >= mp->uvlim[1][i])
326 return(-1);
327 cv.uv[i] = (uint32)(4294967296. *
328 (vp->uv[i] - mp->uvlim[0][i]) /
329 (mp->uvlim[1][i] - mp->uvlim[0][i]));
330 }
331 cv.fl = vp->fl;
332 if (mp->lut.tsiz == 0) {
333 mp->lut.hashf = cvhash;
334 mp->lut.keycmp = cvcmp;
335 mp->lut.freek = free;
336 if (!lu_init(&mp->lut, 50000))
337 goto nomem;
338 }
339 /* find entry */
340 lvp = lu_find(&mp->lut, (char *)&cv);
341 if (lvp == NULL)
342 goto nomem;
343 if (lvp->key == NULL) {
344 lvp->key = (char *)malloc(sizeof(MCVERT)+sizeof(int32));
345 memcpy((void *)lvp->key, (void *)&cv, sizeof(MCVERT));
346 }
347 if (lvp->data == NULL) { /* new vertex */
348 register MESHPATCH *pp;
349 if (mp->npatches <= 0) {
350 mp->patch = (MESHPATCH *)calloc(MPATCHBLKSIZ,
351 sizeof(MESHPATCH));
352 if (mp->patch == NULL)
353 goto nomem;
354 mp->npatches = 1;
355 } else if (mp->patch[mp->npatches-1].nverts >= 256) {
356 if (mp->npatches % MPATCHBLKSIZ == 0) {
357 mp->patch = (MESHPATCH *)realloc(
358 (void *)mp->patch,
359 (mp->npatches + MPATCHBLKSIZ)*
360 sizeof(MESHPATCH));
361 memset((void *)(mp->patch + mp->npatches), '\0',
362 MPATCHBLKSIZ*sizeof(MESHPATCH));
363 }
364 if (mp->npatches++ >= 1L<<22)
365 error(INTERNAL, "too many mesh patches");
366 }
367 pp = &mp->patch[mp->npatches-1];
368 if (pp->xyz == NULL) {
369 pp->xyz = (uint32 (*)[3])calloc(256, 3*sizeof(int32));
370 if (pp->xyz == NULL)
371 goto nomem;
372 }
373 for (i = 0; i < 3; i++)
374 pp->xyz[pp->nverts][i] = cv.xyz[i];
375 if (cv.fl & MT_N) {
376 if (pp->norm == NULL) {
377 pp->norm = (int32 *)calloc(256, sizeof(int32));
378 if (pp->norm == NULL)
379 goto nomem;
380 }
381 pp->norm[pp->nverts] = cv.norm;
382 }
383 if (cv.fl & MT_UV) {
384 if (pp->uv == NULL) {
385 pp->uv = (uint32 (*)[2])calloc(256,
386 2*sizeof(uint32));
387 if (pp->uv == NULL)
388 goto nomem;
389 }
390 for (i = 0; i < 2; i++)
391 pp->uv[pp->nverts][i] = cv.uv[i];
392 }
393 pp->nverts++;
394 lvp->data = lvp->key + sizeof(MCVERT);
395 *(int32 *)lvp->data = (mp->npatches-1) << 8 | (pp->nverts-1);
396 }
397 return(*(int32 *)lvp->data);
398 nomem:
399 error(SYSTEM, "out of memory in addmeshvert");
400 return(-1);
401 }
402
403
404 OBJECT
405 addmeshtri(mp, tv, mo) /* add a new mesh triangle */
406 MESH *mp;
407 MESHVERT tv[3];
408 OBJECT mo;
409 {
410 int32 vid[3], t;
411 int pn[3], i;
412 register MESHPATCH *pp;
413
414 if (!(tv[0].fl & tv[1].fl & tv[2].fl & MT_V))
415 return(OVOID);
416 /* find/allocate patch vertices */
417 for (i = 0; i < 3; i++) {
418 if ((vid[i] = addmeshvert(mp, &tv[i])) < 0)
419 return(OVOID);
420 pn[i] = vid[i] >> 8;
421 }
422 /* normalize material index */
423 if (mo != OVOID) {
424 if ((mo -= mp->mat0) >= mp->nmats)
425 mp->nmats = mo+1;
426 else if (mo < 0)
427 error(INTERNAL, "modifier range error in addmeshtri");
428 }
429 /* assign triangle */
430 if (pn[0] == pn[1] && pn[1] == pn[2]) { /* local case */
431 pp = &mp->patch[pn[0]];
432 if (pp->tri == NULL) {
433 pp->tri = (struct PTri *)malloc(
434 512*sizeof(struct PTri));
435 if (pp->tri == NULL)
436 goto nomem;
437 }
438 if (pp->ntris < 512) {
439 pp->tri[pp->ntris].v1 = vid[0] & 0xff;
440 pp->tri[pp->ntris].v2 = vid[1] & 0xff;
441 pp->tri[pp->ntris].v3 = vid[2] & 0xff;
442 if (pp->ntris == 0)
443 pp->solemat = mo;
444 else if (pp->trimat == NULL && mo != pp->solemat) {
445 pp->trimat = (int16 *)malloc(
446 512*sizeof(int16));
447 if (pp->trimat == NULL)
448 goto nomem;
449 for (i = pp->ntris; i--; )
450 pp->trimat[i] = pp->solemat;
451 }
452 if (pp->trimat != NULL)
453 pp->trimat[pp->ntris] = mo;
454 return(pn[0] << 10 | pp->ntris++);
455 }
456 }
457 if (pn[0] == pn[1]) {
458 t = vid[2]; vid[2] = vid[1]; vid[1] = vid[0]; vid[0] = t;
459 i = pn[2]; pn[2] = pn[1]; pn[1] = pn[0]; pn[0] = i;
460 } else if (pn[0] == pn[2]) {
461 t = vid[0]; vid[0] = vid[1]; vid[1] = vid[2]; vid[2] = t;
462 i = pn[0]; pn[0] = pn[1]; pn[1] = pn[2]; pn[2] = i;
463 }
464 if (pn[1] == pn[2]) { /* single link */
465 pp = &mp->patch[pn[1]];
466 if (pp->j1tri == NULL) {
467 pp->j1tri = (struct PJoin1 *)malloc(
468 256*sizeof(struct PJoin1));
469 if (pp->j1tri == NULL)
470 goto nomem;
471 }
472 if (pp->nj1tris < 256) {
473 pp->j1tri[pp->nj1tris].v1j = vid[0];
474 pp->j1tri[pp->nj1tris].v2 = vid[1] & 0xff;
475 pp->j1tri[pp->nj1tris].v3 = vid[2] & 0xff;
476 pp->j1tri[pp->nj1tris].mat = mo;
477 return(pn[1] << 10 | 0x200 | pp->nj1tris++);
478 }
479 }
480 /* double link */
481 pp = &mp->patch[pn[2]];
482 if (pp->j2tri == NULL) {
483 pp->j2tri = (struct PJoin2 *)malloc(
484 256*sizeof(struct PJoin2));
485 if (pp->j2tri == NULL)
486 goto nomem;
487 }
488 if (pp->nj2tris >= 256)
489 error(INTERNAL, "too many patch triangles in addmeshtri");
490 pp->j2tri[pp->nj2tris].v1j = vid[0];
491 pp->j2tri[pp->nj2tris].v2j = vid[1];
492 pp->j2tri[pp->nj2tris].v3 = vid[2] & 0xff;
493 pp->j2tri[pp->nj2tris].mat = mo;
494 return(pn[2] << 10 | 0x300 | pp->nj2tris++);
495 nomem:
496 error(SYSTEM, "out of memory in addmeshtri");
497 return(OVOID);
498 }
499
500
501 char *
502 checkmesh(mp) /* validate mesh data */
503 register MESH *mp;
504 {
505 static char embuf[128];
506 int nouvbounds = 1;
507 register int i;
508 /* basic checks */
509 if (mp == NULL)
510 return("NULL mesh pointer");
511 if (!mp->ldflags)
512 return("unassigned mesh");
513 if (mp->name == NULL)
514 return("missing mesh name");
515 if (mp->nref <= 0)
516 return("unreferenced mesh");
517 /* check boundaries */
518 if (mp->ldflags & IO_BOUNDS) {
519 if (mp->mcube.cusize <= FTINY)
520 return("illegal octree bounds in mesh");
521 nouvbounds = (mp->uvlim[1][0] - mp->uvlim[0][0] <= FTINY ||
522 mp->uvlim[1][1] - mp->uvlim[0][1] <= FTINY);
523 }
524 /* check octree */
525 if (mp->ldflags & IO_TREE) {
526 if (isempty(mp->mcube.cutree))
527 error(WARNING, "empty mesh octree");
528 }
529 /* check scene data */
530 if (mp->ldflags & IO_SCENE) {
531 if (!(mp->ldflags & IO_BOUNDS))
532 return("unbounded scene in mesh");
533 if (mp->mat0 < 0 || mp->mat0+mp->nmats > nobjects)
534 return("bad mesh modifier range");
535 for (i = mp->mat0+mp->nmats; i-- > mp->mat0; ) {
536 int otyp = objptr(i)->otype;
537 if (!ismodifier(otyp)) {
538 sprintf(embuf,
539 "non-modifier in mesh (%s \"%s\")",
540 ofun[otyp].funame, objptr(i)->oname);
541 return(embuf);
542 }
543 }
544 if (mp->npatches <= 0)
545 error(WARNING, "no patches in mesh");
546 for (i = 0; i < mp->npatches; i++) {
547 register MESHPATCH *pp = &mp->patch[i];
548 if (pp->nverts <= 0)
549 error(WARNING, "no vertices in patch");
550 else {
551 if (pp->xyz == NULL)
552 return("missing patch vertex list");
553 if (nouvbounds && pp->uv != NULL)
554 return("unreferenced uv coordinates");
555 }
556 if (pp->ntris > 0 && pp->tri == NULL)
557 return("missing patch triangle list");
558 if (pp->nj1tris > 0 && pp->j1tri == NULL)
559 return("missing patch joiner triangle list");
560 if (pp->nj2tris > 0 && pp->j2tri == NULL)
561 return("missing patch double-joiner list");
562 }
563 }
564 return(NULL); /* seems OK */
565 }
566
567
568 static void
569 tallyoctree(ot, ecp, lcp, ocp) /* tally octree size */
570 OCTREE ot;
571 int *ecp, *lcp, *ocp;
572 {
573 int i;
574
575 if (isempty(ot)) {
576 (*ecp)++;
577 return;
578 }
579 if (isfull(ot)) {
580 OBJECT oset[MAXSET+1];
581 (*lcp)++;
582 objset(oset, ot);
583 *ocp += oset[0];
584 return;
585 }
586 for (i = 0; i < 8; i++)
587 tallyoctree(octkid(ot, i), ecp, lcp, ocp);
588 }
589
590
591 void
592 printmeshstats(ms, fp) /* print out mesh statistics */
593 MESH *ms;
594 FILE *fp;
595 {
596 int lfcnt=0, lecnt=0, locnt=0;
597 int vcnt=0, ncnt=0, uvcnt=0;
598 int nscnt=0, uvscnt=0;
599 int tcnt=0, t1cnt=0, t2cnt=0;
600 int i, j;
601
602 tallyoctree(ms->mcube.cutree, &lecnt, &lfcnt, &locnt);
603 for (i = 0; i < ms->npatches; i++) {
604 register MESHPATCH *pp = &ms->patch[i];
605 vcnt += pp->nverts;
606 if (pp->norm != NULL) {
607 for (j = pp->nverts; j--; )
608 if (pp->norm[j])
609 ncnt++;
610 nscnt += pp->nverts;
611 }
612 if (pp->uv != NULL) {
613 for (j = pp->nverts; j--; )
614 if (pp->uv[j][0])
615 uvcnt++;
616 uvscnt += pp->nverts;
617 }
618 tcnt += pp->ntris;
619 t1cnt += pp->nj1tris;
620 t2cnt += pp->nj2tris;
621 }
622 fprintf(fp, "Mesh statistics:\n");
623 fprintf(fp, "\t%ld materials\n", ms->nmats);
624 fprintf(fp, "\t%d patches (%.2f MBytes)\n", ms->npatches,
625 (ms->npatches*sizeof(MESHPATCH) +
626 vcnt*3*sizeof(uint32) +
627 nscnt*sizeof(int32) +
628 uvscnt*2*sizeof(uint32) +
629 tcnt*sizeof(struct PTri) +
630 t1cnt*sizeof(struct PJoin1) +
631 t2cnt*sizeof(struct PJoin2))/(1024.*1024.));
632 fprintf(fp, "\t%d vertices (%.1f%% w/ normals, %.1f%% w/ uv)\n",
633 vcnt, 100.*ncnt/vcnt, 100.*uvcnt/vcnt);
634 fprintf(fp, "\t%d triangles (%.1f%% local, %.1f%% joiner)\n",
635 tcnt+t1cnt+t2cnt,
636 100.*tcnt/(tcnt+t1cnt+t2cnt),
637 100.*t1cnt/(tcnt+t1cnt+t2cnt));
638 fprintf(fp,
639 "\t%d leaves in octree (%.1f%% empty, %.2f avg. set size)\n",
640 lfcnt+lecnt, 100.*lecnt/(lfcnt+lecnt),
641 (double)locnt/lfcnt);
642 }
643
644
645 void
646 freemesh(ms) /* free mesh data */
647 register MESH *ms;
648 {
649 MESH mhead;
650 MESH *msp;
651
652 if (ms == NULL)
653 return;
654 if (ms->nref <= 0)
655 error(CONSISTENCY, "unreferenced mesh in freemesh");
656 ms->nref--;
657 if (ms->nref) /* still in use */
658 return;
659 /* else remove from list */
660 mhead.next = mlist;
661 for (msp = &mhead; msp->next != NULL; msp = msp->next)
662 if (msp->next == ms) {
663 msp->next = ms->next;
664 ms->next = NULL;
665 break;
666 }
667 if (ms->next != NULL) /* can't be in list anymore */
668 error(CONSISTENCY, "unlisted mesh in freemesh");
669 mlist = mhead.next;
670 /* free mesh data */
671 freestr(ms->name);
672 octfree(ms->mcube.cutree);
673 lu_done(&ms->lut);
674 if (ms->npatches > 0) {
675 register MESHPATCH *pp = ms->patch + ms->npatches;
676 while (pp-- > ms->patch) {
677 if (pp->j2tri != NULL)
678 free((void *)pp->j2tri);
679 if (pp->j1tri != NULL)
680 free((void *)pp->j1tri);
681 if (pp->tri != NULL)
682 free((void *)pp->tri);
683 if (pp->uv != NULL)
684 free((void *)pp->uv);
685 if (pp->norm != NULL)
686 free((void *)pp->norm);
687 if (pp->xyz != NULL)
688 free((void *)pp->xyz);
689 }
690 free((void *)ms->patch);
691 }
692 if (ms->pseudo != NULL)
693 free((void *)ms->pseudo);
694 free((void *)ms);
695 }
696
697
698 void
699 freemeshinst(o) /* free mesh instance */
700 OBJREC *o;
701 {
702 if (o->os == NULL)
703 return;
704 freemesh((*(MESHINST *)o->os).msh);
705 free((void *)o->os);
706 o->os = NULL;
707 }