--- ray/src/common/objutil.c 2021/04/07 16:40:28 2.16 +++ ray/src/common/objutil.c 2021/05/01 00:58:18 2.20 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: objutil.c,v 2.16 2021/04/07 16:40:28 greg Exp $"; +static const char RCSid[] = "$Id: objutil.c,v 2.20 2021/05/01 00:58:18 greg Exp $"; #endif /* * Basic .OBJ scene handling routines. @@ -700,6 +700,89 @@ addFace(Scene *sc, VNDX vid[], int nv) return(f); } +/* Get neighbor vertices: malloc array with valence in index[0] */ +int * +getVertexNeighbors(Scene *sc, int vid) +{ + int *varr; + Face *f; + int j=0; + + if (sc == NULL || (vid < 0) | (vid >= sc->nverts) || + (f = sc->vert[vid].vflist) == NULL) + return(NULL); + + varr = (int *)emalloc(sizeof(int)*CHUNKSIZ); + varr[0] = 0; /* add unique neighbors */ + for ( ; f != NULL; f = f->v[j].fnext) { + int i, cvi; + for (j = f->nv; j--; ) /* find ourself in poly */ + if (f->v[j].vid == vid) + break; + if (j < 0) /* this is an error */ + break; + if (f->nv < 3) /* also never happens */ + continue; + /* check previous neighbor */ + cvi = f->v[ (j > 0) ? j-1 : f->nv-1 ].vid; + for (i = varr[0]+1; --i; ) /* making sure not in list */ + if (varr[i] == cvi) + break; + if (!i) { /* new neighbor? */ + varr = chunk_alloc(int, varr, varr[0]+1); + varr[++varr[0]] = cvi; + } + /* check next neighbor */ + cvi = f->v[ (j < f->nv-1) ? j+1 : 0 ].vid; + for (i = varr[0]+1; --i; ) + if (varr[i] == cvi) + break; + if (!i) { + varr = chunk_alloc(int, varr, varr[0]+1); + varr[++varr[0]] = cvi; + } + } + if (!varr[0]) { + efree((char *)varr); /* something went awry */ + return(NULL); + } + /* tighten array & return */ + return((int *)erealloc((char *)varr, sizeof(int)*(varr[0]+1))); +} + +/* Callback for growBoundingBox() */ +static int +addBBox(Scene *sc, Face *f, void *p) +{ + double (*bbox)[3] = (double (*)[3])p; + int i, j; + + for (i = f->nv; i-- > 0; ) { + double *p3 = sc->vert[f->v[i].vid].p; + for (j = 3; j--; ) { + if (p3[j] < bbox[0][j]) + bbox[0][j] = p3[j]; + if (p3[j] > bbox[1][j]) + bbox[1][j] = p3[j]; + } + } + return(1); +} + +/* Expand bounding box min & max (initialize bbox to all zeroes) */ +int +growBoundingBox(Scene *sc, double bbox[2][3], int flreq, int flexc) +{ + if (sc == NULL || sc->nfaces <= 0 || bbox == NULL) + return(0); + + if (VABSEQ(bbox[0], bbox[1])) { /* first run */ + bbox[0][0] = bbox[0][1] = bbox[0][2] = FHUGE; + bbox[1][0] = bbox[1][1] = bbox[1][2] = -FHUGE; + } + return(foreachFace(sc, addBBox, flreq, flexc, bbox)); +} + /* Allocate an empty scene */ Scene * newScene(void) @@ -799,7 +882,7 @@ addScene(Scene *scdst, const Scene *scsrc) if (scsrc->nfaces <= 0) return(0); /* map vertices */ - vert_map = (int *)emalloc(sizeof(int *)*scsrc->nverts); + vert_map = (int *)emalloc(sizeof(int)*scsrc->nverts); for (i = 0; i < scsrc->nverts; i++) { const Vertex *v = scsrc->vert + i; if (v->vflist == NULL) { @@ -830,12 +913,10 @@ addScene(Scene *scdst, const Scene *scsrc) if (f->mat != cur_mat) setMaterial(scdst, scsrc->matname[cur_mat = f->mat]); if (f->nv > vllen) { - if (vlist == my_vlist) - vlist = (VNDX *)emalloc( - sizeof(VNDX)*(vllen = f->nv)); - else - vlist = (VNDX *)erealloc((char *)vlist, - sizeof(VNDX)*(vllen = f->nv)); + vlist = (VNDX *)( vlist == my_vlist ? + emalloc(sizeof(VNDX)*f->nv) : + erealloc((char *)vlist, sizeof(VNDX)*f->nv) ); + vllen = f->nv; } memset(vlist, 0xff, sizeof(VNDX)*f->nv); for (i = f->nv; i-- > 0; ) { @@ -910,7 +991,7 @@ xfmScene(Scene *sc, const char *xfm) if (!*xfm) return(0); /* parse string into words */ - xav[0] = strcpy((char *)emalloc(strlen(xfm)+1), xfm); + xav[0] = savqstr((char *)xfm); xac = 1; i = 0; for ( ; ; ) { while (!isspace(xfm[++i])) @@ -921,14 +1002,14 @@ xfmScene(Scene *sc, const char *xfm) if (!xfm[i]) break; if (xac >= MAXAC-1) { - free(xav[0]); + freeqstr(xav[0]); return(0); } xav[xac++] = xav[0] + i; } xav[xac] = NULL; i = xfScene(sc, xac, xav); - efree((char *)xav[0]); + freeqstr(xav[0]); return(i); } #undef MAXAC