Beispiel #1
0
    def __init__(self, bgl, enda, scale, libname, srcfile, texdir, output):

        self.old = False  # Old style scenery found and skipped
        self.rrt = False  # Old style runways/roads found and skipped
        self.anim = False  # Animations found and skipped

        assert (scale == 1)  # new-style objects are scaled when placed

        comment = "object %s in file %s" % (libname,
                                            asciify(basename(srcfile), False))

        tex = []
        mattex = []
        vt = []
        idx = []
        matrix = []
        amap = []
        scen = []
        data = {}

        if bgl.read(4) != 'RIFF': raise IOError
        (mdlsize, ) = unpack('<I', bgl.read(4))
        endmdl = bgl.tell() + mdlsize
        if bgl.read(4) != 'MDLX': raise IOError
        while bgl.tell() < endmdl:
            c = bgl.read(4)
            (size, ) = unpack('<I', bgl.read(4))
            if c == 'MDLD':
                end = size + bgl.tell()
                while bgl.tell() < end:
                    c = bgl.read(4)
                    (size, ) = unpack('<I', bgl.read(4))
                    if c == 'TEXT':
                        tex.extend([
                            bgl.read(64).strip('\0').strip()
                            for i in range(0, size, 64)
                        ])
                    elif c == 'MATE':
                        # http://www.fsdeveloper.com/wiki/index.php?title=MDL_file_format_(FSX)#MATE
                        for i in range(0, size, 120):
                            (flags1, flags2, diffuse, detail, normal, specular,
                             emissive, reflection, fresnel, dr, dg, db, da, sr,
                             sg, sb, sa, sp, ds, normalscale, recflectionscale,
                             po, power, bloomfloor, ambientscale, srcblend,
                             dstblend, alphafunc, alphathreshhold,
                             zwritealpha) = unpack('<9I16f3I2f', bgl.read(120))
                            # Get texture names
                            diffuse = (flags1 & Material.FSX_MAT_HAS_DIFFUSE
                                       ) and tex[diffuse] or None
                            emissive = (flags1 & Material.FSX_MAT_HAS_EMISSIVE
                                        ) and tex[emissive] or None
                            if output.xpver <= 10:
                                normal = specular = reflection = None  # Not supported in<=10, so no point doing lookup
                            else:
                                specular = (flags1
                                            & Material.FSX_MAT_HAS_SPECULAR
                                            ) and tex[specular] or None
                                normal = (flags1 & Material.FSX_MAT_HAS_NORMAL
                                          ) and tex[normal] or None
                                reflection = (flags1
                                              & Material.FSX_MAT_HAS_REFLECTION
                                              ) and tex[reflection] or None
                            # Get texture filenames
                            if diffuse:
                                diffuse = findtex(diffuse, texdir,
                                                  output.addtexdir)
                            if emissive:
                                emissive = findtex(emissive, texdir,
                                                   output.addtexdir)
                            if specular:
                                specular = findtex(specular, texdir,
                                                   output.addtexdir)
                            if normal:
                                normal = findtex(normal, texdir,
                                                 output.addtexdir)
                            if reflection:
                                reflection = findtex(reflection, texdir,
                                                     output.addtexdir)

                            t = (diffuse or emissive) and Texture(
                                output.xpver, diffuse, emissive, specular,
                                normal, reflection) or None
                            m = Material(
                                output.xpver,
                                (dr, dg, db),
                                (flags1 & Material.FSX_MAT_SPECULAR)
                                and not specular and
                                ((sr != sg or sr != sb or sr < 0.9) and
                                 (sr, sg, sb) !=
                                 (0, 0, 0)) and [sr, sg, sb] or None,
                                False,  # Poly
                                flags2 & Material.FSX_MAT_DOUBLE_SIDED != 0,
                                flags1 & Material.FSX_MAT_ZTEST_ALPHA
                                and alphafunc in [
                                    Material.FSX_MAT_ALPHA_TEST_GREATER,
                                    Material.FSX_MAT_ALPHA_TEST_GREATER_EQUAL
                                ] and alphathreshhold / 255 or None,
                                not diffuse
                                and ((flags1 & Material.FSX_MAT_SPECULAR) and
                                     (sr, sg, sb) != (0, 0, 0)) and True,
                                flags1 & Material.FSX_MAT_NO_SHADOW != 0)
                            mattex.append((m, t))
                        if __debug__:
                            if output.debug:
                                output.debug.write("Materials %d\n" %
                                                   len(mattex))
                                for i in range(len(mattex)):
                                    output.debug.write(
                                        "%3d:\t%s\t%s\n" %
                                        (i, mattex[i][0], mattex[i][1]))
                    elif c == 'INDE':
                        idx = unpack('<%dH' % (size / 2), bgl.read(size))
                    elif c == 'VERB':
                        endv = size + bgl.tell()
                        while bgl.tell() < endv:
                            c = bgl.read(4)
                            (size, ) = unpack('<I', bgl.read(4))
                            if c == 'VERT':
                                vt.append([
                                    unpack('<8f', bgl.read(32))
                                    for i in range(0, size, 32)
                                ])
                            else:
                                bgl.seek(size, 1)
                    elif c == 'TRAN':
                        for i in range(0, size, 64):
                            matrix.append(
                                Matrix([
                                    unpack('<4f', bgl.read(16))
                                    for j in range(4)
                                ]))
                        if __debug__:
                            if output.debug:
                                output.debug.write("Matrices %d\n" %
                                                   len(matrix))
                                for i in range(len(matrix)):
                                    output.debug.write("%s = %d\n" %
                                                       (matrix[i], i))
                    elif c == 'AMAP':
                        for i in range(0, size, 8):
                            (a, b) = unpack('<2I', bgl.read(8))
                            amap.append(b)
                        if __debug__:
                            if output.debug:
                                output.debug.write("Animation map %d\n" %
                                                   len(amap))
                                for i in range(len(amap)):
                                    output.debug.write("%2d: %2d\n" %
                                                       (i, amap[i]))
                    elif c == 'SCEN':
                        # Assumed to be after TRAN and AMAP sections
                        count = size / 8
                        for i in range(count):
                            (child, peer, offset,
                             unk) = unpack('<4h', bgl.read(8))
                            scen.append((child, peer, offset, -1))
                        # Invert Child/Peer pointers to get parents
                        for i in range(count):
                            (child, peer, thisoff, parent) = scen[i]
                            if child != -1:  # child's parent is me
                                (xchild, xpeer, xoff, xparent) = scen[child]
                                scen[child] = (xchild, xpeer, xoff, i)
                            if peer != -1:  # peer's parent is my parent
                                (xchild, xpeer, xoff, xparent) = scen[peer]
                                scen[peer] = (xchild, xpeer, xoff, parent)
                        # Replace AMAP offsets with matrix
                        if __debug__:
                            if output.debug:
                                output.debug.write("Scene Graph %d\n" %
                                                   len(scen))
                        for i in range(count):
                            (child, peer, offset, parent) = scen[i]
                            scen[i] = (child, peer, matrix[amap[offset / 8]],
                                       parent)
                            if __debug__:
                                if output.debug:
                                    output.debug.write(
                                        "%2d: %2d %2d %2d %2d\n" %
                                        (i, child, peer, parent, offset / 8))
                    elif c == 'LODT':
                        endt = size + bgl.tell()
                        partno = 0
                        maxlod = 0
                        while bgl.tell() < endt:
                            c = bgl.read(4)
                            (size, ) = unpack('<I', bgl.read(4))
                            if c == 'LODE':
                                ende = size + bgl.tell()
                                (lod, ) = unpack('<I', bgl.read(4))
                                while bgl.tell() < ende:
                                    c = bgl.read(4)
                                    (size, ) = unpack('<I', bgl.read(4))
                                    if c == 'PART':
                                        (typ, scene, material, verb, voff,
                                         vcount, ioff, icount,
                                         unk) = unpack('<9I', bgl.read(36))
                                        assert (typ == 1)
                                        maxlod = max(lod, maxlod)
                                        (child, peer, finalmatrix,
                                         parent) = scen[scene]
                                        if __debug__:
                                            if output.debug:
                                                output.debug.write(
                                                    "LOD %4d: scene %d verb %d material %d tris %d voff %d vcount %d ioff %d icount %d\n"
                                                    % (lod, scene, verb,
                                                       material, icount / 3,
                                                       voff, vcount, ioff,
                                                       icount))

                                        while parent != -1:
                                            (child, peer, thismatrix,
                                             parent) = scen[parent]
                                            finalmatrix = finalmatrix * thismatrix
                                        if not lod in data: data[lod] = []
                                        data[lod].append(
                                            (mattex[material][0],
                                             mattex[material][1],
                                             vt[verb][voff:voff + vcount],
                                             idx[ioff:ioff + icount],
                                             finalmatrix))
                                        partno += 1
                                    else:
                                        bgl.seek(size, 1)
                            else:
                                bgl.seek(size, 1)
                    else:
                        bgl.seek(size, 1)
            else:
                bgl.seek(size, 1)

        # Only interested in highest LOD
        objs = {}  # objs by texture
        for (m, t, vt, idx, matrix) in data[maxlod]:
            if __debug__:
                if output.debug: output.debug.write("%s\n%s\n" % (t, matrix))
            objvt = []
            nrmmatrix = matrix.adjoint()
            if t:
                assert not t.s and not t.n and not t.r  # Bunching scheme will need re-work
                for (x, y, z, nx, ny, nz, tu, tv) in vt:
                    (x, y, z) = matrix.transform(x, y, z)
                    (nx, ny, nz) = nrmmatrix.rotateAndNormalize(nx, ny, nz)
                    objvt.append((x, y, -z, nx, ny, -nz, tu, tv))
            else:
                # replace material with palette texture
                (pu, pv) = rgb2uv(m.d)
                for (x, y, z, nx, ny, nz, tu, tv) in vt:
                    (x, y, z) = matrix.transform(x, y, z)
                    (nx, ny, nz) = nrmmatrix.rotateAndNormalize(nx, ny, nz)
                    objvt.append((x, y, -z, nx, ny, -nz, pu, pv))
            if t in objs:
                obj = objs[t]
                if t and t.e:
                    obj.tex.e = t.e  # Because we don't compare on emissive
            else:
                objs[t] = obj = Object(libname, comment, t, None)
            obj.addgeometry(m, objvt, idx)

        # Add objs to library with one name
        if objs: output.objdat[libname] = objs.values()
