예제 #1
0
파일: __init__.py 프로젝트: garthand/s3py
 def __init__(self, key=None, stream=None):
     self.version = self.VERSION.DEFAULT
     self.bounds = BoundingBox()
     self.flags = 0x00000000
     self.routing_footprint = ExternalResource(ResourceKey())
     self.entries = []
     RCOL.__init__(self, key, stream)
예제 #2
0
 def __init__(self, key, stream=None, rcol=None):
     self.version = self.VERSION.STANDARD
     self.bounds = BoundingBox()
     self.extra_bounds = []
     self.fade_type = 0
     self.custom_fade_distance = 0.0
     self.lods = []
     RCOL.__init__(self, key, stream)
예제 #3
0
파일: __init__.py 프로젝트: garthand/s3py
 def __init__(self, ftpt, stream=None):
     self.ftpt = ftpt
     self.name = None
     self.priority = 0
     self.footprint_type_flags = 0
     self.points = []
     self.allow_intersection_flags = 0
     self.surface_type_flags = 0
     self.surface_attribute_flags = 0
     self.level_offset = 0
     self.elevation_offset = 0
     self.bounds = BoundingBox(dimensions=2)
     Serializable.__init__(self, stream)
예제 #4
0
 def __init__(self, key=None, stream=None):
     self.version = self.VERSION.DEFAULT
     self.bounds = BoundingBox()
     self.flags = 0x00000000
     self.routing_footprint = ExternalResource(ResourceKey())
     self.entries = []
     RCOL.__init__(self, key, stream)
예제 #5
0
 def __init__(self, key, stream=None, rcol=None):
     self.version = self.VERSION.STANDARD
     self.bounds = BoundingBox()
     self.extra_bounds = []
     self.fade_type = 0
     self.custom_fade_distance = 0.0
     self.lods = []
     RCOL.__init__(self, key, stream)
예제 #6
0
 def __init__(self, ftpt, stream=None):
     self.ftpt = ftpt
     self.name = None
     self.priority = 0
     self.footprint_type_flags = 0
     self.points = []
     self.allow_intersection_flags = 0
     self.surface_type_flags = 0
     self.surface_attribute_flags = 0
     self.level_offset = 0
     self.elevation_offset = 0
     self.bounds = BoundingBox(dimensions=2)
     Serializable.__init__(self, stream)
예제 #7
0
 def read_rcol(self, stream, rcol):
     s = StreamReader(stream)
     self.read_tag(stream)
     self.version = s.u32()
     cLods = s.i32()
     self.bounds.read(stream)
     if self.version >= self.VERSION.EXTENDED:
         self.extra_bounds = [
             BoundingBox(stream=stream) for i in range(s.i32())
         ]
         self.fade_type = s.u32()
         self.custom_fade_distance = s.f32()
     self.lods = [self.LOD(stream, rcol) for i in range(cLods)]
예제 #8
0
 def __init__(self, stream=None, resources=None, parent=None):
     self.name = None
     self.material = None
     self.vertex_format = None
     self.vertex_buffer = None
     self.index_buffer = None
     self.flags = self.Flags.PICKABLE
     self.primitive_type = self.PrimitiveType.TRIANGLE_LIST
     self.stream_offset = 0
     self.start_vertex = 0
     self.start_index = 0
     self.min_vertex_index = 0
     self.vertex_count = 0
     self.primitive_count = 0
     self.bounds = BoundingBox()
     self.skin_controller = None
     self.bone_references = []
     self.scale_offsets = None
     self.states = []
     self.parent_name = 0
     self.mirror_plane_normal = [0.0, 0.0, 0.0]
     self.mirror_plane_offset = 0.0
     ChildElement.__init__(self, parent)
     Serializable.__init__(self, stream, resources)
