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 */ |
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 */ |
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 = |
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 */ |
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 |
|
|
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 |