Beispiel #2
0
def makegenquad(name, output, x, z, incx, incz, heights, texs, roof):
    # roof types: 0=flat, 1=pointy, 2=gabled, 3=slanty
    cumheight = 0
    vt = []
    idx = []
    rgbs = []
    for i in range(len(texs)):
        rgbs.append(genrgb(i, texs[i]))
    sign = [(1, 1), (1, -1), (-1, -1), (-1, 1), (1, 1)]
    n = [(cos(incx), sin(incx), 0), (0, sin(incz), -cos(incz)),
         (-cos(incx), sin(incx), 0), (0, sin(incz), cos(incz))]
    for story in range(3):
        if not heights[story]:
            continue
        (u, v) = rgb2uv(rgbs[story])
        x0 = x / 2 - sin(incx) * cumheight
        z0 = z / 2 - sin(incz) * cumheight
        x1 = x / 2 - sin(incx) * (cumheight + heights[story])
        z1 = z / 2 - sin(incz) * (cumheight + heights[story])
        for side in range(4):
            (nx, ny, nz) = n[side]
            base = len(vt)
            for corner in [side, side + 1]:
                (sx, sz) = sign[corner]
                vt.extend([(sx * x0, cumheight, sz * z0, nx, ny, nz, u, v),
                           (sx * x1, cumheight + heights[story], sz * z1, nx,
                            ny, nz, u, v)])
            idx.extend(
                [base, base + 1, base + 2, base + 3, base + 2, base + 1])
        cumheight += heights[story]

    # roof
    x0 = x / 2 - sin(incx) * cumheight
    z0 = z / 2 - sin(incz) * cumheight
    (u, v) = rgb2uv(rgbs[3])
    base = len(vt)
    if roof == 0 or heights[3] == 0:  # simplify if actually flat
        vt.extend([(x0, cumheight, z0, 0, 1, 0, u, v),
                   (x0, cumheight, -z0, 0, 1, 0, u, v),
                   (-x0, cumheight, -z0, 0, 1, 0, u, v),
                   (-x0, cumheight, z0, 0, 1, 0, u, v)])
        idx.extend([base + 2, base + 1, base, base, base + 3, base + 2])

    elif roof == 1:
        # pointy
        topheight = cumheight + heights[3]
        incx = atan(x / (2 * heights[3]))
        incz = atan(z / (2 * heights[3]))
        vt.extend([(x0, cumheight, z0, cos(incx), sin(incx), 0, u, v),
                   (0, topheight, 0, cos(incx), sin(incx), 0, u, v),
                   (x0, cumheight, -z0, cos(incx), sin(incx), 0, u, v),
                   (-x0, cumheight, z0, -cos(incx), sin(incx), 0, u, v),
                   (0, topheight, 0, -cos(incx), sin(incx), 0, u, v),
                   (-x0, cumheight, -z0, -cos(incx), sin(incx), 0, u, v),
                   (x0, cumheight, z0, 0, sin(incz), cos(incz), u, v),
                   (0, topheight, 0, 0, sin(incz), cos(incz), u, v),
                   (-x0, cumheight, z0, 0, sin(incz), cos(incz), u, v),
                   (x0, cumheight, -z0, 0, sin(incz), -cos(incz), u, v),
                   (0, topheight, 0, 0, sin(incz), -cos(incz), u, v),
                   (-x0, cumheight, -z0, 0, sin(incz), -cos(incz), u, v)])
        idx.extend([
            base, base + 1, base + 2, base + 5, base + 4, base + 3, base + 8,
            base + 7, base + 6, base + 9, base + 10, base + 11
        ])

    elif roof == 2:
        # gabled
        topheight = cumheight + heights[3]
        incz = atan(z / (2 * heights[3]))
        ny = sin(incz)
        nz = cos(incz)
        #roof
        vt.extend([(x0, cumheight, z0, 0, ny, nz, u, v),
                   (x0, topheight, 0, 0, ny, nz, u, v),
                   (-x0, topheight, 0, 0, ny, nz, u, v),
                   (-x0, cumheight, z0, 0, ny, nz, u, v),
                   (x0, cumheight, -z0, 0, ny, -nz, u, v),
                   (x0, topheight, 0, 0, ny, -nz, u, v),
                   (-x0, topheight, 0, 0, ny, -nz, u, v),
                   (-x0, cumheight, -z0, 0, ny, -nz, u, v)])
        idx.extend([
            base + 2, base + 1, base, base, base + 3, base + 2, base + 4,
            base + 5, base + 6, base + 6, base + 7, base + 4
        ])
        #gables
        (u, v) = rgb2uv(rgbs[4])
        base = len(vt)
        vt.extend([(x0, cumheight, z0, 1, 0, 0, u, v),
                   (x0, topheight, 0, 1, 0, 0, u, v),
                   (x0, cumheight, -z0, 1, 0, 0, u, v),
                   (-x0, cumheight, z0, -1, 0, 0, u, v),
                   (-x0, topheight, 0, -1, 0, 0, u, v),
                   (-x0, cumheight, -z0, -1, 0, 0, u, v)])
        idx.extend([base, base + 1, base + 2, base + 5, base + 4, base + 3])

    elif roof == 3:
        # slanty
        topheight = cumheight + heights[3]
        incz = atan(z / heights[3])
        ny = sin(incz)
        nz = cos(incz)
        #roof
        vt.extend([(x0, cumheight, z0, 0, ny, nz, u, v),
                   (x0, topheight, -z0, 0, ny, nz, u, v),
                   (-x0, topheight, -z0, 0, ny, nz, u, v),
                   (-x0, cumheight, z0, 0, ny, nz, u, v)])
        idx.extend([base + 2, base + 1, base, base, base + 3, base + 2])
        #gables
        (u, v) = rgb2uv(rgbs[4])
        base = len(vt)
        vt.extend([(x0, topheight, -z0, 1, 0, 0, u, v),
                   (x0, cumheight, -z0, 1, 0, 0, u, v),
                   (x0, cumheight, z0, 1, 0, 0, u, v),
                   (-x0, topheight, -z0, -1, 0, 0, u, v),
                   (-x0, cumheight, -z0, -1, 0, 0, u, v),
                   (-x0, cumheight, z0, -1, 0, 0, u, v)])
        idx.extend([base, base + 1, base + 2, base + 5, base + 4, base + 3])
        #face
        (u, v) = rgb2uv(rgbs[5])
        base = len(vt)
        vt.extend([(x0, topheight, -z0, 0, 0, -1, u, v),
                   (x0, cumheight, -z0, 0, 0, -1, u, v),
                   (-x0, cumheight, -z0, 0, 0, -1, u, v),
                   (-x0, topheight, -z0, 0, 0, -1, u, v)])
        idx.extend([base + 2, base + 1, base, base, base + 3, base + 2])

    obj = Object(name, "Generic building", None, None)
    obj.addgeometry(Material(output.xpver, None), vt, idx)
    return obj
