460 |
|
++nfound; |
461 |
|
} |
462 |
|
} |
463 |
+ |
if (verbose) |
464 |
+ |
fprintf(stderr, "Found %d duplicate faces\n", nfound); |
465 |
|
return(nfound); |
466 |
|
} |
467 |
|
|
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) |
710 |
|
return(f); |
711 |
|
} |
712 |
|
|
713 |
< |
/* Duplicate a scene */ |
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 */ |
793 |
– |
#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 |