예제 #9
0
    class Area(Serializable):
        def __init__(self, ftpt, stream=None):
            self.ftpt = ftpt
            self.name = None
            self.priority = 0
            self.footprint_type_flags = 0
            self.points = []
            self.allow_intersection_flags = 0
            self.surface_type_flags = 0
            self.surface_attribute_flags = 0
            self.level_offset = 0
            self.elevation_offset = 0
            self.bounds = BoundingBox(dimensions=2)
            Serializable.__init__(self, stream)

        def read(self, stream, resource=None):
            s = StreamReader(stream)
            self.name = s.u32()
            self.priority = s.i8()
            self.footprint_type_flags = s.u32()
            self.points = [(s.f32(), s.f32()) for i in range(s.i32())]
            self.allow_intersection_flags = s.u32()
            self.surface_type_flags = s.u32()
            self.surface_attribute_flags = s.u32()
            self.level_offset = s.i32()
            if self.ftpt.version >= Footprint.VERSION.EXTENDED: self.elevation_offset = s.f32()
            self.bounds.read(stream)

        def write(self, stream, resource=None):
            s = StreamWriter(stream)
            self.bounds.clear()
            s.hash(self.name)
            s.i8(self.priority)
            s.u32(self.footprint_type_flags)
            s.i32(len(self.points))
            for point in self.points:
                self.bounds.add(point)
                s.f32(point[0])
                s.f32(point[1])
            s.u32(self.allow_intersection_flags)
            s.u32(self.surface_type_flags)
            s.u32(self.surface_attribute_flags)
            s.i8(self.level_offset)
            if self.ftpt.version >= Footprint.VERSION.EXTENDED: s.f32(self.elevation_offset)
            self.bounds.write(stream)
예제 #10
0
파일: __init__.py 프로젝트: garthand/s3py
    class Area(Serializable):
        def __init__(self, ftpt, stream=None):
            self.ftpt = ftpt
            self.name = None
            self.priority = 0
            self.footprint_type_flags = 0
            self.points = []
            self.allow_intersection_flags = 0
            self.surface_type_flags = 0
            self.surface_attribute_flags = 0
            self.level_offset = 0
            self.elevation_offset = 0
            self.bounds = BoundingBox(dimensions=2)
            Serializable.__init__(self, stream)

        def read(self, stream, resource=None):
            s = StreamReader(stream)
            self.name = s.u32()
            self.priority = s.i8()
            self.footprint_type_flags = s.u32()
            self.points = [(s.f32(), s.f32()) for i in range(s.i32())]
            self.allow_intersection_flags = s.u32()
            self.surface_type_flags = s.u32()
            self.surface_attribute_flags = s.u32()
            self.level_offset = s.i32()
            if self.ftpt.version >= Footprint.VERSION.EXTENDED: self.elevation_offset = s.f32()
            self.bounds.read(stream)

        def write(self, stream, resource=None):
            s = StreamWriter(stream)
            self.bounds.clear()
            s.hash(self.name)
            s.i8(self.priority)
            s.u32(self.footprint_type_flags)
            s.i32(len(self.points))
            for point in self.points:
                self.bounds.add(point)
                s.f32(point[0])
                s.f32(point[1])
            s.u32(self.allow_intersection_flags)
            s.u32(self.surface_type_flags)
            s.u32(self.surface_attribute_flags)
            s.i8(self.level_offset)
            if self.ftpt.version >= Footprint.VERSION.EXTENDED: s.f32(self.elevation_offset)
            self.bounds.write(stream)
예제 #11
0
 def __init__(self, stream=None, resources=None, parent=None):
     self.name = None
     self.material = None
     self.vertex_format = None
     self.vertex_buffer = None
     self.index_buffer = None
     self.flags = self.Flags.PICKABLE
     self.primitive_type = self.PrimitiveType.TRIANGLE_LIST
     self.stream_offset = 0
     self.start_vertex = 0
     self.start_index = 0
     self.min_vertex_index = 0
     self.vertex_count = 0
     self.primitive_count = 0
     self.bounds = BoundingBox()
     self.skin_controller = None
     self.bone_references = []
     self.scale_offsets = None
     self.states = []
     self.parent_name = 0
     self.mirror_plane_normal = [0.0, 0.0, 0.0]
     self.mirror_plane_offset = 0.0
     ChildElement.__init__(self,parent)
     Serializable.__init__(self, stream, resources)
