--- ray/src/common/mesh.c 2017/03/01 21:51:38 2.28 +++ 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.28 2017/03/01 21:51:38 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" @@ -287,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; @@ -374,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; @@ -385,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) { @@ -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; }