static void putfullnode( /* write out a full node */ OCTREE fn ) { OBJECT oset[MAXSET+1]; register int i; objset(oset, fn); for (i = 0; i <= oset[0]; i++) oputint((long)oset[i], sizeof(OBJECT)); }
static void add2full( /* add object to full node */ register CUBE *cu, OBJECT obj ) { OCTREE ot; OBJECT oset[MAXSET+1]; CUBE cukid; register int i, j; objset(oset, cu->cutree); cukid.cusize = cu->cusize * 0.5; if (oset[0] < objlim || cukid.cusize < (oset[0] < MAXSET ? mincusize : mincusize/256.0)) { /* add to set */ if (oset[0] >= MAXSET) { sprintf(errmsg, "set overflow in addobject (%s)", objptr(obj)->oname); error(INTERNAL, errmsg); } insertelem(oset, obj); cu->cutree = fullnode(oset); return; } /* subdivide cube */ if ((ot = octalloc()) == EMPTY) error(SYSTEM, "out of octree space"); /* assign subcubes */ for (i = 0; i < 8; i++) { cukid.cutree = EMPTY; for (j = 0; j < 3; j++) { cukid.cuorg[j] = cu->cuorg[j]; if ((1<<j) & i) cukid.cuorg[j] += cukid.cusize; } for (j = 1; j <= oset[0]; j++) addface(&cukid, oset[j]); addface(&cukid, obj); /* returned node */ octkid(ot, i) = cukid.cutree; } cu->cutree = ot; }
static int checkhit( /* check for hit in full cube */ RAY *r, CUBE *cu, OBJECT *cxs ) { OBJECT oset[MAXSET+1]; objset(oset, cu->cutree); checkset(oset, cxs); /* avoid double-checking */ (*r->hitf)(oset, r); /* test for hit in set */ if (r->robj == OVOID) return(0); /* no scores yet */ return(incube(cu, r->rop)); /* hit OK if in current cube */ }
static int nonsurfintree(OCTREE ot) /* check tree for modifiers */ { OBJECT set[MAXSET+1]; register int i; if (isempty(ot)) return(0); if (istree(ot)) { for (i = 0; i < 8; i++) if (nonsurfintree(octkid(ot, i))) return(1); return(0); } objset(set, ot); for (i = set[0]; i > 0; i-- ) if (ismodifier(objptr(set[i])->otype)) return(1); return(0); }
static OCTREE cvmeshoct( /* convert triangles in subtree */ OCTREE ot ) { int i; if (isempty(ot)) return(EMPTY); if (isfull(ot)) { OBJECT oset1[MAXSET+1]; OBJECT oset2[MAXSET+1]; objset(oset1, ot); oset2[0] = 0; for (i = oset1[0]; i > 0; i--) insertelem(oset2, cvmeshtri(oset1[i])); return(fullnode(oset2)); } for (i = 8; i--; ) octkid(ot, i) = cvmeshoct(octkid(ot, i)); return(ot); }
static void tallyoctree( /* tally octree size */ OCTREE ot, int *ecp, int *lcp, int *ocp ) { int i; if (isempty(ot)) { (*ecp)++; return; } if (isfull(ot)) { OBJECT oset[MAXSET+1]; (*lcp)++; objset(oset, ot); *ocp += oset[0]; return; } for (i = 0; i < 8; i++) tallyoctree(octkid(ot, i), ecp, lcp, ocp); }
static void add2full( /* add object to full node */ register CUBE *cu, OBJECT obj, int inc ) { OCTREE ot; OBJECT oset[MAXSET+1]; CUBE cukid; unsigned char inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8]; register int i, j; objset(oset, cu->cutree); cukid.cusize = cu->cusize * 0.5; if (inc==O_IN || oset[0] < objlim || cukid.cusize < (oset[0] < MAXSET ? mincusize : mincusize/256.0)) { /* add to set */ if (oset[0] >= MAXSET) { sprintf(errmsg, "set overflow in addobject (%s)", objptr(obj)->oname); error(INTERNAL, errmsg); } insertelem(oset, obj); cu->cutree = fullnode(oset); return; } /* subdivide cube */ if ((ot = octalloc()) == EMPTY) error(SYSTEM, "out of octree space"); /* mark volumes */ j = (oset[0]+7)>>3; while (j--) volflg[j] = inflg[j] = 0; for (j = 1; j <= oset[0]; j++) if (isvolume(objptr(oset[j])->otype)) { setbit(volflg,j-1); if ((*ofun[objptr(oset[j])->otype].funp) (objptr(oset[j]), cu) == O_IN) setbit(inflg,j-1); } /* assign subcubes */ for (i = 0; i < 8; i++) { cukid.cutree = EMPTY; for (j = 0; j < 3; j++) { cukid.cuorg[j] = cu->cuorg[j]; if ((1<<j) & i) cukid.cuorg[j] += cukid.cusize; } /* surfaces first */ for (j = 1; j <= oset[0]; j++) if (!tstbit(volflg,j-1)) addobject(&cukid, oset[j]); /* then this object */ addobject(&cukid, obj); /* then partial volumes */ for (j = 1; j <= oset[0]; j++) if (tstbit(volflg,j-1) && !tstbit(inflg,j-1)) addobject(&cukid, oset[j]); /* full volumes last */ for (j = 1; j <= oset[0]; j++) if (tstbit(inflg,j-1)) addobject(&cukid, oset[j]); /* returned node */ octkid(ot, i) = cukid.cutree; } cu->cutree = ot; }