예제 #12
0
class VisualProxy(RCOL):
    ID = 0x736884F1
    TAG = 'VPXY'

    class VERSION:
        DEFAULT = 0x00000004

    def __init__(self, key=None, stream=None):
        self.version = self.VERSION.DEFAULT
        self.bounds = BoundingBox()
        self.flags = 0x00000000
        self.routing_footprint = ExternalResource(ResourceKey())
        self.entries = []
        RCOL.__init__(self, key, stream)

    def read_rcol(self, stream, rcol):
        self.read_tag(stream)
        s = StreamReader(stream)
        tgi = TGIList()
        self.version = s.u32()
        tgi.begin_read(stream)
        cEntries = s.u8()
        for entry_index in range(cEntries):
            t = s.u8()
            entry = self.Entry.create_instance(t)
            entry.read(stream, tgi)
            self.entries.append(entry)
        assert s.u8() == 0x02
        self.bounds.read(stream)
        self.flags = s.u32()
        if s.u8():
            self.routing_footprint = tgi.get_resource(s.u32())
        tgi.end_read(stream)

    def write_rcol(self, stream, rcol):
        self.write_tag(stream)
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        s.u8(len(self.entries))
        for entry in self.entries:
            s.u8(entry.TYPE)
            entry.write(stream, tgi)
        s.u8(2)
        self.bounds.write(stream)
        s.u32(self.flags)
        if self.routing_footprint.key != ResourceKey():
            s.u8(1)
            s.tgi(self.routing_footprint.key, 'TGI')
        else: s.u8(0)
        tgi.end_write(stream)

    class Entry(Serializable):
        def __init__(self, stream=None, resources=None):
            Serializable.__init__(self, stream, resources)

        @staticmethod
        def create_instance(type):
            if type == VisualProxy.MiscEntry.TYPE: return VisualProxy.MiscEntry()
            elif type == VisualProxy.LodEntry.TYPE: return VisualProxy.LodEntry()
        def read(self, stream, resources=None):
            pass
        def write(self, stream, resources=None):
            pass

    class MiscEntry(Entry):
        TYPE = 0x00000001

        def __init__(self, stream=None, resources=None, parent=None):
            self.index = 0
            self.resource = ExternalResource(ResourceKey())
            VisualProxy.Entry.__init__(self, stream, resources)

        def read(self, stream, tgi=None):
            s = StreamReader(stream)
            self.index = s.u32()
            self.resource = tgi.get_resource(self.index)

        def write(self, stream, tgi=None):
            s = StreamWriter(stream)
            s.u32(self.index)
            s.u32(tgi.get_resource_index(self.resource))

        def __str__(self):
            return "%s" % self.resource

    class LodEntry(Entry):
        TYPE = 0x00000000

        def __init__(self, stream=None, resources=None):
            self.index = 0
            self.resources = []
            VisualProxy.Entry.__init__(self, stream, resources)

        def read(self, stream, resources=None):
            s = StreamReader(stream)
            self.index = s.u8()
            self.resources = [resources.get_resource(s.u32()) for i in range(s.u8())]

        def write(self, stream, resources=None):
            s = StreamWriter(stream)
            s.u8(self.index)
            s.u8(len(self.resources))
            for resource in self.resources: s.u32(resources.get_resource_index(resource))

        def __str__(self):
            return "%s" % self.resources