Beispiel #3
0
def makegenmulti(name, output, sides, x, z, heights, texs):
    # building fits inside an oval inscribed in a x*z box
    slice = 2 * pi / sides
    halfslice = pi / sides
    sides2 = sides * 2
    cumheight = 0
    vt = []
    idx = []
    rgbs = []
    for i in range(len(texs)):
        rgbs.append(genrgb(i, texs[i]))
    for story in range(3):
        (u, v) = rgb2uv(rgbs[story])
        base = len(vt)
        for corner in range(sides):
            angle = corner * slice - halfslice
            nx = sin(angle)
            nz = cos(angle)
            x0 = x * nx / 2
            z0 = z * nz / 2
            vt.append((x0, cumheight, z0, nx, 0, nz, u, v))
            vt.append((x0, cumheight + heights[story], z0, nx, 0, nz, u, v))
            idx.extend([
                base + corner * 2, base + (corner * 2 + 1) % sides2,
                base + (corner * 2 + 2) % sides2,
                base + (corner * 2 + 3) % sides2,
                base + (corner * 2 + 2) % sides2,
                base + (corner * 2 + 1) % sides2
            ])
        cumheight += heights[story]

    # roof
    (u, v) = rgb2uv(rgbs[3])
    base = len(vt)

    if heights[3] == 0:  # simplify if actually flat
        for corner in range(sides):
            angle = corner * slice - halfslice
            x0 = sin(angle) * x / 2
            z0 = cos(angle) * z / 2
            vt.append((x0, cumheight, z0, 0, 1, 0, u, v))
            vt.append((0, cumheight, 0, 0, 1, 0, u, v))
            idx.extend([
                base + corner * 2, base + (corner * 2 + 1) % sides2,
                base + (corner * 2 + 2) % sides2
            ])
    else:
        incx = atan(x / (2 * heights[3]))
        incz = atan(z / (2 * heights[3]))
        for corner in range(sides):
            # FIXME: normal calculation is incorrect
            angle = corner * slice - halfslice
            nx = cos(incx) * sin(angle)
            ny = sin(incx) * sin(angle) + sin(incz) * cos(angle)
            nz = cos(incz) * cos(angle)
            x0 = sin(angle) * x / 2
            z0 = cos(angle) * z / 2
            vt.append((x0, cumheight, z0, nx, ny, nz, u, v))
            angle = corner * slice
            nx = cos(incx) * sin(angle)
            ny = sin(incx) * sin(angle) + sin(incz) * cos(angle)
            nz = cos(incz) * cos(angle)
            vt.append((0, cumheight + heights[3], 0, nx, ny, nz, u, v))
            idx.extend([
                base + corner * 2, base + (corner * 2 + 1) % sides2,
                base + (corner * 2 + 2) % sides2
            ])

    obj = Object(name, "Generic building", None, None)
    obj.addgeometry(Material(output.xpver, None), vt, idx)
    return obj
