19 |
|
int |
20 |
|
findName(const char *nm, const char **nmlist, int n) |
21 |
|
{ |
22 |
< |
register int i; |
22 |
> |
int i; |
23 |
|
|
24 |
|
for (i = n; i-- > 0; ) |
25 |
|
if (!strcmp(nmlist[i], nm)) |
44 |
|
void |
45 |
|
selectGroup(Scene *sc, const char *gname, int invert) |
46 |
|
{ |
47 |
< |
int gid = findName(gname, (const char **)sc->grpname, sc->ngrps); |
47 |
> |
int gid = getGroupID(sc, gname); |
48 |
|
Face *f; |
49 |
|
|
50 |
|
if (gid < 0) |
62 |
|
void |
63 |
|
selectMaterial(Scene *sc, const char *mname, int invert) |
64 |
|
{ |
65 |
< |
int mid = findName(mname, (const char **)sc->matname, sc->nmats); |
65 |
> |
int mid = getMaterialID(sc, mname); |
66 |
|
Face *f; |
67 |
|
|
68 |
|
if (mid < 0) |
180 |
|
int |
181 |
|
changeGroup(Scene *sc, const char *gname, int flreq, int flexc) |
182 |
|
{ |
183 |
< |
int grp = findName(gname, (const char **)sc->grpname, sc->ngrps); |
183 |
> |
int grp = getGroupID(sc, gname); |
184 |
|
if (grp < 0) { |
185 |
|
sc->grpname = chunk_alloc(char *, sc->grpname, sc->ngrps); |
186 |
|
sc->grpname[grp=sc->ngrps++] = savqstr((char *)gname); |
203 |
|
int |
204 |
|
changeMaterial(Scene *sc, const char *mname, int flreq, int flexc) |
205 |
|
{ |
206 |
< |
int mat = findName(mname, (const char **)sc->matname, sc->nmats); |
206 |
> |
int mat = getMaterialID(sc, mname); |
207 |
|
if (mat < 0) { |
208 |
|
sc->matname = chunk_alloc(char *, sc->matname, sc->nmats); |
209 |
|
sc->matname[mat=sc->nmats++] = savqstr((char *)mname); |
259 |
|
repl_tex[0] = -1; |
260 |
|
for (f = sc->vert[repl].vflist; f != NULL; f = f->v[j].fnext) { |
261 |
|
/* make sure prev isn't in there */ |
262 |
< |
for (j = 0; j < f->nv; j++) |
262 |
> |
for (j = f->nv; j-- > 0; ) |
263 |
|
if (f->v[j].vid == prev) |
264 |
|
return(0); |
265 |
< |
for (j = 0; j < f->nv; j++) |
265 |
> |
for (j = f->nv; j-- > 0; ) |
266 |
|
if (f->v[j].vid == repl) |
267 |
|
break; |
268 |
< |
if (j >= f->nv) |
268 |
> |
if (j < 0) |
269 |
|
goto linkerr; |
270 |
|
if (f->v[j].tid < 0) |
271 |
|
continue; |
290 |
|
/* get replacement normals */ |
291 |
|
repl_norm[0] = -1; |
292 |
|
for (f = sc->vert[repl].vflist; f != NULL; f = f->v[j].fnext) { |
293 |
< |
for (j = 0; j < f->nv; j++) |
293 |
> |
for (j = f->nv; j-- > 0; ) |
294 |
|
if (f->v[j].vid == repl) |
295 |
|
break; |
296 |
|
if (f->v[j].nid < 0) |
315 |
|
} |
316 |
|
/* replace occurrences of vertex */ |
317 |
|
for (f = sc->vert[prev].vflist; f != NULL; f = f->v[j].fnext) { |
318 |
< |
for (j = 0; j < f->nv; j++) |
318 |
> |
for (j = f->nv; j-- > 0; ) |
319 |
|
if (f->v[j].vid == prev) |
320 |
|
break; |
321 |
< |
if (j >= f->nv) |
321 |
> |
if (j < 0) |
322 |
|
goto linkerr; |
323 |
|
/* XXX doesn't allow for multiple references to prev in face */ |
324 |
|
f->v[j].vid = repl; /* replace vertex itself */ |
325 |
< |
if (faceArea(sc, f, NULL) <= FTINY) |
325 |
> |
if (faceArea(sc, f, NULL) <= FTINY*FTINY) |
326 |
|
f->flags |= FACE_DEGENERATE; |
327 |
|
if (f->v[j].tid >= 0) /* replace texture if appropriate */ |
328 |
|
for (i = 0; repl_tex[i] >= 0; i++) { |
432 |
|
/* look for duplicates */ |
433 |
|
for (f1 = sc->vert[vid].vflist; f1 != NULL; |
434 |
|
f1 = f1->v[j].fnext) { |
435 |
< |
for (j = 0; j < f1->nv; j++) |
435 |
> |
for (j = f1->nv; j-- > 0; ) |
436 |
|
if (f1->v[j].vid == vid) |
437 |
|
break; |
438 |
< |
if (j >= f1->nv) |
438 |
> |
if (j < 0) |
439 |
|
break; /* missing link! */ |
440 |
|
if (f1 == f) |
441 |
|
continue; /* shouldn't happen */ |
460 |
|
++nfound; |
461 |
|
} |
462 |
|
} |
463 |
+ |
if (verbose) |
464 |
+ |
fprintf(stderr, "Found %d duplicate faces\n", nfound); |
465 |
|
return(nfound); |
466 |
|
} |
467 |
|
|
488 |
|
continue; |
489 |
|
} |
490 |
|
while (vf != NULL) { |
491 |
< |
for (j = 0; j < vf->nv; j++) |
491 |
> |
for (j = vf->nv; j-- > 0; ) |
492 |
|
if (vf->v[j].vid == vid) |
493 |
|
break; |
494 |
< |
if (j >= vf->nv) |
494 |
> |
if (j < 0) |
495 |
|
break; /* error */ |
496 |
|
if (vf->v[j].fnext == ftst) { |
497 |
|
vf->v[j].fnext = |
549 |
|
sc->descr[sc->ndescr++] = savqstr((char *)comment); |
550 |
|
} |
551 |
|
|
552 |
+ |
/* Find index for comment containing the given string (starting from n) */ |
553 |
+ |
int |
554 |
+ |
findComment(Scene *sc, const char *match, int n) |
555 |
+ |
{ |
556 |
+ |
if (n >= sc->ndescr) |
557 |
+ |
return(-1); |
558 |
+ |
n *= (n > 0); |
559 |
+ |
while (n < sc->ndescr) |
560 |
+ |
if (strstr(sc->descr[n], match) != NULL) |
561 |
+ |
return(n); |
562 |
+ |
return(-1); |
563 |
+ |
} |
564 |
+ |
|
565 |
|
/* Clear comments */ |
566 |
|
void |
567 |
|
clearComments(Scene *sc) |
588 |
|
for ( ; ; ) { /* else find position */ |
589 |
|
if (fp == f) |
590 |
|
return; /* already in list */ |
591 |
< |
for (j = 0; j < fp->nv; j++) |
591 |
> |
for (j = fp->nv; j-- > 0; ) |
592 |
|
if (fp->v[j].vid == vid) |
593 |
|
break; |
594 |
< |
if (j >= fp->nv) |
594 |
> |
if (j < 0) |
595 |
|
error(CONSISTENCY, "Link error in add2facelist()"); |
596 |
|
if (fp->v[j].fnext == NULL) |
597 |
|
break; /* reached the end */ |
614 |
|
return(sc); |
615 |
|
} |
616 |
|
|
617 |
< |
/* Add a vertex to our scene */ |
617 |
> |
/* Add a vertex to a scene */ |
618 |
|
int |
619 |
|
addVertex(Scene *sc, double x, double y, double z) |
620 |
|
{ |
626 |
|
return(sc->nverts++); |
627 |
|
} |
628 |
|
|
629 |
< |
/* Add a texture coordinate to our scene */ |
629 |
> |
/* Add a texture coordinate to a scene */ |
630 |
|
int |
631 |
|
addTexture(Scene *sc, double u, double v) |
632 |
|
{ |
636 |
|
return(sc->ntex++); |
637 |
|
} |
638 |
|
|
639 |
< |
/* Add a surface normal to our scene */ |
639 |
> |
/* Add a surface normal to a scene */ |
640 |
|
int |
641 |
|
addNormal(Scene *sc, double xn, double yn, double zn) |
642 |
|
{ |
654 |
|
void |
655 |
|
setGroup(Scene *sc, const char *nm) |
656 |
|
{ |
657 |
< |
sc->lastgrp = findName(nm, (const char **)sc->grpname, sc->ngrps); |
657 |
> |
sc->lastgrp = getGroupID(sc, nm); |
658 |
|
if (sc->lastgrp >= 0) |
659 |
|
return; |
660 |
|
sc->grpname = chunk_alloc(char *, sc->grpname, sc->ngrps); |
665 |
|
void |
666 |
|
setMaterial(Scene *sc, const char *nm) |
667 |
|
{ |
668 |
< |
sc->lastmat = findName(nm, (const char **)sc->matname, sc->nmats); |
668 |
> |
sc->lastmat = getMaterialID(sc, nm); |
669 |
|
if (sc->lastmat >= 0) |
670 |
|
return; |
671 |
|
sc->matname = chunk_alloc(char *, sc->matname, sc->nmats); |
672 |
|
sc->matname[sc->lastmat=sc->nmats++] = savqstr((char *)nm); |
673 |
|
} |
674 |
|
|
675 |
< |
/* Duplicate a scene */ |
675 |
> |
/* Add new face to a scene */ |
676 |
> |
Face * |
677 |
> |
addFace(Scene *sc, VNDX vid[], int nv) |
678 |
> |
{ |
679 |
> |
Face *f; |
680 |
> |
int i; |
681 |
> |
|
682 |
> |
if (nv < 3) |
683 |
> |
return(NULL); |
684 |
> |
f = (Face *)emalloc(sizeof(Face)+sizeof(VertEnt)*(nv-3)); |
685 |
> |
f->flags = 0; |
686 |
> |
f->nv = nv; |
687 |
> |
f->grp = sc->lastgrp; |
688 |
> |
f->mat = sc->lastmat; |
689 |
> |
for (i = 0; i < nv; i++) { /* add each vertex */ |
690 |
> |
int j; |
691 |
> |
f->v[i].vid = vid[i][0]; |
692 |
> |
f->v[i].tid = vid[i][1]; |
693 |
> |
f->v[i].nid = vid[i][2]; |
694 |
> |
f->v[i].fnext = NULL; |
695 |
> |
for (j = i; j-- > 0; ) |
696 |
> |
if (f->v[j].vid == vid[i][0]) |
697 |
> |
break; |
698 |
> |
if (j < 0) { /* first occurrence? */ |
699 |
> |
f->v[i].fnext = sc->vert[vid[i][0]].vflist; |
700 |
> |
sc->vert[vid[i][0]].vflist = f; |
701 |
> |
} else if (nv == 3) /* degenerate triangle? */ |
702 |
> |
f->flags |= FACE_DEGENERATE; |
703 |
> |
} |
704 |
> |
f->next = sc->flist; /* push onto face list */ |
705 |
> |
sc->flist = f; |
706 |
> |
sc->nfaces++; |
707 |
> |
/* check face area */ |
708 |
> |
if (!(f->flags & FACE_DEGENERATE) && faceArea(sc, f, NULL) <= FTINY*FTINY) |
709 |
> |
f->flags |= FACE_DEGENERATE; |
710 |
> |
return(f); |
711 |
> |
} |
712 |
> |
|
713 |
> |
/* Duplicate a scene, optionally selecting faces */ |
714 |
|
Scene * |
715 |
< |
dupScene(const Scene *osc) |
715 |
> |
dupScene(const Scene *osc, int flreq, int flexc) |
716 |
|
{ |
717 |
+ |
int fltest = flreq | flexc; |
718 |
|
Scene *sc; |
719 |
|
const Face *fo; |
720 |
|
Face *f; |
763 |
|
sc->nnorms = osc->nnorms; |
764 |
|
} |
765 |
|
for (fo = osc->flist; fo != NULL; fo = fo->next) { |
766 |
+ |
if ((fo->flags & fltest) != flreq) |
767 |
+ |
continue; |
768 |
|
f = (Face *)emalloc(sizeof(Face) + |
769 |
|
sizeof(VertEnt)*(fo->nv-3)); |
770 |
|
memcpy((void *)f, (const void *)fo, sizeof(Face) + |
775 |
|
sc->flist = f; |
776 |
|
sc->nfaces++; |
777 |
|
} |
778 |
+ |
deleteUnreferenced(sc); /* jetsam */ |
779 |
|
return(sc); |
780 |
|
} |
781 |
|
|
782 |
+ |
#define MAXAC 100 |
783 |
+ |
|
784 |
|
/* Transform entire scene */ |
785 |
|
int |
786 |
|
xfScene(Scene *sc, int xac, char *xav[]) |
787 |
|
{ |
788 |
+ |
char comm[24+MAXAC*8]; |
789 |
+ |
char *cp; |
790 |
|
XF myxf; |
791 |
|
FVECT vec; |
792 |
|
int i; |
809 |
|
vec[0] /= myxf.sca; vec[1] /= myxf.sca; vec[2] /= myxf.sca; |
810 |
|
VCOPY(sc->norm[i], vec); |
811 |
|
} |
812 |
+ |
/* add comment */ |
813 |
+ |
cp = strcpy(comm, "Transformed by:"); |
814 |
+ |
for (i = 0; i < xac; i++) { |
815 |
+ |
while (*cp) cp++; |
816 |
+ |
*cp++ = ' '; |
817 |
+ |
strcpy(cp, xav[i]); |
818 |
+ |
} |
819 |
+ |
addComment(sc, comm); |
820 |
|
return(xac); /* all done */ |
821 |
|
} |
822 |
|
|
823 |
|
/* Ditto, using transform string rather than pre-parsed words */ |
755 |
– |
#define MAXAC 100 |
824 |
|
int |
825 |
|
xfmScene(Scene *sc, const char *xfm) |
826 |
|
{ |
857 |
|
return(i); |
858 |
|
} |
859 |
|
#undef MAXAC |
860 |
+ |
|
861 |
+ |
/* Delete unreferenced vertices, normals, texture coords */ |
862 |
+ |
void |
863 |
+ |
deleteUnreferenced(Scene *sc) |
864 |
+ |
{ |
865 |
+ |
int *vmap; |
866 |
+ |
Face *f; |
867 |
+ |
int nused, i; |
868 |
+ |
/* allocate index map */ |
869 |
+ |
if (!sc->nverts) |
870 |
+ |
return; |
871 |
+ |
i = sc->nverts; |
872 |
+ |
if (sc->ntex > i) |
873 |
+ |
i = sc->ntex; |
874 |
+ |
if (sc->nnorms > i) |
875 |
+ |
i = sc->nnorms; |
876 |
+ |
vmap = (int *)emalloc(sizeof(int)*i); |
877 |
+ |
/* remap positions */ |
878 |
+ |
for (i = nused = 0; i < sc->nverts; i++) { |
879 |
+ |
if (sc->vert[i].vflist == NULL) { |
880 |
+ |
vmap[i] = -1; |
881 |
+ |
continue; |
882 |
+ |
} |
883 |
+ |
if (nused != i) |
884 |
+ |
sc->vert[nused] = sc->vert[i]; |
885 |
+ |
vmap[i] = nused++; |
886 |
+ |
} |
887 |
+ |
if (nused == sc->nverts) |
888 |
+ |
goto skip_pos; |
889 |
+ |
sc->vert = (Vertex *)erealloc((char *)sc->vert, |
890 |
+ |
sizeof(Vertex)*(nused+(CHUNKSIZ-1))); |
891 |
+ |
sc->nverts = nused; |
892 |
+ |
for (f = sc->flist; f != NULL; f = f->next) |
893 |
+ |
for (i = f->nv; i--; ) |
894 |
+ |
if ((f->v[i].vid = vmap[f->v[i].vid]) < 0) |
895 |
+ |
error(CONSISTENCY, |
896 |
+ |
"Link error in del_unref_verts()"); |
897 |
+ |
skip_pos: |
898 |
+ |
/* remap texture coord's */ |
899 |
+ |
if (!sc->ntex) |
900 |
+ |
goto skip_tex; |
901 |
+ |
memset((void *)vmap, 0, sizeof(int)*sc->ntex); |
902 |
+ |
for (f = sc->flist; f != NULL; f = f->next) |
903 |
+ |
for (i = f->nv; i--; ) |
904 |
+ |
if (f->v[i].tid >= 0) |
905 |
+ |
vmap[f->v[i].tid] = 1; |
906 |
+ |
for (i = nused = 0; i < sc->ntex; i++) { |
907 |
+ |
if (!vmap[i]) |
908 |
+ |
continue; |
909 |
+ |
if (nused != i) |
910 |
+ |
sc->tex[nused] = sc->tex[i]; |
911 |
+ |
vmap[i] = nused++; |
912 |
+ |
} |
913 |
+ |
if (nused == sc->ntex) |
914 |
+ |
goto skip_tex; |
915 |
+ |
sc->tex = (TexCoord *)erealloc((char *)sc->tex, |
916 |
+ |
sizeof(TexCoord)*(nused+(CHUNKSIZ-1))); |
917 |
+ |
sc->ntex = nused; |
918 |
+ |
for (f = sc->flist; f != NULL; f = f->next) |
919 |
+ |
for (i = f->nv; i--; ) |
920 |
+ |
if (f->v[i].tid >= 0) |
921 |
+ |
f->v[i].tid = vmap[f->v[i].tid]; |
922 |
+ |
skip_tex: |
923 |
+ |
/* remap normals */ |
924 |
+ |
if (!sc->nnorms) |
925 |
+ |
goto skip_norms; |
926 |
+ |
memset((void *)vmap, 0, sizeof(int)*sc->nnorms); |
927 |
+ |
for (f = sc->flist; f != NULL; f = f->next) |
928 |
+ |
for (i = f->nv; i--; ) |
929 |
+ |
if (f->v[i].nid >= 0) |
930 |
+ |
vmap[f->v[i].nid] = 1; |
931 |
+ |
for (i = nused = 0; i < sc->nnorms; i++) { |
932 |
+ |
if (!vmap[i]) |
933 |
+ |
continue; |
934 |
+ |
if (nused != i) |
935 |
+ |
memcpy((void *)sc->norm[nused], |
936 |
+ |
(void *)sc->norm[i], |
937 |
+ |
sizeof(Normal)); |
938 |
+ |
vmap[i] = nused++; |
939 |
+ |
} |
940 |
+ |
if (nused == sc->nnorms) |
941 |
+ |
goto skip_norms; |
942 |
+ |
sc->norm = (Normal *)erealloc((char *)sc->norm, |
943 |
+ |
sizeof(Normal)*(nused+(CHUNKSIZ-1))); |
944 |
+ |
sc->nnorms = nused; |
945 |
+ |
for (f = sc->flist; f != NULL; f = f->next) |
946 |
+ |
for (i = f->nv; i--; ) |
947 |
+ |
if (f->v[i].nid >= 0) |
948 |
+ |
f->v[i].nid = vmap[f->v[i].nid]; |
949 |
+ |
skip_norms: |
950 |
+ |
/* clean up */ |
951 |
+ |
efree((char *)vmap); |
952 |
+ |
} |
953 |
|
|
954 |
|
/* Free a scene */ |
955 |
|
void |