예제 #13
0
class ObjectMesh(Serializable, ChildElement, Mesh):
    class Flags:
        BASIN_INTERIOR = 0x00000001
        HD_EXTERIOR_LIT = 0x00000002
        PORTAL_SIDE = 0x00000004
        DROP_SHADOW = 0x00000008
        SHADOW_CASTER = 0x00000010
        FOUNDATION = 0x00000020
        PICKABLE = 0x00000040

    class PrimitiveType:
        POINT_LIST = 0x00000000
        LINE_LIST = 0x00000001
        LINE_STRIP = 0x00000002
        TRIANGLE_LIST = 0x00000003
        TRIANGLE_FAN = 0x00000004
        TRIANGLE_STRIP = 0x00000005
        QUAD_LIST = 0x00000006
        DISPLAY_LIST = 0x00000007


    class State(Serializable):
        def __init__(self, stream=None):
            self.name = 0
            self.start_index = 0
            self.start_vertex = 0
            self.vertex_count = 0
            self.index_count = 0
            Serializable.__init__(self, stream)

        def read(self, stream, resource=None):
            s = StreamReader(stream)
            self.name = s.u32()
            self.start_index = s.i32()
            self.start_vertex = s.i32()
            self.vertex_count = s.i32()
            self.index_count = s.i32()

        def write(self, stream, resource=None):
            s = StreamWriter(stream)
            s.hash(self.name)
            s.i32(self.start_index)
            s.i32(self.start_vertex)
            s.i32(self.vertex_count)
            s.i32(self.index_count)

    def is_dropshadow(self):
        return isinstance(self.material,MaterialDefinition) and int(self.material.shader_name) == 0xC09C7582

    def __init__(self, stream=None, resources=None, parent=None):
        self.name = None
        self.material = None
        self.vertex_format = None
        self.vertex_buffer = None
        self.index_buffer = None
        self.flags = self.Flags.PICKABLE
        self.primitive_type = self.PrimitiveType.TRIANGLE_LIST
        self.stream_offset = 0
        self.start_vertex = 0
        self.start_index = 0
        self.min_vertex_index = 0
        self.vertex_count = 0
        self.primitive_count = 0
        self.bounds = BoundingBox()
        self.skin_controller = None
        self.bone_references = []
        self.scale_offsets = None
        self.states = []
        self.parent_name = 0
        self.mirror_plane_normal = [0.0, 0.0, 0.0]
        self.mirror_plane_offset = 0.0
        ChildElement.__init__(self,parent)
        Serializable.__init__(self, stream, resources)
    def get_vertex_format(self):
        return self.vertex_format if self.vertex_format != None else VertexFormat.default_sunshadow() if Flag.is_set(self.flags,self.Flags.SHADOW_CASTER) else VertexFormat.default_drop_shadow()



    def read(self, stream, rcol):
        s = StreamReader(stream)
        data_len = s.u32()
        end = stream.tell() + data_len
        self.name = s.u32()
        self.material = rcol.get_block(s.u32(), (MaterialDefinition, MaterialSet))
        self.vertex_format = rcol.get_block(s.u32(), VertexFormat)
        self.vertex_buffer = rcol.get_block(s.u32(), (VertexBuffer, VertexBufferShadow))
        self.index_buffer = rcol.get_block(s.u32(), (IndexBuffer, IndexBufferShadow))
        flags = s.u32()
        self.flags = flags >> 8
        self.primitive_type = flags & 0x000000FF
        self.stream_offset = s.u32()
        self.start_vertex = s.i32()
        self.start_index = s.i32()
        self.min_vertex_index = s.i32()
        self.vertex_count = s.i32()
        self.primitive_count = s.i32()
        self.bounds.read(stream)
        self.skin_controller = rcol.get_block(s.u32(), ObjectSkinController)
        self.bone_references = [s.u32() for i in range(s.i32())]
        self.scale_offsets = rcol.get_block(s.u32(), MaterialDefinition)
        self.states = [self.State(stream) for i in range(s.i32())]
        if self.parent.version > ModelLod.VERSION.DEFAULT:
            self.parent_name = s.u32()
            self.mirror_plane_normal = [s.f32() for i in range(3)]
            self.mirror_plane_offset = s.f32()
        if not stream.tell() == end: raise Exception(
            "Invalid MLOD.Mesh data length: expected 0x%X, but got 0x%08X" % (end, stream.tell()))

    def write(self, stream, rcol):
        s = StreamWriter(stream)
        len_offset = stream.tell()
        s.u32(0)
        start = stream.tell()
        s.hash(self.name)
        s.u32(rcol.get_block_index(self.material))
        s.u32(rcol.get_block_index(self.vertex_format))
        s.u32(rcol.get_block_index(self.vertex_buffer))
        s.u32(rcol.get_block_index(self.index_buffer))

        flags = self.primitive_type
        flags |= (self.flags << 8)
        s.u32(flags)
        s.u32(self.stream_offset)
        s.i32(self.start_vertex)
        s.i32(self.start_index)
        s.i32(self.min_vertex_index)
        s.i32(self.vertex_count)
        s.i32(self.primitive_count)
        self.bounds.write(stream)
        s.u32(rcol.get_block_index(self.skin_controller))
        s.i32(len(self.bone_references))
        for bone in self.bone_references: s.u32(bone)
        s.u32(rcol.get_block_index(self.scale_offsets))
        s.i32(len(self.states))
        for state in self.states: state.write_rcol(self, rcol)
        if self.parent.version > ModelLod.VERSION.DEFAULT:
            s.hash(self.parent_name)
            for i in range(3): s.f32(self.mirror_plane_normal[i])
            s.f32(self.mirror_plane_offset)
        end = stream.tell()
        stream.seek(len_offset, SEEK_SET)
        s.u32(end - start)
        stream.seek(end, SEEK_SET)

    def get_uv_scales(self):
        uvscales = [1/0x7FFF] * 3
        key = 'uvscales'
        material = self.material
        if material == None: return  None
        while not  isinstance(material, MaterialDefinition):
            if isinstance(material, MaterialSet):
                material = material.default_material.material
            else:
                raise Exception("Expected a MaterialDefinition or MaterialSet")
        if key in material.material_block:
            uvscales = material.material_block[key]
        return uvscales

    def get_vertices(self):
        uvscales = self.get_uv_scales()
        vrtf = self.get_vertex_format()
        verts = self.vertex_buffer.buffer.read_vertices(self.stream_offset, vrtf, self.vertex_count,
            uvscales)
        return verts

    def get_triangles(self):
        primitive_size = 0
        if self.primitive_type == self.PrimitiveType.TRIANGLE_LIST:
            primitive_size = 3
        else:
            raise NotImplementedError()
        return [[self.index_buffer.buffer[self.start_index + (primitive_index * primitive_size) + i] for i in
                 range(primitive_size)] for primitive_index in range(self.primitive_count)]
