| 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 |