--- ray/src/common/mesh.c 2016/03/22 03:56:17 2.27 +++ ray/src/common/mesh.c 2021/06/10 00:27:25 2.35 @@ -1,12 +1,10 @@ #ifndef lint -static const char RCSid[] = "$Id: mesh.c,v 2.27 2016/03/22 03:56:17 greg Exp $"; +static const char RCSid[] = "$Id: mesh.c,v 2.35 2021/06/10 00:27:25 greg Exp $"; #endif /* * Mesh support routines */ -#include - #include "rtio.h" #include "rtmath.h" #include "rterror.h" @@ -52,6 +50,7 @@ static int cvcmp(const char *vv1, const char *vv2) /* compare encoded vertices */ { const MCVERT *v1 = (const MCVERT *)vv1, *v2 = (const MCVERT *)vv2; + if (v1->fl != v2->fl) return(1); if (v1->xyz[0] != v2->xyz[0]) @@ -286,7 +285,7 @@ getmeshpseudo( /* get mesh pseudo object for materia OBJECT mo ) { - if (mo < mp->mat0 || mo >= mp->mat0 + mp->nmats) + if ((mo < mp->mat0) | (mo >= mp->mat0 + mp->nmats)) error(INTERNAL, "modifier out of range in getmeshpseudo"); if (mp->pseudo == NULL) { int i; @@ -327,12 +326,12 @@ getmeshtri( /* get triangle vertices */ int32 addmeshvert( /* find/add a mesh vertex */ - MESH *mp, + MESH *mp, MESHVERT *vp ) { - LUENT *lvp; - MCVERT cv; + LUENT *lvp; + MCVERT cv; int i; if (!(vp->fl & MT_V)) @@ -373,7 +372,7 @@ addmeshvert( /* find/add a mesh vertex */ goto nomem; if (lvp->key == NULL) { lvp->key = (char *)malloc(sizeof(MCVERT)+sizeof(int32)); - memcpy((void *)lvp->key, (void *)&cv, sizeof(MCVERT)); + memcpy(lvp->key, &cv, sizeof(MCVERT)); } if (lvp->data == NULL) { /* new vertex */ MESHPATCH *pp; @@ -384,16 +383,16 @@ addmeshvert( /* find/add a mesh vertex */ goto nomem; mp->npatches = 1; } else if (mp->patch[mp->npatches-1].nverts >= 256) { + if (mp->npatches >= 1L<<22) + error(INTERNAL, "too many mesh patches"); if (mp->npatches % MPATCHBLKSIZ == 0) { - mp->patch = (MESHPATCH *)realloc( - (void *)mp->patch, - (mp->npatches + MPATCHBLKSIZ)* - sizeof(MESHPATCH)); - memset((void *)(mp->patch + mp->npatches), '\0', + mp->patch = (MESHPATCH *)realloc(mp->patch, + (mp->npatches + MPATCHBLKSIZ)* + sizeof(MESHPATCH)); + memset((mp->patch + mp->npatches), '\0', MPATCHBLKSIZ*sizeof(MESHPATCH)); } - if (mp->npatches++ >= 1L<<22) - error(INTERNAL, "too many mesh patches"); + mp->npatches++; } pp = &mp->patch[mp->npatches-1]; if (pp->xyz == NULL) { @@ -439,8 +438,8 @@ addmeshtri( /* add a new mesh triangle */ OBJECT mo ) { - int32 vid[3], t; - int pn[3], i; + int32 vid[3], t; + int pn[3], i; MESHPATCH *pp; if (!(tv[0].fl & tv[1].fl & tv[2].fl & MT_V)) @@ -459,7 +458,7 @@ addmeshtri( /* add a new mesh triangle */ error(INTERNAL, "modifier range error in addmeshtri"); } /* assign triangle */ - if (pn[0] == pn[1] && pn[1] == pn[2]) { /* local case */ + if ((pn[0] == pn[1]) & (pn[1] == pn[2])) { /* local case */ pp = &mp->patch[pn[0]]; if (pp->tri == NULL) { pp->tri = (struct PTri *)malloc( @@ -485,8 +484,7 @@ addmeshtri( /* add a new mesh triangle */ pp->trimat[pp->ntris] = mo; return(pn[0] << 10 | pp->ntris++); } - } - if (pn[0] == pn[1]) { + } else if (pn[0] == pn[1]) { t = vid[2]; vid[2] = vid[1]; vid[1] = vid[0]; vid[0] = t; i = pn[2]; pn[2] = pn[1]; pn[1] = pn[0]; pn[0] = i; } else if (pn[0] == pn[2]) { @@ -510,20 +508,37 @@ addmeshtri( /* add a new mesh triangle */ } } /* double link */ - pp = &mp->patch[pn[2]]; + pp = &mp->patch[pn[i=0]]; + if (mp->patch[pn[1]].nj2tris < pp->nj2tris) + pp = &mp->patch[pn[i=1]]; + if (mp->patch[pn[2]].nj2tris < pp->nj2tris) + pp = &mp->patch[pn[i=2]]; + if (pp->nj2tris >= 256) + error(INTERNAL, "too many patch triangles in addmeshtri"); if (pp->j2tri == NULL) { pp->j2tri = (struct PJoin2 *)malloc( 256*sizeof(struct PJoin2)); if (pp->j2tri == NULL) goto nomem; } - if (pp->nj2tris >= 256) - error(INTERNAL, "too many patch triangles in addmeshtri"); - pp->j2tri[pp->nj2tris].v1j = vid[0]; - pp->j2tri[pp->nj2tris].v2j = vid[1]; - pp->j2tri[pp->nj2tris].v3 = vid[2] & 0xff; pp->j2tri[pp->nj2tris].mat = mo; - return(pn[2] << 10 | 0x300 | pp->nj2tris++); + switch (i) { + case 0: + pp->j2tri[pp->nj2tris].v3 = vid[0] & 0xff; + pp->j2tri[pp->nj2tris].v1j = vid[1]; + pp->j2tri[pp->nj2tris].v2j = vid[2]; + return(pn[0] << 10 | 0x300 | pp->nj2tris++); + case 1: + pp->j2tri[pp->nj2tris].v2j = vid[0]; + pp->j2tri[pp->nj2tris].v3 = vid[1] & 0xff; + pp->j2tri[pp->nj2tris].v1j = vid[2]; + return(pn[1] << 10 | 0x300 | pp->nj2tris++); + case 2: + pp->j2tri[pp->nj2tris].v1j = vid[0]; + pp->j2tri[pp->nj2tris].v2j = vid[1]; + pp->j2tri[pp->nj2tris].v3 = vid[2] & 0xff; + return(pn[2] << 10 | 0x300 | pp->nj2tris++); + } nomem: error(SYSTEM, "out of memory in addmeshtri"); return(OVOID); @@ -535,7 +550,7 @@ checkmesh(MESH *mp) /* validate mesh data */ { static char embuf[128]; int nouvbounds = 1; - int i; + int i, j; /* basic checks */ if (mp == NULL) return("NULL mesh pointer"); @@ -557,12 +572,15 @@ checkmesh(MESH *mp) /* validate mesh data */ if (isempty(mp->mcube.cutree)) error(WARNING, "empty mesh octree"); } - /* check scene data */ + /* check patch data */ if (mp->ldflags & IO_SCENE) { + MESHVERT mv; if (!(mp->ldflags & IO_BOUNDS)) return("unbounded scene in mesh"); if (mp->mat0 < 0 || mp->mat0+mp->nmats > nobjects) return("bad mesh modifier range"); + if (mp->nmats > 0) /* allocate during preload_objs()! */ + getmeshpseudo(mp, mp->mat0); for (i = mp->mat0+mp->nmats; i-- > mp->mat0; ) { int otyp = objptr(i)->otype; if (!ismodifier(otyp)) { @@ -584,15 +602,58 @@ checkmesh(MESH *mp) /* validate mesh data */ if (nouvbounds && pp->uv != NULL) return("unreferenced uv coordinates"); } - if (pp->ntris > 0 && pp->tri == NULL) - return("missing patch triangle list"); - if (pp->nj1tris > 0 && pp->j1tri == NULL) - return("missing patch joiner triangle list"); - if (pp->nj2tris > 0 && pp->j2tri == NULL) - return("missing patch double-joiner list"); + if (pp->ntris > 0) { + struct PTri *tp = pp->tri; + if (tp == NULL) + return("missing patch triangle list"); + if (mp->nmats <= 0) + j = -1; + else if (pp->trimat == NULL) + j = ((pp->solemat < 0) | (pp->solemat >= mp->nmats)) - 1; + else + for (j = pp->ntris; j--; ) + if ((pp->trimat[j] < 0) | + (pp->trimat[j] >= mp->nmats)) + break; + if (j >= 0) + return("bad local triangle material"); + for (j = pp->ntris; j--; tp++) + if ((tp->v1 >= pp->nverts) | (tp->v2 >= pp->nverts) | + (tp->v3 >= pp->nverts)) + return("bad local triangle index"); + } + if (pp->nj1tris > 0) { + struct PJoin1 *j1p = pp->j1tri; + if (j1p == NULL) + return("missing patch joiner triangle list"); + for (j = pp->nj1tris; j--; j1p++) { + if (mp->nmats > 0 && + (j1p->mat < 0) | (j1p->mat >= mp->nmats)) + return("bad j1 triangle material"); + if (!getmeshvert(&mv, mp, j1p->v1j, MT_V)) + return("bad j1 triangle joiner"); + if ((j1p->v2 >= pp->nverts) | (j1p->v3 >= pp->nverts)) + return("bad j1 triangle local index"); + } + } + if (pp->nj2tris > 0) { + struct PJoin2 *j2p = pp->j2tri; + if (j2p == NULL) + return("missing patch double-joiner list"); + for (j = pp->nj2tris; j--; j2p++) { + if (mp->nmats > 0 && + (j2p->mat < 0) | (j2p->mat >= mp->nmats)) + return("bad j2 triangle material"); + if (!getmeshvert(&mv, mp, j2p->v1j, MT_V) | + !getmeshvert(&mv, mp, j2p->v2j, MT_V)) + return("bad j2 triangle joiner"); + if (j2p->v3 >= pp->nverts) + return("bad j2 triangle local index"); + } + } } } - return(NULL); /* seems OK */ + return(NULL); /* seems to be self-consistent */ } @@ -709,23 +770,25 @@ freemesh(MESH *ms) /* free mesh data */ MESHPATCH *pp = ms->patch + ms->npatches; while (pp-- > ms->patch) { if (pp->j2tri != NULL) - free((void *)pp->j2tri); + free(pp->j2tri); if (pp->j1tri != NULL) - free((void *)pp->j1tri); + free(pp->j1tri); if (pp->tri != NULL) - free((void *)pp->tri); + free(pp->tri); if (pp->uv != NULL) - free((void *)pp->uv); + free(pp->uv); if (pp->norm != NULL) - free((void *)pp->norm); + free(pp->norm); if (pp->xyz != NULL) - free((void *)pp->xyz); + free(pp->xyz); + if (pp->trimat != NULL) + free(pp->trimat); } - free((void *)ms->patch); + free(ms->patch); } if (ms->pseudo != NULL) - free((void *)ms->pseudo); - free((void *)ms); + free(ms->pseudo); + free(ms); } @@ -735,6 +798,6 @@ freemeshinst(OBJREC *o) /* free mesh instance */ if (o->os == NULL) return; freemesh((*(MESHINST *)o->os).msh); - free((void *)o->os); + free(o->os); o->os = NULL; }