Beispiel #4
0
def makegenquad(name, output, x, z, incx, incz, heights, texs, roof):
    # roof types: 0=flat, 1=pointy, 2=gabled, 3=slanty
    cumheight=0
    vt=[]
    idx=[]
    rgbs=[]
    for i in range(len(texs)):
        rgbs.append(genrgb(i, texs[i]))
    sign=[(1,1), (1,-1), (-1,-1), (-1,1), (1,1)]
    n=[( cos(incx),sin(incx),0), (0,sin(incz),-cos(incz)),
       (-cos(incx),sin(incx),0), (0,sin(incz), cos(incz))]
    for story in range(3):
        if not heights[story]:
            continue
        (u,v)=rgb2uv(rgbs[story])
        x0=x/2-sin(incx)*cumheight
        z0=z/2-sin(incz)*cumheight
        x1=x/2-sin(incx)*(cumheight+heights[story])
        z1=z/2-sin(incz)*(cumheight+heights[story])
        for side in range(4):
            (nx,ny,nz)=n[side]
            base=len(vt)
            for corner in [side, side+1]:
                (sx,sz)=sign[corner]
                vt.extend([(sx*x0, cumheight, sz*z0, nx,ny,nz, u,v),
                           (sx*x1, cumheight+heights[story], sz*z1,
                            nx,ny,nz, u,v)])
            idx.extend([base,base+1,base+2, base+3,base+2,base+1])
        cumheight += heights[story]

    # roof
    x0=x/2-sin(incx)*cumheight
    z0=z/2-sin(incz)*cumheight
    (u,v)=rgb2uv(rgbs[3])
    base=len(vt)
    if roof==0 or heights[3]==0:        # simplify if actually flat
        vt.extend([( x0, cumheight,  z0, 0,1,0, u,v),
                   ( x0, cumheight, -z0, 0,1,0, u,v),
                   (-x0, cumheight, -z0, 0,1,0, u,v),
                   (-x0, cumheight,  z0, 0,1,0, u,v)])
        idx.extend([base+2,base+1,base, base,base+3,base+2])

    elif roof==1:
        # pointy
        topheight=cumheight+heights[3]
        incx=atan(x/(2*heights[3]))
        incz=atan(z/(2*heights[3]))
        vt.extend([( x0, cumheight,  z0,  cos(incx),sin(incx),0, u,v),
                   (  0, topheight,   0,  cos(incx),sin(incx),0, u,v),
                   ( x0, cumheight, -z0,  cos(incx),sin(incx),0, u,v),
                   (-x0, cumheight,  z0, -cos(incx),sin(incx),0, u,v),
                   (  0, topheight,   0, -cos(incx),sin(incx),0, u,v),
                   (-x0, cumheight, -z0, -cos(incx),sin(incx),0, u,v),
                   ( x0, cumheight,  z0, 0,sin(incz), cos(incz), u,v),
                   (  0, topheight,   0, 0,sin(incz), cos(incz), u,v),
                   (-x0, cumheight,  z0, 0,sin(incz), cos(incz), u,v),
                   ( x0, cumheight, -z0, 0,sin(incz),-cos(incz), u,v),
                   (  0, topheight,   0, 0,sin(incz),-cos(incz), u,v),
                   (-x0, cumheight, -z0, 0,sin(incz),-cos(incz), u,v)])
        idx.extend([  base,base+1,base+2, base+5,base+4,base+3,
                    base+8,base+7,base+6, base+9,base+10,base+11])

    elif roof==2:
        # gabled
        topheight=cumheight+heights[3]
        incz=atan(z/(2*heights[3]))
        ny=sin(incz)
        nz=cos(incz)
        #roof
        vt.extend([( x0, cumheight,  z0, 0,ny,nz, u,v),
                   ( x0, topheight,   0, 0,ny,nz, u,v),
                   (-x0, topheight,   0, 0,ny,nz, u,v),
                   (-x0, cumheight,  z0, 0,ny,nz, u,v),
                   ( x0, cumheight, -z0, 0,ny,-nz, u,v),
                   ( x0, topheight,   0, 0,ny,-nz, u,v),
                   (-x0, topheight,   0, 0,ny,-nz, u,v),
                   (-x0, cumheight, -z0, 0,ny,-nz, u,v)])
        idx.extend([base+2,base+1,base,     base,base+3,base+2,
                    base+4,base+5,base+6, base+6,base+7,base+4])
        #gables
        (u,v)=rgb2uv(rgbs[4])
        base=len(vt)
        vt.extend([( x0, cumheight,  z0, 1,0,0, u,v),
                   ( x0, topheight,   0, 1,0,0, u,v),
                   ( x0, cumheight, -z0, 1,0,0, u,v),
                   (-x0, cumheight,  z0, -1,0,0, u,v),
                   (-x0, topheight,   0, -1,0,0, u,v),
                   (-x0, cumheight, -z0, -1,0,0, u,v)])
        idx.extend([base,base+1,base+2, base+5,base+4,base+3])

    elif roof==3:
        # slanty
        topheight=cumheight+heights[3]
        incz=atan(z/heights[3])
        ny=sin(incz)
        nz=cos(incz)
        #roof
        vt.extend([( x0, cumheight,  z0, 0,ny,nz, u,v),
                   ( x0, topheight, -z0, 0,ny,nz, u,v),
                   (-x0, topheight, -z0, 0,ny,nz, u,v),
                   (-x0, cumheight,  z0, 0,ny,nz, u,v)])
        idx.extend([base+2,base+1,base, base,base+3,base+2])
        #gables
        (u,v)=rgb2uv(rgbs[4])
        base=len(vt)
        vt.extend([( x0, topheight, -z0,  1,0,0, u,v),
                   ( x0, cumheight, -z0,  1,0,0, u,v),
                   ( x0, cumheight,  z0,  1,0,0, u,v),
                   (-x0, topheight, -z0, -1,0,0, u,v),
                   (-x0, cumheight, -z0, -1,0,0, u,v),
                   (-x0, cumheight,  z0, -1,0,0, u,v)])
        idx.extend([base,base+1,base+2, base+5,base+4,base+3])
        #face
        (u,v)=rgb2uv(rgbs[5])
        base=len(vt)
        vt.extend([( x0, topheight, -z0, 0,0,-1, u,v),
                   ( x0, cumheight, -z0, 0,0,-1, u,v),
                   (-x0, cumheight, -z0, 0,0,-1, u,v),
                   (-x0, topheight, -z0, 0,0,-1, u,v)])
        idx.extend([base+2,base+1,base, base,base+3,base+2])
        
    obj=Object(name, "Generic building", None, None)
    obj.addgeometry(Material(output.xpver, None), vt, idx)
    return obj
