Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from struct import pack, unpack
- from math import sqrt
- def from_file(file_path):
- return TER().from_file(file_path)
- class TER:
- def __init__(self, tiles = None):
- self.chunks = []
- # Highest and lowest height points
- self.high = -32767
- self.low = 32767
- if tiles:
- self.blank(tiles)
- def __str__(self):
- return "TER tiles=%d verts=%d" % (len(self.chunks), len(self.chunks)*16)
- def blank(self, tiles):
- self.chunks = []
- for chunk in range(tiles):
- self.chunks += [Chunk()]
- def get_height_range(self):
- for chunk in self.chunks:
- for h in chunk.h:
- self.low = min(self.low, h)
- self.high = max(self.high, h)
- return self.low, self.high
- def from_file(self, file_path):
- with open(file_path, "rb") as fl:
- # [Header:16 Bytes]
- magic_number = fl.read(4)
- version = unpack("i", fl.read(4))[0]
- if magic_number != b"TERR" or version != 3:
- raise Exception("Invalid TER file.")
- # Width(inverted), Height(inverted), Width, Height
- size = unpack("HHHH", fl.read(8))
- ter_chunks = (size[2]//2)*(size[3]//2)
- # [Chunks:164] Total: (ter_chuks)
- for chunk_id in range(ter_chunks):
- height = list(unpack("h"*16, fl.read(32)))
- normal = list(unpack("B"*16, fl.read(16)))
- color = []
- c_data = unpack("B"*48, fl.read(48))
- for i in range(len(c_data)//3):
- color += [[c_data[i*3], c_data[i*3+1], c_data[i*3+2]]]
- alpha1 = list(unpack("B"*16, fl.read(16)))
- alpha2 = list(unpack("B"*16, fl.read(16)))
- alpha3 = list(unpack("B"*16, fl.read(16)))
- fl.seek(16, 1) # Unused junk info about pathing
- textures = unpack("H", fl.read(2))[0]
- tex0 = textures & 0x000F
- tex1 = (textures >> 4) & 0x000F
- tex2 = (textures >> 8) & 0x000F
- tex3 = (textures >> 12) & 0x000F
- fl.seek(2, 1)
- alpha = [alpha1, alpha2, alpha3]
- textures = [tex0, tex1, tex2, tex3]
- self.chunks += [Chunk(height, normal, color, alpha, textures)]
- return self
- def to_file(self, file_path):
- with open(file_path, "wb") as fl:
- fl.write(b"TERR")
- fl.write(pack("i", 3))
- size = int(sqrt(len(self.chunks)))
- fl.write(pack("HHHH", 0x10000-size*2, 0x10000-size*2, size*2, size*2))
- for chunk in self.chunks:
- fl.write(chunk.pack())
- class Chunk:
- def __init__(self,
- height = None,
- normal = None,
- rgb = None,
- alpha = None,
- textures = None):
- if height is None:
- height = [0 for i in range(16)]
- if normal is None:
- normal = [0 for i in range(16)]
- if rgb is None:
- rgb = [[255 for i in range(3)] for i in range(16)]
- if alpha is None:
- alpha = [[0 for i in range(16)] for i in range(3)]
- if textures is None:
- textures = [0, 1, 2, 3]
- self.h = height
- self.n = normal
- self.c = rgb
- self.a = alpha
- self.t = textures
- self.data = None
- def pack(self, normals = True):
- """Pack data and return as bytes."""
- data = bytearray(164)
- data[0:32] = pack("h"*16, *self.h)
- if normals:
- data[32:48] = pack("B"*16, *self.n)
- for color, c in enumerate(self.c):
- i = color*3
- data[48+i:96+i] = pack("B"*3, *c)
- texint = self.t[0]
- texint |= self.t[1] << 4
- texint |= self.t[2] << 8
- texint |= self.t[3] << 12
- data[96:112] = pack("B"*16, *self.a[0])
- data[112:128] = pack("B"*16, *self.a[1])
- data[128:144] = pack("B"*16, *self.a[2])
- data[144:160] = b"\x00"*16
- data[160:162] = pack("H", texint)
- data[162:164] = b"\x00\x00" # Struct padding
- return data
- if __name__ == "__main__":
- file = "./Subject.TER"
- ter = TER().from_file(file)
- print(ter)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement