| 8 |
|
*/ |
| 9 |
|
|
| 10 |
|
#include <stdlib.h> |
| 11 |
+ |
#include <ctype.h> |
| 12 |
|
#include "rtio.h" |
| 13 |
|
#include "rtmath.h" |
| 14 |
|
#include "rterror.h" |
| 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)) |
| 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++) { |
| 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) |
| 614 |
|
return(sc); |
| 615 |
|
} |
| 616 |
|
|
| 617 |
+ |
/* Add a vertex to a scene */ |
| 618 |
+ |
int |
| 619 |
+ |
addVertex(Scene *sc, double x, double y, double z) |
| 620 |
+ |
{ |
| 621 |
+ |
sc->vert = chunk_alloc(Vertex, sc->vert, sc->nverts); |
| 622 |
+ |
sc->vert[sc->nverts].p[0] = x; |
| 623 |
+ |
sc->vert[sc->nverts].p[1] = y; |
| 624 |
+ |
sc->vert[sc->nverts].p[2] = z; |
| 625 |
+ |
sc->vert[sc->nverts].vflist = NULL; |
| 626 |
+ |
return(sc->nverts++); |
| 627 |
+ |
} |
| 628 |
+ |
|
| 629 |
+ |
/* Add a texture coordinate to a scene */ |
| 630 |
+ |
int |
| 631 |
+ |
addTexture(Scene *sc, double u, double v) |
| 632 |
+ |
{ |
| 633 |
+ |
sc->tex = chunk_alloc(TexCoord, sc->tex, sc->ntex); |
| 634 |
+ |
sc->tex[sc->ntex].u = u; |
| 635 |
+ |
sc->tex[sc->ntex].v = v; |
| 636 |
+ |
return(sc->ntex++); |
| 637 |
+ |
} |
| 638 |
+ |
|
| 639 |
+ |
/* Add a surface normal to a scene */ |
| 640 |
+ |
int |
| 641 |
+ |
addNormal(Scene *sc, double xn, double yn, double zn) |
| 642 |
+ |
{ |
| 643 |
+ |
FVECT nrm; |
| 644 |
+ |
|
| 645 |
+ |
nrm[0] = xn; nrm[1] = yn; nrm[2] = zn; |
| 646 |
+ |
if (normalize(nrm) == .0) |
| 647 |
+ |
return(-1); |
| 648 |
+ |
sc->norm = chunk_alloc(Normal, sc->norm, sc->nnorms); |
| 649 |
+ |
VCOPY(sc->norm[sc->nnorms], nrm); |
| 650 |
+ |
return(sc->nnorms++); |
| 651 |
+ |
} |
| 652 |
+ |
|
| 653 |
+ |
/* Set current (last) group */ |
| 654 |
+ |
void |
| 655 |
+ |
setGroup(Scene *sc, const char *nm) |
| 656 |
+ |
{ |
| 657 |
+ |
sc->lastgrp = findName(nm, (const char **)sc->grpname, sc->ngrps); |
| 658 |
+ |
if (sc->lastgrp >= 0) |
| 659 |
+ |
return; |
| 660 |
+ |
sc->grpname = chunk_alloc(char *, sc->grpname, sc->ngrps); |
| 661 |
+ |
sc->grpname[sc->lastgrp=sc->ngrps++] = savqstr((char *)nm); |
| 662 |
+ |
} |
| 663 |
+ |
|
| 664 |
+ |
/* Set current (last) material */ |
| 665 |
+ |
void |
| 666 |
+ |
setMaterial(Scene *sc, const char *nm) |
| 667 |
+ |
{ |
| 668 |
+ |
sc->lastmat = findName(nm, (const char **)sc->matname, sc->nmats); |
| 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 |
+ |
/* 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 */ |
| 714 |
|
Scene * |
| 715 |
|
dupScene(const Scene *osc) |
| 774 |
|
} |
| 775 |
|
return(sc); |
| 776 |
|
} |
| 777 |
+ |
|
| 778 |
+ |
#define MAXAC 100 |
| 779 |
+ |
|
| 780 |
+ |
/* Transform entire scene */ |
| 781 |
+ |
int |
| 782 |
+ |
xfScene(Scene *sc, int xac, char *xav[]) |
| 783 |
+ |
{ |
| 784 |
+ |
char comm[24+MAXAC*8]; |
| 785 |
+ |
char *cp; |
| 786 |
+ |
XF myxf; |
| 787 |
+ |
FVECT vec; |
| 788 |
+ |
int i; |
| 789 |
+ |
|
| 790 |
+ |
if ((sc == NULL) | (xac <= 0) | (xav == NULL)) |
| 791 |
+ |
return(0); |
| 792 |
+ |
/* compute matrix */ |
| 793 |
+ |
if (xf(&myxf, xac, xav) < xac) |
| 794 |
+ |
return(0); |
| 795 |
+ |
/* transform vertices */ |
| 796 |
+ |
for (i = 0; i < sc->nverts; i++) { |
| 797 |
+ |
VCOPY(vec, sc->vert[i].p); |
| 798 |
+ |
multp3(vec, vec, myxf.xfm); |
| 799 |
+ |
VCOPY(sc->vert[i].p, vec); |
| 800 |
+ |
} |
| 801 |
+ |
/* transform normals */ |
| 802 |
+ |
for (i = 0; i < sc->nnorms; i++) { |
| 803 |
+ |
VCOPY(vec, sc->norm[i]); |
| 804 |
+ |
multv3(vec, vec, myxf.xfm); |
| 805 |
+ |
vec[0] /= myxf.sca; vec[1] /= myxf.sca; vec[2] /= myxf.sca; |
| 806 |
+ |
VCOPY(sc->norm[i], vec); |
| 807 |
+ |
} |
| 808 |
+ |
/* add comment */ |
| 809 |
+ |
cp = strcpy(comm, "Transformed by:"); |
| 810 |
+ |
for (i = 0; i < xac; i++) { |
| 811 |
+ |
while (*cp) cp++; |
| 812 |
+ |
*cp++ = ' '; |
| 813 |
+ |
strcpy(cp, xav[i]); |
| 814 |
+ |
} |
| 815 |
+ |
addComment(sc, comm); |
| 816 |
+ |
return(xac); /* all done */ |
| 817 |
+ |
} |
| 818 |
+ |
|
| 819 |
+ |
/* Ditto, using transform string rather than pre-parsed words */ |
| 820 |
+ |
int |
| 821 |
+ |
xfmScene(Scene *sc, const char *xfm) |
| 822 |
+ |
{ |
| 823 |
+ |
char *xav[MAXAC+1]; |
| 824 |
+ |
int xac, i; |
| 825 |
+ |
|
| 826 |
+ |
if ((sc == NULL) | (xfm == NULL)) |
| 827 |
+ |
return(0); |
| 828 |
+ |
/* skip spaces at beginning */ |
| 829 |
+ |
while (isspace(*xfm)) |
| 830 |
+ |
xfm++; |
| 831 |
+ |
if (!*xfm) |
| 832 |
+ |
return(0); |
| 833 |
+ |
/* parse string into words */ |
| 834 |
+ |
xav[0] = strcpy((char *)malloc(strlen(xfm)+1), xfm); |
| 835 |
+ |
xac = 1; i = 0; |
| 836 |
+ |
for ( ; ; ) { |
| 837 |
+ |
while (!isspace(xfm[++i])) |
| 838 |
+ |
if (!xfm[i]) |
| 839 |
+ |
break; |
| 840 |
+ |
while (isspace(xfm[i])) |
| 841 |
+ |
xav[0][i++] = '\0'; |
| 842 |
+ |
if (!xfm[i]) |
| 843 |
+ |
break; |
| 844 |
+ |
if (xac >= MAXAC-1) { |
| 845 |
+ |
free(xav[0]); |
| 846 |
+ |
return(0); |
| 847 |
+ |
} |
| 848 |
+ |
xav[xac++] = xav[0] + i; |
| 849 |
+ |
} |
| 850 |
+ |
xav[xac] = NULL; |
| 851 |
+ |
i = xfScene(sc, xac, xav); |
| 852 |
+ |
free(xav[0]); |
| 853 |
+ |
return(i); |
| 854 |
+ |
} |
| 855 |
+ |
#undef MAXAC |
| 856 |
|
|
| 857 |
|
/* Free a scene */ |
| 858 |
|
void |