예제 #1
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]
예제 #2
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]
예제 #3
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
예제 #4
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 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;
예제 #5
0
파일: Cube.py 프로젝트: FraMecca/CipollaMod
def flataxisface(c, orient):
    fx = c.faces[dimension(orient)]
    if dimcoord(orient):
        fx >>= 4
    return (fx & 0x0F0F0F0F) == 0x01010101*(fx & 0x0F)
예제 #6
0
파일: Cube.py 프로젝트: FraMecca/CipollaMod
def notouchingface(c, orient):
    face = c.faces[dimension(orient)];
    if dimcoord(orient):
        return (face&0x80808080)==0
    else:
        return ((0x88888888-face)&0x08080808) == 0
예제 #7
0
파일: Cube.py 프로젝트: FraMecca/CipollaMod
def touchingface(c, orient):
    face = c.faces[dimension(orient)];
    if dimcoord(orient):
        return (face & 0xF0F0F0F0) == 0x80808080
    else:
        return (face & 0x0F0F0F0F) == 0
예제 #8
0
파일: Cube.py 프로젝트: fdChasm/pycube2map
def flataxisface(c, orient):
    fx = c.faces[dimension(orient)]
    if dimcoord(orient):
        fx >>= 4
    return (fx & 0x0F0F0F0F) == 0x01010101*(fx & 0x0F)
예제 #9
0
파일: Cube.py 프로젝트: fdChasm/pycube2map
def notouchingface(c, orient):
    face = c.faces[dimension(orient)];
    if dimcoord(orient):
        return (face&0x80808080)==0
    else:
        return ((0x88888888-face)&0x08080808) == 0
예제 #10
0
파일: Cube.py 프로젝트: fdChasm/pycube2map
def touchingface(c, orient):
    face = c.faces[dimension(orient)];
    if dimcoord(orient):
        return (face & 0xF0F0F0F0) == 0x80808080
    else:
        return (face & 0x0F0F0F0F) == 0
예제 #11
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)
예제 #12
0
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
예제 #13
0
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&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 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;
예제 #14
0
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)