예제 #14
0
class Model(RCOL):
    TAG = 'MODL'
    ID = 0x01661233

    class VERSION():
        STANDARD = 0x00000100
        EXTENDED = 0x00000102

    class LOD(Serializable):
        class FLAGS:
            NONE = 0x00000000
            PORTAL = 0x00000001
            DOOR = 0x00000002

        def __init__(self, stream=None, rcol=None):
            self.model = None
            self.flags = Model.LOD.FLAGS.NONE
            self.id = LOD_ID.MEDIUM_DETAIL
            self.min_z = 0.0
            self.max_z = 0.0
            Serializable.__init__(self, stream, rcol)

        def read(self, stream, resources):
            s = StreamReader(stream)
            self.model = resources.get_block(s.u32(), ModelLod)
            self.flags = s.u32()
            self.id = s.u16()
            self.is_sunshadow = bool(s.u16())
            self.min_z = s.f32()
            self.max_z = s.f32()

        def write(self, stream, resources):
            s = StreamWriter(stream)
            s.u32(resources.get_block_index(self.model, RCOL.Reference.PUBLIC))
            s.u32(self.flags)
            s.u16(self.id)
            s.u16(int(self.is_sunshadow))
            s.f32(self.min_z)
            s.f32(self.max_z)


    def __init__(self, key, stream=None, rcol=None):
        self.version = self.VERSION.STANDARD
        self.bounds = BoundingBox()
        self.extra_bounds = []
        self.fade_type = 0
        self.custom_fade_distance = 0.0
        self.lods = []
        RCOL.__init__(self, key, stream)


    def read_rcol(self, stream, rcol):
        s = StreamReader(stream)
        self.read_tag(stream)
        self.version = s.u32()
        cLods = s.i32()
        self.bounds.read(stream)
        if self.version >= self.VERSION.EXTENDED:
            self.extra_bounds = [BoundingBox(stream=stream) for i in range(s.i32())]
            self.fade_type = s.u32()
            self.custom_fade_distance = s.f32()
        self.lods = [self.LOD(stream, rcol) for i in range(cLods)]

    def write_rcol(self, stream, rcol):
        s = StreamWriter(stream)
        self.write_tag(stream)
        s.u32(self.version)
        s.i32(len(self.lods))
        self.bounds.write(stream)
        if self.version >= self.VERSION.EXTENDED:
            s.i32(len(self.extra_bounds))
            for extra in self.extra_bounds:
                extra.write(stream)
            s.u32(self.fade_type)
            s.f32(self.custom_fade_distance)
        for lod in self.lods:
            lod.write_rcol(stream, rcol)