Beispiel #5
0
def makegenmulti(name, output, sides, x, z, heights, texs):
    # building fits inside an oval inscribed in a x*z box
    slice=2*pi/sides
    halfslice=pi/sides
    sides2=sides*2
    cumheight=0
    vt=[]
    idx=[]
    rgbs=[]
    for i in range(len(texs)):
        rgbs.append(genrgb(i, texs[i]))
    for story in range(3):
        (u,v)=rgb2uv(rgbs[story])
        base=len(vt)
        for corner in range(sides):
            angle=corner*slice-halfslice
            nx=sin(angle)
            nz=cos(angle)
            x0=x*nx/2
            z0=z*nz/2
            vt.append((x0, cumheight, z0, nx,0,nz, u,v))
            vt.append((x0, cumheight+heights[story], z0, nx,0,nz, u,v))
            idx.extend([base + corner*2,
                        base +(corner*2+1)%sides2,
                        base +(corner*2+2)%sides2,
                        base +(corner*2+3)%sides2,
                        base +(corner*2+2)%sides2,
                        base +(corner*2+1)%sides2])
        cumheight += heights[story]

    # roof
    (u,v)=rgb2uv(rgbs[3])
    base=len(vt)

    if heights[3]==0:        # simplify if actually flat
        for corner in range(sides):
            angle=corner*slice-halfslice
            x0=sin(angle)*x/2
            z0=cos(angle)*z/2
            vt.append((x0, cumheight, z0, 0,1,0, u,v))
            vt.append((0,  cumheight, 0, 0,1,0, u,v))
            idx.extend([base +corner*2,
                        base+(corner*2+1)%sides2,
                        base+(corner*2+2)%sides2])
    else:
        incx=atan(x/(2*heights[3]))
        incz=atan(z/(2*heights[3]))
        for corner in range(sides):
            # FIXME: normal calculation is incorrect
            angle=corner*slice-halfslice
            nx=cos(incx)*sin(angle)
            ny=sin(incx)*sin(angle)+sin(incz)*cos(angle)
            nz=cos(incz)*cos(angle)
            x0=sin(angle)*x/2
            z0=cos(angle)*z/2
            vt.append((x0, cumheight, z0, nx,ny,nz, u,v))
            angle=corner*slice
            nx=cos(incx)*sin(angle)
            ny=sin(incx)*sin(angle)+sin(incz)*cos(angle)
            nz=cos(incz)*cos(angle)
            vt.append((0, cumheight+heights[3], 0, nx,ny,nz, u,v))
            idx.extend([base +corner*2,
                        base+(corner*2+1)%sides2,
                        base+(corner*2+2)%sides2])

    obj=Object(name, "Generic building", None, None)
    obj.addgeometry(Material(output.xpver, None), vt, idx)
    return obj
