def neighbourcube(c, cube_map, orient, x, y, z, size, ro, rsize): worldsize = cube_map.meta_data['wordsize'] n = ivec(x, y, z) dim = dimension(orient); diff = n[dim]; if dimcoord(orient): n[dim] += size else: n[dim] -= size diff ^= n[dim]; if diff >= uint(worldsize): ro = n rsize = size return c scale = worldscale nc = cube_map.octants if neighbourdepth >= 0: scale -= neighbourdepth + 1 diff >>= scale while 1: scale += 1 dif >>= 1 if diff == 0: break nc = neighbourstack[worldscale - scale] scale -= 1 nc = nc[octastep(n.x, n.y, n.z, scale)] if (size>>scale == 0) and nc.children is not None: while 1: scale -= 1 nc = nc[0].children[octastep(n.x, n.y, n.z, scale)] if (size>>scale == 0) and nc.children is not None: break ro = n.mask(~0<<scale) rsize = 1<<scale return nc[0]
def neighbourcube(c, cube_map, orient, x, y, z, size, ro, rsize): worldsize = cube_map.meta_data['wordsize'] n = ivec(x, y, z) dim = dimension(orient) diff = n[dim] if dimcoord(orient): n[dim] += size else: n[dim] -= size diff ^= n[dim] if diff >= uint(worldsize): ro = n rsize = size return c scale = worldscale nc = cube_map.octants if neighbourdepth >= 0: scale -= neighbourdepth + 1 diff >>= scale while 1: scale += 1 dif >>= 1 if diff == 0: break nc = neighbourstack[worldscale - scale] scale -= 1 nc = nc[octastep(n.x, n.y, n.z, scale)] if (size >> scale == 0) and nc.children is not None: while 1: scale -= 1 nc = nc[0].children[octastep(n.x, n.y, n.z, scale)] if (size >> scale == 0) and nc.children is not None: break ro = n.mask(~0 << scale) rsize = 1 << scale return nc[0]
def occludesface(c, orient, o, size, vo, vsize, vmat, nmat, matmask, vf, numv): dim = dimension(orient) if c.children == 0: if nmat != empty_material_types.MAT_AIR and (c.material & matmask) == nmat: nf = [facevec() for _ in range(8)] return clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, nf) < 3 if c.isentirelysolid(): return True if vmat != empty_material_types.MAT_AIR and ( (c.material & matmask) == vmat or (isliquid(vmat) and isclipped(c.material & material_types.MATF_VOLUME))): return True if touchingface(c, orient) and faceedges(c, orient) == F_SOLID: return True cf = [facevec() for _ in range(8)] numc = clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, cf) if numc < 3: return True if c.isempty() or notouchingface(c, orient): return False of = [facevec() for _ in range(4)] numo = genfacevecs(c, orient, o, size, False, of) return numo >= 3 and insideface(cf, numc, of, numo) size >>= 1 coord = dimcoord(orient) for i in range(8): if octacoord(dim, i) == coord: if occludesface(c.children[i], orient, ivec(i, o.x, o.y, o.z, size), size, vo, vsize, vmat, nmat, matmask, vf, numv) == 0: return False return True
def occludesface(c, orient, o, size, vo, vsize, vmat, nmat, matmask, vf, numv): dim = dimension(orient) if c.children == 0: if nmat != empty_material_types.MAT_AIR and (c.material & matmask) == nmat: nf = [facevec() for _ in xrange(8)] return clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, nf) < 3; if c.isentirelysolid(): return True if vmat != empty_material_types.MAT_AIR and ((c.material & matmask) == vmat or (isliquid(vmat) and isclipped(c.material & material_types.MATF_VOLUME))): return True if touchingface(c, orient) and faceedges(c, orient) == F_SOLID: return True cf = [facevec() for _ in xrange(8)] numc = clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, cf) if numc < 3: return True if c.isempty() or notouchingface(c, orient): return False of = [facevec() for _ in xrange(4)] numo = genfacevecs(c, orient, o, size, False, of) return numo >= 3 and insideface(cf, numc, of, numo) size >>= 1 coord = dimcoord(orient) for i in xrange(8): if octacoord(dim, i) == coord: if occludesface(c.children[i], orient, ivec(i, o.x, o.y, o.z, size), size, vo, vsize, vmat, nmat, matmask, vf, numv) == 0: return False; return True;
def flataxisface(c, orient): fx = c.faces[dimension(orient)] if dimcoord(orient): fx >>= 4 return (fx & 0x0F0F0F0F) == 0x01010101*(fx & 0x0F)
def notouchingface(c, orient): face = c.faces[dimension(orient)]; if dimcoord(orient): return (face&0x80808080)==0 else: return ((0x88888888-face)&0x08080808) == 0
def touchingface(c, orient): face = c.faces[dimension(orient)]; if dimcoord(orient): return (face & 0xF0F0F0F0) == 0x80808080 else: return (face & 0x0F0F0F0F) == 0
def savec(f, cube_map, c, o, size, nolms): for i in range(8): co = ivec(i, o.x, o.y, o.z, size) if len(c[i].children) > 0: writechar(f, octa_save_types.OCTSAV_CHILDREN) savec(f, cube_map, c[i].children, co, size >> 1, nolms) else: oflags = 0 surfmask = 0 totalverts = 0 if c[i].material != empty_material_types.MAT_AIR: oflags |= 0x40 if not nolms: if c[i].merged: oflags |= 0x80 if c[i].ext: for j in range(6): surf = c[i].ext.surfaces[j] if not surf.used: continue oflags |= 0x20 surfmask |= 1 << j totalverts += surf.totalverts() if c[i].children: writechar(f, oflags | octa_save_types.OCTSAV_LODCUBE) elif c[i].isempty(): writechar(f, oflags | octa_save_types.OCTSAV_EMPTY) elif c[i].isentirelysolid(): writechar(f, oflags | octa_save_types.OCTSAV_SOLID) else: writechar(f, oflags | octa_save_types.OCTSAV_NORMAL) f.write(c[i].data) for j in range(6): writeushort(f, c[i].texture_walls[j]) if oflags & 0x40: writeushort(f, c[i].material) if oflags & 0x80: writechar(f, c[i].merged) if oflags & 0x20: writechar(f, surfmask) writechar(f, totalverts) for j in range(6): if surfmask & (1 << j): surf = c[i].ext.surfaces[j] verts = c[i].ext.verts() + surf.verts layerverts = surf.numverts & layer_types.MAXFACEVERTS numverts = surf.totalverts() vertmask = 0 vertorder = 0 uvorder = 0 dim = dimension(j) vc = C[dim] vr = R[dim] if numverts: if c[i].merged & (1 << j): vertmask |= 0x04 if layerverts == 4: v = [ verts[0].getxyz(), verts[1].getxyz(), verts[2].getxyz(), verts[3].getxyz() ] for k in range(4): v0 = v[k] v1 = v[(k + 1) & 3] v2 = v[(k + 2) & 3] v3 = v[(k + 3) & 3] if v1[vc] == v0[vc] and v1[vr] == v2[ vr] and v3[vc] == v2[ vc] and v3[vr] == v0[vr]: vertmask |= 0x01 vertorder = k break else: vis = visibletris(c[i], cube_map, j, co.x, co.y, co.z, size) if vis & 4 or faceconvexity(c[i], j) < 0: vertmask |= 0x01 if layerverts < 4 and vis & 2: vertmask |= 0x02 matchnorm = True for k in range(numverts): v = verts[k] if v.u or v.v: vertmask |= 0x40 if v.norm: vertmask |= 0x80 if v.norm != verts[0].norm: matchnorm = False if matchnorm: vertmask |= 0x08 if vertmask & 0x40 and layerverts == 4: for k in range(4): v0 = verts[k] v1 = verts[(k + 1) & 3] v2 = verts[(k + 2) & 3] v3 = verts[(k + 3) & 3] if v1.u == v0.u and v1.v == v2.v and v3.u == v2.u and v3.v == v0.v: if surf.numverts & layer_types.LAYER_DUP: b0 = verts[4 + k] b1 = verts[4 + ((k + 1) & 3)] b2 = verts[4 + ((k + 2) & 3)] b3 = verts[4 + ((k + 3) & 3)] if b1.u != b0.u or b1.v != b2.v or b3.u != b2.u or b3.v != b0.v: continue uvorder = k vertmask |= 0x02 | (( (k + 4 - vertorder) & 3) << 4) break surf.verts = vertmask f.write(surf, sizeof(surfaceinfo)) hasxyz = (vertmask & 0x04) != 0 hasuv = (vertmask & 0x40) != 0 hasnorm = (vertmask & 0x80) != 0 if layerverts == 4: if hasxyz and vertmask & 0x01: v0 = verts[vertorder].getxyz() v2 = verts[(vertorder + 2) & 3].getxyz() writeushort(f, v0[vc]) writeushort(f, v0[vr]) writeushort(f, v2[vc]) writeushort(f, v2[vr]) hasxyz = False if hasuv and vertmask & 0x02: v0 = verts[uvorder] v2 = verts[(uvorder + 2) & 3] writeushort(f, v0.u) writeushort(f, v0.v) writeushort(f, v2.u) writeushort(f, v2.v) if surf.numverts & layer_types.LAYER_DUP: b0 = verts[4 + uvorder] b2 = verts[4 + ((uvorder + 2) & 3)] writeushort(f, b0.u) writeushort(f, b0.v) writeushort(f, b2.u) writeushort(f, b2.v) hasuv = False if hasnorm and vertmask & 0x08: writeushort(f, verts[0].norm) hasnorm = False if hasxyz or hasuv or hasnorm: for k in range(layerverts): v = verts[(k + vertorder) % layerverts] if hasxyz: xyz = v.getxyz() writeushort(f, xyz[vc]) writeushort(f, xyz[vr]) if hasuv: writeushort(f, v.u) writeushort(f, v.v) if hasnorm: writeushort(f, v.norm) if surf.numverts & layer_types.LAYER_DUP: for k in range(layerverts): v = verts[layerverts + (k + vertorder) % layerverts] if hasuv: writeushort(f, v.u) writeushort(f, v.v) if c[i].children: savec(f, cube_map, c[i].children, co, size >> 1, nolms)
def visibletris(c, cube_map, orient, x, y, z, size, nmat, matmask): vis = 3 touching = 0xF e1, e2, e3, n = [ivec() for _ in range(4)] v = [None] * 4 genfaceverts(c, orient, v) e1 = v[1] e2 = v[2] e3 = v[0] n.cross((e1).sub(v[0]), (e2).sub(v[0])) convex = (e3).sub(v[3]).dot(n) if convex == 0: if ivec().cross(e3, e2).iszero(): if n.iszero(): return 0 vis = 1 touching = 0xF & ~(1 << 3) elif n.iszero(): vis = 2 touching = 0xF & ~(1 << 1) dim = dimension(orient) coord = dimcoord(orient) if v[0][dim] != coord * 8: touching &= ~(1 << 0) if v[1][dim] != coord * 8: touching &= ~(1 << 1) if v[2][dim] != coord * 8: touching &= ~(1 << 2) if v[3][dim] != coord * 8: touching &= ~(1 << 3) # mask of triangles not touching notouchmasks = [ # order 0: flat or convex # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0], # order 1: concave [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0], ] order = 1 if convex < 0 else 0 notouch = notouchmasks[order][touching] if (vis & notouch) == vis: return vis no = ivec() nsize = 0 o = neighbourcube(c, cube_map, orient, x, y, z, size, no, nsize) if o is c: return 0 if c.material & matmask == nmat: nmat = empty_material_types.MAT_AIR vo = ivec(x, y, z) vo.mask(0xFFF) no.mask(0xFFF) cf = [facevec() for _ in range(4)] of = [facevec() for _ in range(4)] opp = opposite(orient) numo = 0 numc = 0 if nsize > size or (nsize == size and o.children == 0): if o.isempty() or notouchingface(o, opp): return vis if nmat != empty_material_types.MAT_AIR and (o.material & matmask) == nmat: return vis if o.isentirelysolid() or (touchingface(o, opp) and faceedges(o, opp) == F_SOLID): return vis & notouch numc = genfacevecs(c, orient, vo, size, False, cf, v) numo = genfacevecs(o, opp, no, nsize, False, of) if numo < 3: return vis if insideface(cf, numc, of, numo): return vis & notouch else: numc = genfacevecs(c, orient, vo, size, False, cf, v) if occludesface(o, opp, no, nsize, vo, size, empty_material_types.MAT_AIR, nmat, matmask, cf, numc): return vis & notouch if vis != 3 or notouch: return vis triverts = [ # order [ # coord [[1, 2, 3], [0, 1, 3]], # verts [[0, 1, 2], [0, 2, 3]] ], [ # coord [[0, 1, 2], [3, 0, 2]], # verts [[1, 2, 3], [1, 3, 0]] ] ] while 1: for i in range(2): verts = triverts[order][coord][i] tf = [cf[verts[0]], cf[verts[1]], cf[verts[2]]] if numo > 0: if insideface(tf, 3, of, numo) == 0: continue elif occludesface(o, opp, no, nsize, vo, size, empty_material_types.MAT_AIR, nmat, matmask, tf, 3) == 0: continue return vis & ~(1 << i) vis |= 4 order += 1 if order <= 1: break return 3
def visibletris(c, cube_map, orient, x, y, z, size, nmat, matmask): vis = 3 touching = 0xF e1, e2, e3, n = [ivec() for _ in xrange(4)] v = [None]*4 genfaceverts(c, orient, v) e1 = v[1] e2 = v[2] e3 = v[0] n.cross((e1).sub(v[0]), (e2).sub(v[0])) convex = (e3).sub(v[3]).dot(n) if convex == 0: if ivec().cross(e3, e2).iszero(): if n.iszero(): return 0 vis = 1 touching = 0xF & ~(1<<3) elif n.iszero(): vis = 2 touching = 0xF&~(1<<1) dim = dimension(orient) coord = dimcoord(orient) if v[0][dim] != coord*8: touching &= ~(1<<0) if v[1][dim] != coord*8: touching &= ~(1<<1) if v[2][dim] != coord*8: touching &= ~(1<<2) if v[3][dim] != coord*8: touching &= ~(1<<3) # mask of triangles not touching notouchmasks = [ # order 0: flat or convex # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [ 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0 ], # order 1: concave [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0 ], ] order = 1 if convex < 0 else 0 notouch = notouchmasks[order][touching] if (vis¬ouch)==vis: return vis no = ivec() nsize = 0 o = neighbourcube(c, cube_map, orient, x, y, z, size, no, nsize) if o is c: return 0 if c.material & matmask == nmat: nmat = empty_material_types.MAT_AIR vo = ivec(x, y, z) vo.mask(0xFFF) no.mask(0xFFF) cf = [facevec() for _ in xrange(4)] of = [facevec() for _ in xrange(4)] opp = opposite(orient) numo = 0 numc = 0 if nsize > size or (nsize == size and o.children == 0): if o.isempty() or notouchingface(o, opp): return vis if nmat != empty_material_types.MAT_AIR and (o.material & matmask) == nmat: return vis if o.isentirelysolid() or (touchingface(o, opp) and faceedges(o, opp) == F_SOLID): return vis & notouch numc = genfacevecs(c, orient, vo, size, False, cf, v) numo = genfacevecs(o, opp, no, nsize, False, of) if numo < 3: return vis if insideface(cf, numc, of, numo): return vis & notouch else: numc = genfacevecs(c, orient, vo, size, False, cf, v) if occludesface(o, opp, no, nsize, vo, size, empty_material_types.MAT_AIR, nmat, matmask, cf, numc): return vis & notouch if vis != 3 or notouch: return vis triverts = [ # order [ # coord [ [ 1, 2, 3 ], [ 0, 1, 3 ] ], # verts [ [ 0, 1, 2 ], [ 0, 2, 3 ] ] ], [ # coord [ [ 0, 1, 2 ], [ 3, 0, 2 ] ], # verts [ [ 1, 2, 3 ], [ 1, 3, 0 ] ] ] ] while 1: for i in xrange(2): verts = triverts[order][coord][i] tf = [cf[verts[0]], cf[verts[1]], cf[verts[2]]] if numo > 0: if insideface(tf, 3, of, numo) == 0: continue elif occludesface(o, opp, no, nsize, vo, size, empty_material_types.MAT_AIR, nmat, matmask, tf, 3) == 0: continue return vis & ~(1<<i) vis |= 4; order += 1 if order <= 1: break return 3;
def savec(f, cube_map, c, o, size, nolms): for i in xrange(8): co = ivec(i, o.x, o.y, o.z, size) if len(c[i].children) > 0: writechar(f, octa_save_types.OCTSAV_CHILDREN) savec(f, cube_map, c[i].children, co, size>>1, nolms) else: oflags = 0 surfmask = 0 totalverts = 0 if c[i].material != empty_material_types.MAT_AIR: oflags |= 0x40 if not nolms: if c[i].merged: oflags |= 0x80 if c[i].ext: for j in xrange(6): surf = c[i].ext.surfaces[j] if not surf.used: continue oflags |= 0x20 surfmask |= 1<<j totalverts += surf.totalverts() if c[i].children: writechar(f, oflags | octa_save_types.OCTSAV_LODCUBE) elif c[i].isempty(): writechar(f, oflags | octa_save_types.OCTSAV_EMPTY) elif c[i].isentirelysolid(): writechar(f, oflags | octa_save_types.OCTSAV_SOLID) else: writechar(f, oflags | octa_save_types.OCTSAV_NORMAL) f.write(c[i].data) for j in xrange(6): writeushort(f, c[i].texture_walls[j]) if oflags&0x40: writeushort(f, c[i].material); if oflags&0x80: writechar(f, c[i].merged) if oflags&0x20: writechar(f, surfmask) writechar(f, totalverts) for j in xrange(6): if surfmask & (1<<j): surf = c[i].ext.surfaces[j] verts = c[i].ext.verts() + surf.verts; layerverts = surf.numverts & layer_types.MAXFACEVERTS numverts = surf.totalverts() vertmask = 0 vertorder = 0 uvorder = 0 dim = dimension(j) vc = C[dim] vr = R[dim] if numverts: if c[i].merged & (1<<j): vertmask |= 0x04; if layerverts == 4: v = [verts[0].getxyz(), verts[1].getxyz(), verts[2].getxyz(), verts[3].getxyz()] for k in xrange(4): v0 = v[k] v1 = v[(k+1) & 3] v2 = v[(k+2) & 3] v3 = v[(k+3) & 3] if v1[vc] == v0[vc] and v1[vr] == v2[vr] and v3[vc] == v2[vc] and v3[vr] == v0[vr]: vertmask |= 0x01 vertorder = k break else: vis = visibletris(c[i], cube_map, j, co.x, co.y, co.z, size) if vis & 4 or faceconvexity(c[i], j) < 0: vertmask |= 0x01 if layerverts < 4 and vis & 2: vertmask |= 0x02 matchnorm = True for k in xrange(numverts): v = verts[k] if v.u or v.v: vertmask |= 0x40 if v.norm: vertmask |= 0x80 if v.norm != verts[0].norm: matchnorm = False if matchnorm: vertmask |= 0x08 if vertmask & 0x40 and layerverts == 4: for k in xrange(4): v0 = verts[k] v1 = verts[(k+1)&3] v2 = verts[(k+2)&3] v3 = verts[(k+3)&3] if v1.u == v0.u and v1.v == v2.v and v3.u == v2.u and v3.v == v0.v: if surf.numverts & layer_types.LAYER_DUP: b0 = verts[4+k] b1 = verts[4+((k+1)&3)] b2 = verts[4+((k+2)&3)] b3 = verts[4+((k+3)&3)] if b1.u != b0.u or b1.v != b2.v or b3.u != b2.u or b3.v != b0.v: continue uvorder = k vertmask |= 0x02 | (((k+4-vertorder)&3)<<4) break surf.verts = vertmask f.write(surf, sizeof(surfaceinfo)) hasxyz = (vertmask & 0x04)!=0 hasuv = (vertmask & 0x40)!=0 hasnorm = (vertmask & 0x80)!=0 if layerverts == 4: if hasxyz and vertmask & 0x01: v0 = verts[vertorder].getxyz() v2 = verts[(vertorder+2)&3].getxyz() writeushort(f, v0[vc]) writeushort(f, v0[vr]) writeushort(f, v2[vc]) writeushort(f, v2[vr]) hasxyz = False if hasuv and vertmask & 0x02: v0 = verts[uvorder] v2 = verts[(uvorder+2)&3] writeushort(f, v0.u) writeushort(f, v0.v) writeushort(f, v2.u) writeushort(f, v2.v) if surf.numverts & layer_types.LAYER_DUP: b0 = verts[4+uvorder] b2 = verts[4+((uvorder+2)&3)] writeushort(f, b0.u) writeushort(f, b0.v) writeushort(f, b2.u) writeushort(f, b2.v) hasuv = False; if hasnorm and vertmask&0x08: writeushort(f, verts[0].norm) hasnorm = False if hasxyz or hasuv or hasnorm: for k in xrange(layerverts): v = verts[(k+vertorder)%layerverts] if hasxyz: xyz = v.getxyz() writeushort(f, xyz[vc]) writeushort(f, xyz[vr]) if hasuv: writeushort(f, v.u) writeushort(f, v.v) if hasnorm: writeushort(f, v.norm) if surf.numverts & layer_types.LAYER_DUP: for k in xrange(layerverts): v = verts[layerverts + (k+vertorder)%layerverts] if hasuv: writeushort(f, v.u) writeushort(f, v.v) if c[i].children: savec(f, cube_map, c[i].children, co, size>>1, nolms)