예제 #15
0
class Model(RCOL):
    TAG = 'MODL'
    ID = 0x01661233

    class VERSION():
        STANDARD = 0x00000100
        EXTENDED = 0x00000102

    class LOD(Serializable):
        class FLAGS:
            NONE = 0x00000000
            PORTAL = 0x00000001
            DOOR = 0x00000002

        def __init__(self, stream=None, rcol=None):
            self.model = None
            self.flags = Model.LOD.FLAGS.NONE
            self.id = LOD_ID.MEDIUM_DETAIL
            self.min_z = 0.0
            self.max_z = 0.0
            Serializable.__init__(self, stream, rcol)

        def read(self, stream, resources):
            s = StreamReader(stream)
            self.model = resources.get_block(s.u32(), ModelLod)
            self.flags = s.u32()
            self.id = s.u16()
            self.is_sunshadow = bool(s.u16())
            self.min_z = s.f32()
            self.max_z = s.f32()

        def write(self, stream, resources):
            s = StreamWriter(stream)
            s.u32(resources.get_block_index(self.model, RCOL.Reference.PUBLIC))
            s.u32(self.flags)
            s.u16(self.id)
            s.u16(int(self.is_sunshadow))
            s.f32(self.min_z)
            s.f32(self.max_z)

    def __init__(self, key, stream=None, rcol=None):
        self.version = self.VERSION.STANDARD
        self.bounds = BoundingBox()
        self.extra_bounds = []
        self.fade_type = 0
        self.custom_fade_distance = 0.0
        self.lods = []
        RCOL.__init__(self, key, stream)

    def read_rcol(self, stream, rcol):
        s = StreamReader(stream)
        self.read_tag(stream)
        self.version = s.u32()
        cLods = s.i32()
        self.bounds.read(stream)
        if self.version >= self.VERSION.EXTENDED:
            self.extra_bounds = [
                BoundingBox(stream=stream) for i in range(s.i32())
            ]
            self.fade_type = s.u32()
            self.custom_fade_distance = s.f32()
        self.lods = [self.LOD(stream, rcol) for i in range(cLods)]

    def write_rcol(self, stream, rcol):
        s = StreamWriter(stream)
        self.write_tag(stream)
        s.u32(self.version)
        s.i32(len(self.lods))
        self.bounds.write(stream)
        if self.version >= self.VERSION.EXTENDED:
            s.i32(len(self.extra_bounds))
            for extra in self.extra_bounds:
                extra.write(stream)
            s.u32(self.fade_type)
            s.f32(self.custom_fade_distance)
        for lod in self.lods:
            lod.write_rcol(stream, rcol)
예제 #16
0
파일: __init__.py 프로젝트: garthand/s3py
class VisualProxy(RCOL):
    ID = 0x736884F1
    TAG = 'VPXY'

    class VERSION:
        DEFAULT = 0x00000004

    def __init__(self, key=None, stream=None):
        self.version = self.VERSION.DEFAULT
        self.bounds = BoundingBox()
        self.flags = 0x00000000
        self.routing_footprint = ExternalResource(ResourceKey())
        self.entries = []
        RCOL.__init__(self, key, stream)

    def read_rcol(self, stream, rcol):
        self.read_tag(stream)
        s = StreamReader(stream)
        tgi = TGIList()
        self.version = s.u32()
        tgi.begin_read(stream)
        cEntries = s.u8()
        for entry_index in range(cEntries):
            type = s.u8()
            entry = self.Entry.create_instance(type)
            entry.read(stream, tgi)
            self.entries.append(entry)
        assert s.u8() == 0x02
        self.bounds.read(stream)
        self.flags = s.u32()
        if s.u8():
            self.routing_footprint = tgi.get_resource(s.u32())
        tgi.end_read(stream)

    def write_rcol(self, stream, rcol):
        self.write_tag(stream)
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        s.u8(len(self.entries))
        for entry in self.entries:
            s.u8(entry.TYPE)
            entry.write(stream, tgi)
        s.u8(2)
        self.bounds.write(stream)
        s.u32(self.flags)
        if self.routing_footprint.key != ResourceKey():
            s.u8(1)
            s.tgi(self.routing_footprint.key, 'TGI')
        else: s.u8(0)
        tgi.end_write(stream)

    class Entry(Serializable):
        def __init__(self, stream=None, resources=None):
            Serializable.__init__(self, stream, resources)

        @staticmethod
        def create_instance(type):
            if type == VisualProxy.MiscEntry.TYPE: return VisualProxy.MiscEntry()
            elif type == VisualProxy.LodEntry.TYPE: return VisualProxy.LodEntry()

    class MiscEntry(Entry):
        TYPE = 0x00000001

        def __init__(self, stream=None, resources=None, parent=None):
            self.index = 0
            self.resource = ExternalResource(ResourceKey())
            VisualProxy.Entry.__init__(self, stream, resources)

        def read(self, stream, tgi):
            s = StreamReader(stream)
            self.index = s.u32()
            self.resource = tgi.get_resource(self.index)

        def write(self, stream, tgi):
            s = StreamWriter(stream)
            s.u32(self.index)
            s.u32(tgi.get_resource_index(self.resource))

        def __str__(self):
            return "%s" % self.resource

    class LodEntry(Entry):
        TYPE = 0x00000000

        def __init__(self, stream=None, resources=None):
            self.index = 0
            self.resources = []
            VisualProxy.Entry.__init__(self, stream, resources)

        def read(self, stream, resources):
            s = StreamReader(stream)
            self.index = s.u8()
            self.resources = [resources.get_resource(s.u32()) for i in range(s.u8())]

        def write(self, stream, resources):
            s = StreamWriter(stream)
            s.u8(self.index)
            s.u8(len(self.resources))
            for resource in self.resources: s.u32(resources.get_resource_index(resource))

        def __str__(self):
            return "%s" % self.resources
예제 #17
0
class ObjectMesh(Serializable, ChildElement, Mesh):
    class Flags:
        BASIN_INTERIOR = 0x00000001
        HD_EXTERIOR_LIT = 0x00000002
        PORTAL_SIDE = 0x00000004
        DROP_SHADOW = 0x00000008
        SHADOW_CASTER = 0x00000010
        FOUNDATION = 0x00000020
        PICKABLE = 0x00000040

    class PrimitiveType:
        POINT_LIST = 0x00000000
        LINE_LIST = 0x00000001
        LINE_STRIP = 0x00000002
        TRIANGLE_LIST = 0x00000003
        TRIANGLE_FAN = 0x00000004
        TRIANGLE_STRIP = 0x00000005
        QUAD_LIST = 0x00000006
        DISPLAY_LIST = 0x00000007

    class State(Serializable):
        def __init__(self, stream=None):
            self.name = 0
            self.start_index = 0
            self.start_vertex = 0
            self.vertex_count = 0
            self.index_count = 0
            Serializable.__init__(self, stream)

        def read(self, stream, resource=None):
            s = StreamReader(stream)
            self.name = s.u32()
            self.start_index = s.i32()
            self.start_vertex = s.i32()
            self.vertex_count = s.i32()
            self.index_count = s.i32()

        def write(self, stream, resource=None):
            s = StreamWriter(stream)
            s.hash(self.name)
            s.i32(self.start_index)
            s.i32(self.start_vertex)
            s.i32(self.vertex_count)
            s.i32(self.index_count)

    def is_dropshadow(self):
        return isinstance(self.material, MaterialDefinition) and int(
            self.material.shader_name) == 0xC09C7582

    def __init__(self, stream=None, resources=None, parent=None):
        self.name = None
        self.material = None
        self.vertex_format = None
        self.vertex_buffer = None
        self.index_buffer = None
        self.flags = self.Flags.PICKABLE
        self.primitive_type = self.PrimitiveType.TRIANGLE_LIST
        self.stream_offset = 0
        self.start_vertex = 0
        self.start_index = 0
        self.min_vertex_index = 0
        self.vertex_count = 0
        self.primitive_count = 0
        self.bounds = BoundingBox()
        self.skin_controller = None
        self.bone_references = []
        self.scale_offsets = None
        self.states = []
        self.parent_name = 0
        self.mirror_plane_normal = [0.0, 0.0, 0.0]
        self.mirror_plane_offset = 0.0
        ChildElement.__init__(self, parent)
        Serializable.__init__(self, stream, resources)

    def get_vertex_format(self):
        return self.vertex_format if self.vertex_format != None else VertexFormat.default_sunshadow(
        ) if Flag.is_set(self.flags, self.Flags.SHADOW_CASTER
                         ) else VertexFormat.default_drop_shadow()

    def read(self, stream, rcol):
        s = StreamReader(stream)
        data_len = s.u32()
        end = stream.tell() + data_len
        self.name = s.u32()
        self.material = rcol.get_block(s.u32(),
                                       (MaterialDefinition, MaterialSet))
        self.vertex_format = rcol.get_block(s.u32(), VertexFormat)
        self.vertex_buffer = rcol.get_block(s.u32(),
                                            (VertexBuffer, VertexBufferShadow))
        self.index_buffer = rcol.get_block(s.u32(),
                                           (IndexBuffer, IndexBufferShadow))
        flags = s.u32()
        self.flags = flags >> 8
        self.primitive_type = flags & 0x000000FF
        self.stream_offset = s.u32()
        self.start_vertex = s.i32()
        self.start_index = s.i32()
        self.min_vertex_index = s.i32()
        self.vertex_count = s.i32()
        self.primitive_count = s.i32()
        self.bounds.read(stream)
        self.skin_controller = rcol.get_block(s.u32(), ObjectSkinController)
        self.bone_references = [s.u32() for i in range(s.i32())]
        self.scale_offsets = rcol.get_block(s.u32(), MaterialDefinition)
        self.states = [self.State(stream) for i in range(s.i32())]
        if self.parent.version > ModelLod.VERSION.DEFAULT:
            self.parent_name = s.u32()
            self.mirror_plane_normal = [s.f32() for i in range(3)]
            self.mirror_plane_offset = s.f32()
        if not stream.tell() == end:
            raise Exception(
                "Invalid MLOD.Mesh data length: expected 0x%X, but got 0x%08X"
                % (end, stream.tell()))

    def write(self, stream, rcol):
        s = StreamWriter(stream)
        len_offset = stream.tell()
        s.u32(0)
        start = stream.tell()
        s.hash(self.name)
        s.u32(rcol.get_block_index(self.material))
        s.u32(rcol.get_block_index(self.vertex_format))
        s.u32(rcol.get_block_index(self.vertex_buffer))
        s.u32(rcol.get_block_index(self.index_buffer))

        flags = self.primitive_type
        flags |= (self.flags << 8)
        s.u32(flags)
        s.u32(self.stream_offset)
        s.i32(self.start_vertex)
        s.i32(self.start_index)
        s.i32(self.min_vertex_index)
        s.i32(self.vertex_count)
        s.i32(self.primitive_count)
        self.bounds.write(stream)
        s.u32(rcol.get_block_index(self.skin_controller))
        s.i32(len(self.bone_references))
        for bone in self.bone_references:
            s.u32(bone)
        s.u32(rcol.get_block_index(self.scale_offsets))
        s.i32(len(self.states))
        for state in self.states:
            state.write_rcol(self, rcol)
        if self.parent.version > ModelLod.VERSION.DEFAULT:
            s.hash(self.parent_name)
            for i in range(3):
                s.f32(self.mirror_plane_normal[i])
            s.f32(self.mirror_plane_offset)
        end = stream.tell()
        stream.seek(len_offset, SEEK_SET)
        s.u32(end - start)
        stream.seek(end, SEEK_SET)

    def get_uv_scales(self):
        uvscales = [1 / 0x7FFF] * 3
        key = 'uvscales'
        material = self.material
        if material == None: return None
        while not isinstance(material, MaterialDefinition):
            if isinstance(material, MaterialSet):
                material = material.default_material.material
            else:
                raise Exception("Expected a MaterialDefinition or MaterialSet")
        if key in material.material_block:
            uvscales = material.material_block[key]
        return uvscales

    def get_vertices(self):
        uvscales = self.get_uv_scales()
        vrtf = self.get_vertex_format()
        verts = self.vertex_buffer.buffer.read_vertices(
            self.stream_offset, vrtf, self.vertex_count, uvscales)
        return verts

    def get_triangles(self):
        primitive_size = 0
        if self.primitive_type == self.PrimitiveType.TRIANGLE_LIST:
            primitive_size = 3
        else:
            raise NotImplementedError()
        return [[
            self.index_buffer.buffer[self.start_index +
                                     (primitive_index * primitive_size) + i]
            for i in range(primitive_size)
        ] for primitive_index in range(self.primitive_count)]