Beispiel #6
0
    def __init__(self, bgl, enda, scale, libname, srcfile, texdir, output):

        self.old=False	# Old style scenery found and skipped
        self.rrt=False	# Old style runways/roads found and skipped
        self.anim=False	# Animations found and skipped

        assert(scale==1)	# new-style objects are scaled when placed

        comment="object %s in file %s" % (libname,asciify(basename(srcfile),False))

        tex=[]
        mattex=[]
        vt=[]
        idx=[]
        matrix=[]
        amap=[]
        scen=[]
        data={}
        
        if bgl.read(4)!='RIFF': raise IOError
        (mdlsize,)=unpack('<I', bgl.read(4))
        endmdl=bgl.tell()+mdlsize
        if bgl.read(4)!='MDLX': raise IOError
        while bgl.tell()<endmdl:
            c=bgl.read(4)
            (size,)=unpack('<I', bgl.read(4))
            if c=='MDLD':
                end=size+bgl.tell()
                while bgl.tell()<end:
                    c=bgl.read(4)
                    (size,)=unpack('<I', bgl.read(4))
                    if c=='TEXT':
                        tex.extend([bgl.read(64).strip('\0').strip() for i in range(0,size,64)])
                    elif c=='MATE':
                        # http://www.fsdeveloper.com/wiki/index.php?title=MDL_file_format_(FSX)#MATE
                        for i in range(0,size,120):
                            (flags1,flags2,diffuse,detail,normal,specular,emissive,reflection,fresnel,dr,dg,db,da,sr,sg,sb,sa,sp,ds,normalscale,recflectionscale,po,power,bloomfloor,ambientscale,srcblend,dstblend,alphafunc,alphathreshhold,zwritealpha)=unpack('<9I16f3I2f', bgl.read(120))
                            # Get texture names
                            diffuse   =(flags1 & Material.FSX_MAT_HAS_DIFFUSE) and tex[diffuse] or None
                            emissive  =(flags1 & Material.FSX_MAT_HAS_EMISSIVE) and tex[emissive] or None
                            if output.xpver<=10:
                                normal=specular=reflection=None	# Not supported in<=10, so no point doing lookup
                            else:
                                specular  =(flags1 & Material.FSX_MAT_HAS_SPECULAR) and tex[specular] or None
                                normal    =(flags1 & Material.FSX_MAT_HAS_NORMAL) and tex[normal] or None
                                reflection=(flags1 & Material.FSX_MAT_HAS_REFLECTION) and tex[reflection] or None
                            # Get texture filenames
                            if diffuse:   diffuse   =findtex(diffuse, texdir, output.addtexdir)
                            if emissive:  emissive  =findtex(emissive, texdir, output.addtexdir)
                            if specular:  specular  =findtex(specular, texdir, output.addtexdir)
                            if normal:    normal    =findtex(normal, texdir, output.addtexdir)
                            if reflection:reflection=findtex(reflection, texdir, output.addtexdir)

                            t=(diffuse or emissive) and Texture(output.xpver, diffuse, emissive, specular, normal, reflection) or None
                            m=Material(output.xpver,
                                       (dr,dg,db),
                                       (flags1 & Material.FSX_MAT_SPECULAR) and not specular and ((sr!=sg or sr!=sb or sr<0.9) and (sr,sg,sb)!=(0,0,0)) and [sr,sg,sb] or None,
                                       False,	# Poly
                                       flags2&Material.FSX_MAT_DOUBLE_SIDED != 0,
                                       flags1&Material.FSX_MAT_ZTEST_ALPHA and alphafunc in [Material.FSX_MAT_ALPHA_TEST_GREATER,Material.FSX_MAT_ALPHA_TEST_GREATER_EQUAL] and alphathreshhold/255 or None,
                                       not diffuse and ((flags1 & Material.FSX_MAT_SPECULAR) and (sr,sg,sb)!=(0,0,0)) and True,
                                       flags1&Material.FSX_MAT_NO_SHADOW != 0)
                            mattex.append((m,t))
                        if __debug__:
                            if output.debug:
                                output.debug.write("Materials %d\n" % len(mattex))
                                for i in range(len(mattex)):
                                    output.debug.write("%3d:\t%s\t%s\n" % (i, mattex[i][0], mattex[i][1]))
                    elif c=='INDE':
                        idx=unpack('<%dH' % (size/2), bgl.read(size))
                    elif c=='VERB':
                        endv=size+bgl.tell()
                        while bgl.tell()<endv:
                            c=bgl.read(4)
                            (size,)=unpack('<I', bgl.read(4))
                            if c=='VERT':
                                vt.append([unpack('<8f',bgl.read(32)) for i in range(0,size,32)])
                            else:
                                bgl.seek(size,1)
                    elif c=='TRAN':
                        for i in range(0,size,64):
                            matrix.append(Matrix([unpack('<4f',bgl.read(16)) for j in range(4)]))
                        if __debug__:
                            if output.debug:
                                output.debug.write("Matrices %d\n" % len(matrix))
                                for i in range(len(matrix)): output.debug.write("%s = %d\n" % (matrix[i], i))
                    elif c=='AMAP':
                        for i in range(0,size,8):
                            (a,b)=unpack('<2I',bgl.read(8))
                            amap.append(b)
                        if __debug__:
                            if output.debug:
                                output.debug.write("Animation map %d\n" % len(amap))
                                for i in range(len(amap)):
                                    output.debug.write("%2d: %2d\n" % (i, amap[i]))
                    elif c=='SCEN':
                        # Assumed to be after TRAN and AMAP sections
                        count=size/8
                        for i in range(count):
                            (child,peer,offset,unk)=unpack('<4h',bgl.read(8))
                            scen.append((child,peer,offset,-1))
                        # Invert Child/Peer pointers to get parents
                        for i in range(count):
                            (child, peer, thisoff, parent)=scen[i]
                            if child!=-1:	# child's parent is me
                                (xchild, xpeer, xoff, xparent)=scen[child]
                                scen[child]=(xchild, xpeer, xoff, i)
                            if peer!=-1:	# peer's parent is my parent
                                (xchild, xpeer, xoff, xparent)=scen[peer]
                                scen[peer]=(xchild, xpeer, xoff, parent)
                        # Replace AMAP offsets with matrix
                        if __debug__:
                            if output.debug: output.debug.write("Scene Graph %d\n" % len(scen))
                        for i in range(count):
                            (child, peer, offset, parent)=scen[i]
                            scen[i]=(child, peer, matrix[amap[offset/8]], parent)
                            if __debug__:
                                if output.debug: output.debug.write("%2d: %2d %2d %2d %2d\n" % (i, child, peer, parent, offset/8))
                    elif c=='LODT':
                        endt=size+bgl.tell()
                        partno=0
                        maxlod=0
                        while bgl.tell()<endt:
                            c=bgl.read(4)
                            (size,)=unpack('<I', bgl.read(4))
                            if c=='LODE':
                                ende=size+bgl.tell()
                                (lod,)=unpack('<I', bgl.read(4))
                                while bgl.tell()<ende:
                                    c=bgl.read(4)
                                    (size,)=unpack('<I', bgl.read(4))
                                    if c=='PART':
                                        (typ,scene,material,verb,voff,vcount,ioff,icount,unk)=unpack('<9I', bgl.read(36))
                                        assert (typ==1)
                                        maxlod=max(lod,maxlod)
                                        (child, peer, finalmatrix, parent)=scen[scene]
                                        if __debug__:
                                            if output.debug:
                                                output.debug.write("LOD %4d: scene %d verb %d material %d tris %d voff %d vcount %d ioff %d icount %d\n" % (lod, scene, verb, material, icount/3, voff, vcount, ioff, icount))

                                        while parent!=-1:
                                            (child, peer, thismatrix, parent)=scen[parent]
                                            finalmatrix=finalmatrix*thismatrix
                                        if not lod in data: data[lod]=[]
                                        data[lod].append((mattex[material][0], mattex[material][1], vt[verb][voff:voff+vcount], idx[ioff:ioff+icount], finalmatrix))
                                        partno+=1
                                    else:
                                        bgl.seek(size,1)
                            else:
                                bgl.seek(size,1)
                    else:
                        bgl.seek(size,1)
            else:
                bgl.seek(size,1)

        # Only interested in highest LOD
        objs={}	# objs by texture
        for (m,t,vt,idx,matrix) in data[maxlod]:
            if __debug__:
                if output.debug: output.debug.write("%s\n%s\n" % (t, matrix))
            objvt=[]
            nrmmatrix=matrix.adjoint()
            if t:
                assert not t.s and not t.n and not t.r	# Bunching scheme will need re-work
                for (x,y,z, nx,ny,nz, tu,tv) in vt:
                    (x,y,z)=matrix.transform(x,y,z)
                    (nx,ny,nz)=nrmmatrix.rotateAndNormalize(nx,ny,nz)
                    objvt.append((x,y,-z, nx,ny,-nz, tu,tv))
            else:
                # replace material with palette texture
                (pu,pv)=rgb2uv(m.d)
                for (x,y,z, nx,ny,nz, tu,tv) in vt:
                    (x,y,z)=matrix.transform(x,y,z)
                    (nx,ny,nz)=nrmmatrix.rotateAndNormalize(nx,ny,nz)
                    objvt.append((x,y,-z, nx,ny,-nz, pu,pv))
            if t in objs:
                obj=objs[t]
                if t and t.e: obj.tex.e=t.e	# Because we don't compare on emissive
            else:
                objs[t]=obj=Object(libname, comment, t, None)
            obj.addgeometry(m, objvt, idx)

        # Add objs to library with one name
        if objs: output.objdat[libname]=objs.values()