def read(self, stream, cdi, floats): assert isinstance(cdi,CurveDataInfo) s = StreamReader(stream) self.data = [] self.frame_index = s.u16() flags = s.u16() self.flags = flags >> 4 if cdi.flags.type == CurveDataType.VECTOR3_INDEXED: for floatsRead in range(cdi.float_count()): index = s.u16() val = floats[index] if flags & 1 << floatsRead: val *= -1 self.data.append(Frame.unpack(val, cdi.offset, cdi.scale)) else: for packedRead in range(cdi.packed_count()): if cdi.flags.type == CurveDataType.VECTOR3_PACKED: packed = s.u32() elif cdi.flags.type in ( CurveDataType.VECTOR4_PACKED, CurveDataType.SCALAR): packed = s.u16() else: raise Exception("Unknown packed format type") for packedIndex in range(int(cdi.float_count() / cdi.packed_count())): floatIndex = packedIndex + packedRead bitsPerFloat = cdi.bits_per_float() maxPackedVal = math.pow(2, bitsPerFloat) - 1.0 mask = int(maxPackedVal) << (packedIndex * bitsPerFloat) val = ( (packed & mask) >> (packedIndex * bitsPerFloat)) / maxPackedVal if flags & 1 << floatIndex: val *= -1.0 self.data.append(Frame.unpack(val, cdi.offset, cdi.scale)) return self
def read(self, stream, cdi, floats): assert isinstance(cdi, CurveDataInfo) s = StreamReader(stream) self.data = [] self.frame_index = s.u16() flags = s.u16() self.flags = flags >> 4 if cdi.flags.type == CurveDataType.VECTOR3_INDEXED: for floatsRead in range(cdi.float_count()): index = s.u16() val = floats[index] if flags & 1 << floatsRead: val *= -1 self.data.append(Frame.unpack(val, cdi.offset, cdi.scale)) else: for packedRead in range(cdi.packed_count()): if cdi.flags.type == CurveDataType.VECTOR3_PACKED: packed = s.u32() elif cdi.flags.type in (CurveDataType.VECTOR4_PACKED, CurveDataType.SCALAR): packed = s.u16() else: raise Exception("Unknown packed format type") for packedIndex in range( int(cdi.float_count() / cdi.packed_count())): floatIndex = packedIndex + packedRead bitsPerFloat = cdi.bits_per_float() maxPackedVal = math.pow(2, bitsPerFloat) - 1.0 mask = int(maxPackedVal) << (packedIndex * bitsPerFloat) val = ((packed & mask) >> (packedIndex * bitsPerFloat)) / maxPackedVal if flags & 1 << floatIndex: val *= -1.0 self.data.append(Frame.unpack(val, cdi.offset, cdi.scale)) return self
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 read(self, stream, resources=None): s = StreamReader(stream) tag = s.chars(8) if not tag == '_pilC3S_': raise Exception("Not a valid _S3Clip_") self.version = s.u32() self.unknown1 = s.u32() self.frame_duration = s.f32() self.max_frame_count = s.u16() self.unknown2 = s.u16() cCurves = s.u32() cFloats = s.u32() curveOffset = StreamPtr.begin_read(s) frameOffset = StreamPtr.begin_read(s) nameOffset = StreamPtr.begin_read(s) srcNameOffset = StreamPtr.begin_read(s) curveOffset.end() curves = [] for curveIndex in range(cCurves): cdi = CurveDataInfo() cdi.read(stream) curves.append(cdi) nameOffset.end() self.name = s.zs() srcNameOffset.end() self.source_file_name = s.zs() frameOffset.end() indexedFloats = [] for floatIndex in range(cFloats): indexedFloats.append(s.f32()) trackMap = {} self.tracks = [] for curveIndex,cdi in enumerate(curves): cdi.frame_data_ptr.end() if cdi.track_key not in trackMap.keys(): t = Track(cdi.track_key) trackMap[cdi.track_key] = t self.tracks.append(t) track = trackMap[cdi.track_key] frames = [] for frameIndex in range(cdi.frame_count): f = Frame() f.read(stream, cdi, indexedFloats) frames.append(f) curve = Curve(cdi.type) curve.flags = cdi.flags curve.frames = frames track[curve.type] = curve return self
def read(self, stream, resources=None): s = StreamReader(stream) tag = s.chars(8) if not tag == '_pilC3S_': raise Exception("Not a valid _S3Clip_") self.version = s.u32() self.unknown1 = s.u32() self.frame_duration = s.f32() self.max_frame_count = s.u16() self.unknown2 = s.u16() cCurves = s.u32() cFloats = s.u32() curveOffset = StreamPtr.begin_read(s) frameOffset = StreamPtr.begin_read(s) nameOffset = StreamPtr.begin_read(s) srcNameOffset = StreamPtr.begin_read(s) curveOffset.end() curves = [] for curveIndex in range(cCurves): cdi = CurveDataInfo() cdi.read(stream) curves.append(cdi) nameOffset.end() self.name = s.zs() srcNameOffset.end() self.source_file_name = s.zs() frameOffset.end() indexedFloats = [] for floatIndex in range(cFloats): indexedFloats.append(s.f32()) trackMap = {} self.tracks = [] for curveIndex, cdi in enumerate(curves): cdi.frame_data_ptr.end() if cdi.track_key not in trackMap.keys(): t = Track(cdi.track_key) trackMap[cdi.track_key] = t self.tracks.append(t) track = trackMap[cdi.track_key] frames = [] for frameIndex in range(cdi.frame_count): f = Frame() f.read(stream, cdi, indexedFloats) frames.append(f) curve = Curve(cdi.type) curve.flags = cdi.flags curve.frames = frames track[curve.type] = curve return self
def read_property(self, stream, hash, tgi): s = StreamReader(stream) id = s.u32() value = None if not id: return False if not s.u8(): t = s.u8() if t == 0x00: value = bool(s.u8()) elif t == 0x01: value = s.i8() elif t == 0x02: value = s.i16() elif t == 0x03: value = s.i32() elif t == 0x04: value = s.i64() elif t == 0x05: value = s.u8() elif t == 0x06: value = s.u16() elif t == 0x07: value = s.u32() elif t == 0x08: value = s.u64() elif t == 0x09: value = s.f32() elif t == 0x0A: value = [s.f32() for i in range(4)] elif t == 0x0B: value = [s.f32() for i in range(4)] elif t == 0x0C: value = tgi.get_resource(s.u8()) elif t == 0x0D: value = s.p16() else: raise Exception("Unknown TXTC parameter type %s" % t) hash[id] = value return True
def load(self): if not self.stream: return s = StreamReader(self.stream) self.entries = [] self.header.read(self.stream) self.stream.seek(self.header.index_offset, SEEK_SET) self.index_flags = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE): self.static_key.t = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP): self.static_key.g = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI): self.static_key.i = s.u32() << 32 if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO): self.static_key.i |= s.u32() for i in range(self.header.index_entry_count): index = self.IndexEntry(self) index.key = ResourceKey() if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE): index.key.t = self.static_key.t else: index.key.t = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP): index.key.g = self.static_key.g else: index.key.g = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI): instance_hi = self.static_key.i >> 32 else: instance_hi = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO): instance_lo = self.static_key.i & 0xFFFFFFFF else: instance_lo = s.u32() index.key.i = (instance_hi << 32) + instance_lo index.offset = s.u32() index.file_size = s.u32() & 0x0FFFFFFF index.mem_size = s.u32() flag = s.u16() index.compressed = flag == 0xFFFF index.unknown = s.u16() self.entries.append(index) nmap = self.name_map for entry in self.entries: entry.name = nmap[entry.key.i] print("Done.")
def load(self): if not self.stream: return s = StreamReader(self.stream) self.entries = [] self.header.read(self.stream) self.stream.seek(self.header.index_offset, SEEK_SET) self.index_flags = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE): self.static_key.t = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP): self.static_key.g = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI): self.static_key.i = s.u32() <<32 if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO): self.static_key.i |= s.u32() for i in range(self.header.index_entry_count): index = self.IndexEntry(self) index.key = ResourceKey() if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE): index.key.t = self.static_key.t else: index.key.t = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP): index.key.g = self.static_key.g else: index.key.g = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI): instance_hi = self.static_key.i >> 32 else: instance_hi = s.u32() if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO): instance_lo = self.static_key.i & 0xFFFFFFFF else: instance_lo = s.u32() index.key.i = (instance_hi << 32) + instance_lo index.offset = s.u32() index.file_size = s.u32() & 0x0FFFFFFF index.mem_size = s.u32() flag = s.u16() index.compressed = flag == 0xFFFF index.unknown = s.u16() self.entries.append(index) nmap = self.name_map for entry in self.entries: entry.name =nmap[entry.key.i] print("Done.")
def read(self, stream, resource=None): s = StreamReader(stream) self.frame_data_ptr = StreamPtr.begin_read(s) self.track_key = s.u32() self.offset = s.f32() self.scale = s.f32() self.frame_count = s.u16() self.flags.read(stream) self.type = s.u8() return self
def read(self, stream, resources=None): s = StreamReader(stream) assert s.u16() == self.TAG self.id = s.u32() self.time_code = s.f32() self.unknown1 = s.f32() self.unknown2 = s.f32() self.unknown3 = s.u32() length = s.u32() self.name = s.zs() assert len(self.name) == length s.align()
def read(self, stream, resource=None): s = StreamReader(stream) assert s.chars(4) == self.TAG self.version = s.u32() cEvents = s.i32() length = s.u32() start_offset = s.u32() assert (start_offset == 4 and cEvents > 0) or (start_offset == 0 == cEvents) self.events = [] start = stream.tell() for event_index in range(cEvents): type = s.u16() event = Event.get_event_class(type)() event.read(stream) self.events.append(event) actual = stream.tell() - start
def read_rcol(self, stream, rcol): s = StreamReader(stream) self.read_tag(stream) self.version = s.u32() tgi = TGIList() tgi.begin_read(stream) self.shader = s.u32() if self.shader: end_material = s.u32() + stream.tell() self.material = MaterialBlock() self.material.read(stream, tgi) assert stream.tell() == end_material self.merge_group = s.u32() self.sort_order = s.u32() cVertices = s.u32() self.vertex_format.read(stream) for vertex_index in range(cVertices): vertex = Vertex() for declaration in self.vertex_format.declarations: if declaration.usage == self.VertexFormat.Declaration.USAGE.POSITION: vertex.position = [s.f32(), s.f32(), s.f32()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.NORMAL: vertex.normal = [s.f32(), s.f32(), s.f32()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.UV: uv = [s.f32(), s.f32()] if vertex.uv == None: vertex.uv = [] vertex.uv.append(uv) elif declaration.usage == self.VertexFormat.Declaration.USAGE.BLEND_INDEX: vertex.blend_indices = [s.i8(), s.i8(), s.i8(), s.i8()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.BLEND_WEIGHT: vertex.blend_weights = [s.f32(), s.f32(), s.f32(), s.f32()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.TANGENT: vertex.tangent = [s.f32(), s.f32(), s.f32()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.COLOUR: vertex.colour = [s.u8(), s.u8(), s.u8(), s.u8()] elif declaration.usage == self.VertexFormat.Declaration.USAGE.ID: vertex.id = s.u32() self.vertices.append(vertex) assert s.u32() == 1 bytes_per_index = s.u8() assert bytes_per_index == 2 self.indices = [[s.u16() for i in range(3)] for i in range(int(s.u32() / 3))] self.skin_controller = tgi.get_resource(s.u32()) self.bones = [s.u32() for i in range(s.u32())] tgi.end_read(stream)
def read_rcol(self, stream, rcol): self.read_tag(stream) s = StreamReader(stream) self.version = s.u32() num = s.u32() cLights = s.u8() cOccluders = s.u8() assert num == (4 + (cLights * 128) + (cOccluders * 14)) num2 = s.u16() assert num2 == (cOccluders * 14) self.lights = [] for light_index in range(cLights): start = stream.tell() light_type = s.u32() light = Light.get_type(light_type)() light.read_rcol(stream) stream.seek(start + 128, SEEK_SET) self.lights.append(light) self.occluders = [Occluder(stream) for i in range(cOccluders)]
class Buffer: def __init__(self): self.stream = BytesIO() self.reader = StreamReader(self.stream) self.writer = StreamWriter(self.stream) def delete_vertices(self, offset, vrtf, count): end_offset = offset + vrtf.stride * count self.stream.seek(end_offset, SEEK_SET) end_data = self.stream.read(-1) self.stream.seek(offset, SEEK_SET) self.stream.truncate() self.stream.writable(end_data) def read_vertices(self, offset, vrtf, count, uvscales): self.stream.seek(offset, SEEK_SET) return [self.read_vertex(vrtf, uvscales) for i in range(count)] def read_vertex(self, vrtf, uvscales): vertex = Vertex() start = self.stream.tell() end = start + vrtf.stride for declaration in vrtf.declarations: u = declaration.usage value = self.read_element(declaration, uvscales[declaration.usage_index]) if u == VertexFormat.USAGE.POSITION: vertex.position = value elif u == VertexFormat.USAGE.NORMAL: vertex.normal = value elif u == VertexFormat.USAGE.UV: if vertex.uv == None: vertex.uv = [] vertex.uv.append(value) elif u == VertexFormat.USAGE.BLEND_INDEX: vertex.blend_indices = value elif u == VertexFormat.USAGE.BLEND_WEIGHT: vertex.blend_weights = value elif u == VertexFormat.USAGE.COLOR: vertex.colour = value elif u == VertexFormat.USAGE.TANGENT: vertex.tangent = value else: raise Exception("Unknown usage %s", declaration.usage) actual = self.stream.tell() return vertex def write_vertices(self, vrtf, vertices, uvscales=None): self.stream.seek(0, SEEK_END) offset = self.stream.tell() for vertex in vertices: self.write_vertex(vrtf, vertex) def write_vertex(self, vrtf, v): for declaration in vrtf.declarations: u = declaration.usage if u == VertexFormat.USAGE.POSITION: data = v.position elif u == VertexFormat.USAGE.NORMAL: data = v.normal elif u == VertexFormat.USAGE.UV: data = v.uv[vrtf.usage_index] elif u == VertexFormat.USAGE.BLEND_INDEX: data = v.blend_indices elif u == VertexFormat.USAGE.BLEND_WEIGHT: data = v.blend_weights elif u == VertexFormat.USAGE.COLOR: data = v.colour elif u == VertexFormat.USAGE.TANGENT: data = v.tangents else: raise Exception('Unknown VRTF usage type %i' % u) self.write_element(declaration, data) def write_element(self, declaration, value): pass def read_element(self, declaration, uvscale): float_count = VertexFormat.FORMAT.float_count(declaration.format) value = [0.0] * float_count f = declaration.format u = declaration.usage if u == VertexFormat.USAGE.UV: if f == VertexFormat.FORMAT.SHORT2: for i in range(float_count): value[i] = self.reader.i16() * uvscale elif f == VertexFormat.FORMAT.SHORT4: shorts = [self.reader.i16() for i in range(4)] assert shorts[2] == 0 value = [ shorts[0] / 0x7FFF, shorts[1] / 0x7FFF, shorts[3] / 0x1FF ] elif f in (VertexFormat.FORMAT.FLOAT, VertexFormat.FORMAT.FLOAT2, VertexFormat.FORMAT.FLOAT3, VertexFormat.FORMAT.FLOAT4): for i in range(float_count): value[i] = self.reader.f32() elif f == VertexFormat.FORMAT.UBYTE4: for i in range(float_count): value[i] = self.reader.i8() elif f == VertexFormat.FORMAT.COLOR_UBYTE4: if u == VertexFormat.USAGE.COLOR: for i in range(float_count): value[i] = self.reader.u8() / 0xFF elif u == VertexFormat.USAGE.BLEND_WEIGHT: for i in range(float_count): value[VertexFormat.FORMAT. UBYTE_MAP[i]] = self.reader.u8() / 0xFF elif u in (VertexFormat.USAGE.NORMAL, VertexFormat.USAGE.TANGENT): bytes = [self.reader.u8() for i in range(4)] for i in range(float_count - 1): value[i] = -1 if bytes[2 - i] == 0 else (( (bytes[2 - i] + 1) / 128.0) - 1) determinant = 0.0 if not bytes[3]: determinant = -1.0 elif bytes[3] == 127.0: determinant = 0.0 elif bytes[3] == 255.0: determinant = 1.0 else: print("Unexpected handedness %i " % bytes[3]) value[float_count - 1] = determinant else: raise Exception("Unhandled usage %s for format %s" % (u, f)) elif f == VertexFormat.FORMAT.SHORT2: for i in range(float_count): value[i] = self.reader.i16() / 0xFFFF elif f == VertexFormat.FORMAT.SHORT4: shorts = [self.reader.i16() for i in range(3)] scalar = self.reader.u16() if not scalar: scalar = 0x7FFF for i in range(float_count): value[i] = float(shorts[i]) / float(scalar) elif f == VertexFormat.FORMAT.USHORT4N: shorts = [self.reader.i16() for i in range(3)] scalar = self.reader.u16() if not scalar: scalar = 511 for i in range(float_count): value[i] = shorts[i] / scalar elif f == VertexFormat.FORMAT.UBYTE4: data = [self.reader.i8() for i in range(4)] else: raise Exception("Unhandled format %s" % f) return value def __del__(self): if self.stream != None: self.stream.close()
def read(self, stream, rcol): RCOLChunk.read(self, stream, rcol) s = StreamReader(stream) self.sg.read(stream, rcol) data_length = s.u32() self.time = s.u16() count_modifiers = s.u16() count_p7 = s.u16() obj_mod_len = s.u8() self.anim_version = s.u8() self.anim_type = s.u8() unknown1 = s.u8() self.locomotion_type = s.u8() obj_name_len = s.u8() self.read_foosball(stream, 4) self.initial_direction = s.f32() self.locomotion_magnitude = s.f32() self.locomotion_scale = s.f32() unknown2 = s.f32() self.unknown3 = s.f32() self.unknown4 = s.f32() self.final_direction = s.f32() self.skeleton_scale = s.f32() self.height = s.f32() self.object_name = s.zs() self.object_modifier_string = s.zs() self.fix_read_offset(stream) self.actors = [] #P1:Object for i in range(count_modifiers): self.read_foosball(stream, 2) actor = self.Actor() actor.unknown1 = s.u16() actor.tracks = [0] * s.u16() part_4_count = s.u16() actor.frames = [0] * (part_4_count & 0x3F) actor.frame_flags = part_4_count & 0xC0 object_name_len = s.u16() self.read_foosball(stream, 3) self.actors.append(actor) for actor in self.actors: actor.name = s.zs() # name_lookup = {} # for name in blend_object_names: # name_lookup[crc32(bytes(name,encoding='ascii'))]=name self.fix_read_offset(stream) for actor in self.actors: for i in range(len(actor.tracks)): self.read_foosball(stream, 2) crc = s.u32() self.read_foosball(stream) unknown5 = s.u32() t = (unknown5 & 0x00F00000) >> 20 # highest 3 bits count_movements = (unknown5 >> 0x1D) & 0x7 self.read_foosball(stream) track = self.Track() track.hash = crc track.duration = 0 track.type = t track.frames = [self.Frame()] * count_movements actor.tracks[i] = track for actor in self.actors: for track in actor.tracks: track.name = s.zs() self.fix_read_offset(stream) #P3:Movements for actor in self.actors: for track_index, track in enumerate(actor.tracks): for i in range(len(track.frames)): f = self.Frame() f.u1 = s.u16() f.u2 = s.u16() track.frames[i] = f self.read_foosball(stream) self.fix_read_offset(stream) #P4:Transforms for actor in self.actors: for track_index, track in enumerate(actor.tracks): for frame_index, frame in enumerate(track.frames): u1 = frame.u1 u2 = frame.u2 dum = u1 >> 0x10 count = u1 & 0x0F t = dum & 3 if t == 0: size = 1 elif t == 1: size = 3 else: size = 4 total = count * size for i in range(t): data = [] for j in range(size): data.append(self.unpack_float(stream)) frame.data.append(data) pass pass pass
class Buffer: def __init__(self): self.stream = BytesIO() self.reader = StreamReader(self.stream) self.writer = StreamWriter(self.stream) def delete_vertices(self, offset, vrtf, count): end_offset = offset + vrtf.stride * count self.stream.seek(end_offset, SEEK_SET) end_data = self.stream.read(-1) self.stream.seek(offset, SEEK_SET) self.stream.truncate() self.stream.writable(end_data) def read_vertices(self, offset, vrtf, count,uvscales): self.stream.seek(offset, SEEK_SET) return [self.read_vertex(vrtf,uvscales) for i in range(count)] def read_vertex(self, vrtf, uvscales): vertex = Vertex() start = self.stream.tell() end = start + vrtf.stride for declaration in vrtf.declarations: u = declaration.usage value = self.read_element(declaration,uvscales[declaration.usage_index]) if u == VertexFormat.USAGE.POSITION: vertex.position = value elif u == VertexFormat.USAGE.NORMAL: vertex.normal = value elif u == VertexFormat.USAGE.UV: if vertex.uv == None: vertex.uv = [] vertex.uv.append(value) elif u == VertexFormat.USAGE.BLEND_INDEX: vertex.blend_indices = value elif u == VertexFormat.USAGE.BLEND_WEIGHT: vertex.blend_weights = value elif u == VertexFormat.USAGE.COLOR: vertex.colour = value elif u == VertexFormat.USAGE.TANGENT: vertex.tangent = value else: raise Exception("Unknown usage %s", declaration.usage) actual = self.stream.tell() return vertex def write_vertices(self, vrtf, vertices, uvscales=None): self.stream.seek(0, SEEK_END) offset = self.stream.tell() for vertex in vertices: self.write_vertex(vrtf, vertex) def write_vertex(self, vrtf, v): for declaration in vrtf.declarations: u = declaration.usage if u == VertexFormat.USAGE.POSITION: data = v.position elif u == VertexFormat.USAGE.NORMAL: data = v.normal elif u == VertexFormat.USAGE.UV: data = v.uv[vrtf.usage_index] elif u == VertexFormat.USAGE.BLEND_INDEX: data = v.blend_indices elif u == VertexFormat.USAGE.BLEND_WEIGHT: data = v.blend_weights elif u == VertexFormat.USAGE.COLOR: data = v.colour elif u == VertexFormat.USAGE.TANGENT: data = v.tangents else: raise Exception('Unknown VRTF usage type %i' % u) self.write_element(declaration, data) def write_element(self, declaration, value): pass def read_element(self, declaration, uvscale): float_count = VertexFormat.FORMAT.float_count(declaration.format) value = [0.0] * float_count f = declaration.format u = declaration.usage if u == VertexFormat.USAGE.UV: if f == VertexFormat.FORMAT.SHORT2: for i in range(float_count): value[i] = self.reader.i16() * uvscale elif f == VertexFormat.FORMAT.SHORT4: shorts = [self.reader.i16() for i in range(4)] assert shorts[2] == 0 value = [shorts[0] /0x7FFF, shorts[1]/0x7FFF, shorts[3] /0x1FF] elif f in (VertexFormat.FORMAT.FLOAT, VertexFormat.FORMAT.FLOAT2, VertexFormat.FORMAT.FLOAT3, VertexFormat.FORMAT.FLOAT4): for i in range(float_count): value[i] = self.reader.f32() elif f == VertexFormat.FORMAT.UBYTE4: for i in range(float_count): value[i] = self.reader.i8() elif f == VertexFormat.FORMAT.COLOR_UBYTE4: if u == VertexFormat.USAGE.COLOR: for i in range(float_count): value[i] = self.reader.u8() / 0xFF elif u == VertexFormat.USAGE.BLEND_WEIGHT: for i in range(float_count): value[VertexFormat.FORMAT.UBYTE_MAP[i]] = self.reader.u8() / 0xFF elif u in (VertexFormat.USAGE.NORMAL, VertexFormat.USAGE.TANGENT): bytes = [self.reader.u8() for i in range(4)] for i in range(float_count - 1): value[i] = -1 if bytes[2 - i] == 0 else ( ((bytes[2 - i] + 1) / 128.0) - 1) determinant = 0.0 if not bytes[3]: determinant = -1.0 elif bytes[3] == 127.0: determinant = 0.0 elif bytes[3] == 255.0: determinant = 1.0 else: print("Unexpected handedness %i " % bytes[3]) value[float_count - 1] = determinant else: raise Exception("Unhandled usage %s for format %s" % (u, f)) elif f == VertexFormat.FORMAT.SHORT2: for i in range(float_count): value[i] = self.reader.i16() / 0xFFFF elif f == VertexFormat.FORMAT.SHORT4: shorts = [self.reader.i16() for i in range(3)] scalar = self.reader.u16() if not scalar: scalar = 0x7FFF for i in range(float_count): value[i] = float(shorts[i]) / float(scalar) elif f == VertexFormat.FORMAT.USHORT4N: shorts = [self.reader.i16() for i in range(3)] scalar = self.reader.u16() if not scalar: scalar = 511 for i in range(float_count): value[i] = shorts[i] / scalar elif f == VertexFormat.FORMAT.UBYTE4: data = [self.reader.i8() for i in range(4)] else: raise Exception("Unhandled format %s" % f) return value def __del__(self): if self.stream != None: self.stream.close()