ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/objutil.c
(Generate patch)

Comparing ray/src/common/objutil.c (file contents):
Revision 2.2 by greg, Thu Apr 2 20:44:15 2020 UTC vs.
Revision 2.13 by greg, Wed Mar 3 18:53:08 2021 UTC

# Line 19 | Line 19 | static const char RCSid[] = "$Id$";
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))
# Line 44 | Line 44 | clearSelection(Scene *sc, int set)
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)
# Line 62 | Line 62 | selectGroup(Scene *sc, const char *gname, int invert)
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)
# Line 180 | Line 180 | chngFaceGroup(Scene *sc, Face *f, void *ptr)
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);
# Line 203 | Line 203 | chngFaceMaterial(Scene *sc, Face *f, void *ptr)
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);
# Line 259 | Line 259 | replace_vertex(Scene *sc, int prev, int repl, double e
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;
# Line 290 | Line 290 | replace_vertex(Scene *sc, int prev, int repl, double e
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)
# Line 315 | Line 315 | replace_vertex(Scene *sc, int prev, int repl, double e
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++) {
# Line 432 | Line 432 | findDuplicateFaces(Scene *sc)
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 */
# Line 460 | Line 460 | findDuplicateFaces(Scene *sc)
460                          ++nfound;
461                  }
462          }
463 +        if (verbose)
464 +                fprintf(stderr, "Found %d duplicate faces\n", nfound);
465          return(nfound);
466   }
467  
# Line 486 | Line 488 | deleteFaces(Scene *sc, int flreq, int flexc)
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 =
# Line 547 | Line 549 | addComment(Scene *sc, const char *comment)
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)
# Line 573 | Line 588 | add2facelist(Scene *sc, Face *f, int i)
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 */
# Line 599 | Line 614 | newScene(void)
614          return(sc);
615   }
616  
617 < /* Duplicate a scene */
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 = getGroupID(sc, nm);
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 = 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 > /* 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;
# Line 651 | Line 763 | dupScene(const Scene *osc)
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) +
# Line 661 | Line 775 | dupScene(const Scene *osc)
775                  sc->flist = f;
776                  sc->nfaces++;
777          }
778 +        deleteUnreferenced(sc);         /* jetsam */
779          return(sc);
780   }
781  
667 /* Transform entire scene */
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;
793 +
794 +        if ((sc == NULL) | (xac <= 0) | (xav == NULL))
795 +                return(0);
796 +                                        /* compute matrix */
797 +        if (xf(&myxf, xac, xav) < xac)
798 +                return(0);
799 +                                        /* transform vertices */
800 +        for (i = 0; i < sc->nverts; i++) {
801 +                VCOPY(vec, sc->vert[i].p);
802 +                multp3(vec, vec, myxf.xfm);
803 +                VCOPY(sc->vert[i].p, vec);
804 +        }
805 +                                        /* transform normals */
806 +        for (i = 0; i < sc->nnorms; i++) {
807 +                VCOPY(vec, sc->norm[i]);
808 +                multv3(vec, vec, myxf.xfm);
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 */
824 + int
825   xfmScene(Scene *sc, const char *xfm)
826   {
827          char    *xav[MAXAC+1];
828          int     xac, i;
674        XF      myxf;
675        FVECT   vec;
829  
830          if ((sc == NULL) | (xfm == NULL))
831                  return(0);
832 <        while (isspace(*xfm))           /* find first word */
832 >                                        /* skip spaces at beginning */
833 >        while (isspace(*xfm))
834                  xfm++;
835          if (!*xfm)
836                  return(0);
837 <                                        /* break into words for xf() */
837 >                                        /* parse string into words */
838          xav[0] = strcpy((char *)malloc(strlen(xfm)+1), xfm);
839          xac = 1; i = 0;
840          for ( ; ; ) {
# Line 691 | Line 845 | xfmScene(Scene *sc, const char *xfm)
845                          xav[0][i++] = '\0';
846                  if (!xfm[i])
847                          break;
848 <                if (xac >= MAXAC-1)
849 <                        goto bad_xform;
848 >                if (xac >= MAXAC-1) {
849 >                        free(xav[0]);
850 >                        return(0);
851 >                }
852                  xav[xac++] = xav[0] + i;
853          }
854          xav[xac] = NULL;
855 <        if (xf(&myxf, xac, xav) < xac)
700 <                goto bad_xform;
855 >        i = xfScene(sc, xac, xav);
856          free(xav[0]);
857 <                                        /* transform vertices */
858 <        for (i = 0; i < sc->nverts; i++) {
859 <                VCOPY(vec, sc->vert[i].p);
860 <                multp3(vec, vec, myxf.xfm);
861 <                VCOPY(sc->vert[i].p, vec);
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 <                                        /* transform normals */
888 <        for (i = 0; i < sc->nnorms; i++) {
889 <                VCOPY(vec, sc->norm[i]);
890 <                multv3(vec, vec, myxf.xfm);
891 <                vec[0] /= myxf.sca; vec[1] /= myxf.sca; vec[2] /= myxf.sca;
892 <                VCOPY(sc->norm[i], vec);
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 <        return xac;                     /* finito */
914 < bad_xform:
915 <        free(xav[0]);
916 <        return(0);
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   }
720 #undef MAXAC
953  
954   /* Free a scene */
955   void

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines