From 78440cce1602ae81625a915aa89cfe0b2b33c9e7 Mon Sep 17 00:00:00 2001 From: Roz K Date: Tue, 3 Jan 2023 13:02:22 +0100 Subject: [PATCH] Bump engine submodule and rework resouces. --- engine | 2 +- game/batch.py | 6 ++-- game/game.py | 62 +++++++++++++++++++------------------ game/obj2rkar.py | 14 ++++----- game/resources.py | 78 ++++++++++++++++++----------------------------- game/vertices.py | 4 +-- 6 files changed, 74 insertions(+), 92 deletions(-) diff --git a/engine b/engine index baac333..d0741af 160000 --- a/engine +++ b/engine @@ -1 +1 @@ -Subproject commit baac333b44118e17e46f85fc8637aa5ff7f519fc +Subproject commit d0741afda706be3a7daa7ef0efd6559eb1824c3a diff --git a/game/batch.py b/game/batch.py index 527d7a2..f8e3d50 100644 --- a/game/batch.py +++ b/game/batch.py @@ -26,13 +26,13 @@ class Batch: __slots__ = ('_batch', 'vertices', 'max_size', 'size', 'flags', '_flags', 'mesh', '_meshes', 'param', '_params', '_name', '__dict__') - def __init__(self, vertices, max_size, max_meshes, **params_decls): + def __init__(self, vertices, max_size, **params_decls): assert max_size <= BATCH_MAX_SIZE nparams = len(params_decls) if nparams: - self._batch = create_batch(vertices._vertices, max_size, max_meshes, params_format(*params_decls.values())) + self._batch = create_batch(vertices._vertices, max_size, params_format(*params_decls.values())) else: - self._batch = create_batch(vertices._vertices, max_size, max_meshes, None) + self._batch = create_batch(vertices._vertices, max_size, None) self.vertices = vertices self.max_size = max_size self.size = 0 diff --git a/game/game.py b/game/game.py index 82a1e2a..37ea92e 100644 --- a/game/game.py +++ b/game/game.py @@ -75,8 +75,10 @@ class PerfGroup(Group): class TestEntity(Entity): __slots__ = 'translation', 'orientation', 'spawn_translation', 'spawn_orientation' - def __init__(self, batch, model, translation, orientation): - Entity.__init__(self, batch, model.flags, model.mesh, translation = translation, orientation = orientation) + def __init__(self, batch, mesh, translation, orientation): + Entity.__init__(self, batch, INSTANCE_FLAG_VISIBLE, mesh, + translation = translation, + orientation = orientation) self.translation = batch.translation[self.index] self.orientation = batch.orientation[self.index] self.spawn_translation = translation @@ -126,15 +128,16 @@ def create_scene(keyboard, mouse): print("Building tiles...") tiles_texture = Texture(*archive.get_texture('tiles')) - tiles_vertices = Vertices(*archive.get_vertices('tiles')) - water_model = archive.get_model('water') - sand_model = archive.get_model('sand') - grass_model = archive.get_model('grass') - forest_model = archive.get_model('forest') - rock_model = archive.get_model('rock') - mud_model = archive.get_model('mud') - lava_model = archive.get_model('lava') - tiles_batch = Batch(tiles_vertices, generated.size ** 2, 8, translation = PARAM_FORMAT_VEC3_SHORT) + tiles_vertices_data = archive.get_vertices('tiles') + tiles_vertices = Vertices(*tiles_vertices_data) + water_mesh = tiles_vertices_data.get_mesh('water') + sand_mesh = tiles_vertices_data.get_mesh('sand') + grass_mesh = tiles_vertices_data.get_mesh('grass') + forest_mesh = tiles_vertices_data.get_mesh('forest') + rock_mesh = tiles_vertices_data.get_mesh('rock') + mud_mesh = tiles_vertices_data.get_mesh('mud') + lava_mesh = tiles_vertices_data.get_mesh('lava') + tiles_batch = Batch(tiles_vertices, generated.size ** 2, translation = PARAM_FORMAT_VEC3_SHORT) #TODO: generator & for real vc = generated.volcano_c @@ -146,44 +149,45 @@ def create_scene(keyboard, mouse): if h == 0.0: continue if r > 0.0: - model = water_model + mesh = water_mesh elif h < 2.0: - model = sand_model + mesh = sand_mesh elif h < 180: if nz > 0.9: if ny < -0.01 and nz > 0.93: - model = forest_model + mesh = forest_mesh else: - model = grass_model + mesh = grass_mesh else: - model = rock_model + mesh = rock_mesh elif vd < vr - 3.0 and nz > 0.999: - model = lava_model + mesh = lava_mesh elif vd < vr + 2.0: - model = mud_model + mesh = mud_mesh elif vd < vr + 6.0 and nz < 0.67: - model = mud_model + mesh = mud_mesh else: - model = rock_model - tiles_batch.spawn(model.flags, model.mesh, + mesh = rock_mesh + tiles_batch.spawn(INSTANCE_FLAG_VISIBLE, mesh, translation = vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0)) tiles_batch.fill() tiles_batch.freeze(flags = True, mesh = True, translation = True) tests_texture = Texture(*archive.get_texture('tests')) - tests_vertices = Vertices(*archive.get_vertices('tests')) - blob_model = archive.get_model('blob') - cube_model = archive.get_model('cube') - clouds_model = archive.get_model('clouds') - tests_batch = Batch(tests_vertices, 3, 3, + tests_vertices_data = archive.get_vertices('tests') + tests_vertices = Vertices(*tests_vertices_data) + blob_mesh = tests_vertices_data.get_mesh('blob') + cube_mesh = tests_vertices_data.get_mesh('cube') + clouds_mesh = tests_vertices_data.get_mesh('clouds') + tests_batch = Batch(tests_vertices, 3, translation = PARAM_FORMAT_VEC3_FLOAT, orientation = PARAM_FORMAT_MAT3_INT10 | PARAM_FORMAT_NORMALIZE) blob_forward = math.vec3_normalize((sun_direction[0], sun_direction[1], 0.0)) blob_right = math.vec3_cross(blob_forward, math.vec3_up) blob_orientation = mat3(vec3(*blob_right), vec3(*blob_forward), vec3_up) - blob = TestEntity(tests_batch, blob_model, translation = vec3(-100.0, -500.0, 0.0), orientation = blob_orientation) - cube = TestEntity(tests_batch, cube_model, translation = vec3(100.0, -500.0, 0.0), orientation = mat3_identity) - clouds = TestEntity(tests_batch, clouds_model, translation = vec3(0.0, 0.0, 32.0), orientation = mat3_identity) + blob = TestEntity(tests_batch, blob_mesh, translation = vec3(-100.0, -500.0, 0.0), orientation = blob_orientation) + cube = TestEntity(tests_batch, cube_mesh, translation = vec3(100.0, -500.0, 0.0), orientation = mat3_identity) + clouds = TestEntity(tests_batch, clouds_mesh, translation = vec3(0.0, 0.0, 32.0), orientation = mat3_identity) tests_batch.fill() tests_batch.freeze(flags = True, mesh = True) diff --git a/game/obj2rkar.py b/game/obj2rkar.py index 1d5ddaa..e95798f 100644 --- a/game/obj2rkar.py +++ b/game/obj2rkar.py @@ -22,7 +22,7 @@ from itertools import starmap, chain, repeat from engine import * from game.math import float_s8, vec3_srgb8a8 -from game.resources import load_png, TextureData, VerticesData, ModelData, Archive +from game.resources import load_png, TextureData, VerticesData, Archive _texture_flags = TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_NEAREST @@ -226,15 +226,13 @@ class ObjArchive(Archive): n = (pack_10(_nz) << 20) | (pack_10(_ny) << 10) | pack_10(_nx) t = ((_tl & 1023) << 20) | (pack_u10(_t) << 10) | pack_u10(_s) return struct.pack('fffII', _px, _py, _pz, n, t) + meshes = {} + for mesh_name, (offset, count) in sorted(models.items()): + meshes[mesh_name] = offset | (count << 16) self.vertices_db[name] = VerticesData(name, array('B', b''.join(starmap(pack_vertex, vertices))), - array('H', indices)) - for name, (offset, count) in sorted(models.items()): - if name[0] != '_': - print("Storing", name) - assert name not in self.models_db.keys() - self.models_db[name] = ModelData( - name, INSTANCE_FLAG_VISIBLE, offset | count << 16) + array('H', indices), + meshes) if __name__ == '__main__': if len(sys.argv) < 3: diff --git a/game/resources.py b/game/resources.py index 28c9dea..073d700 100644 --- a/game/resources.py +++ b/game/resources.py @@ -48,7 +48,7 @@ def _read_struct(file, format): _read_magic(file, b'RK') return struct.unpack(format, data) -def _write_struct(file, format, elems): +def _write_struct(file, format, *elems): assert format data = struct.pack(format, *elems) size = file.write(data) @@ -56,7 +56,7 @@ def _write_struct(file, format, elems): _write_magic(file, b'RK') def _read_string(file): - length, = _read_struct(file, 'B') + length, = _read_struct(file, 'I') assert length data = file.read(length) assert len(data) == length @@ -66,7 +66,7 @@ def _read_string(file): def _write_string(file, string): data = bytes(string, encoding='ascii') assert data and len(data) < 256 - _write_struct(file, 'B', (len(data),)) + _write_struct(file, 'I', len(data)) size = file.write(data) assert size == len(data) _write_magic(file, b'RK') @@ -96,7 +96,7 @@ def _read_blob(file): def _write_blob(file, array): assert array - _write_struct(file, 'II', (ord(array.typecode), len(array))) + _write_struct(file, 'II', ord(array.typecode), len(array)) array.tofile(file) _write_magic(file, b'RK') @@ -124,7 +124,7 @@ class TextureData: @classmethod def from_archive(cls, file): - _read_magic(file, b'TX') + _read_magic(file, b'TXTR') name = _read_string(file) format, width, height, nlevels, flags = _read_struct(file, 'IIIII') pixels = _read_blob(file) @@ -133,70 +133,59 @@ class TextureData: return cls(name, format, width, height, nlevels, flags, pixels) def to_archive(self, file): - _write_magic(file, b'TX') + _write_magic(file, b'TXTR') _write_string(file, self.name) - _write_struct(file, 'IIIII', (self.format, self.width, self.height, self.nlevels, self.flags)) + _write_struct(file, 'IIIII', self.format, self.width, self.height, self.nlevels, self.flags) _write_blob(file, self.pixels) class VerticesData: - __slots__ = 'name', 'vertices', 'indices' + __slots__ = 'name', 'vertices', 'indices', 'meshes' - def __init__(self, name, vertices, indices): + def __init__(self, name, vertices, indices, meshes): if len(vertices) % VERTEX_SIZE != 0: raise RuntimeError("Vertex format mismatch!") self.name = name self.vertices = vertices self.indices = indices + self.meshes = meshes def __iter__(self): yield VERTEX_FORMAT yield len(self.vertices) // VERTEX_SIZE yield self.vertices yield self.indices + yield array('I', self.meshes.values()) + + def get_mesh(self, name): + return self.meshes[name] @classmethod def from_archive(cls, file): - _read_magic(file, b'VT') + _read_magic(file, b'VERT') name = _read_string(file) - nvertices, nindices = _read_struct(file, 'II') + nvertices, nindices, nmeshes = _read_struct(file, 'III') vertices = _read_array(file, 'B', nvertices * VERTEX_SIZE) indices = _read_array(file, 'H', nindices) - return cls(name, vertices, indices) + meshes = _read_array(file, 'I', nmeshes) + names = [_read_string(file) for _ in range(nmeshes)] + return cls(name, vertices, indices, dict(zip(names, meshes))) def to_archive(self, file): - _write_magic(file, b'VT') + _write_magic(file, b'VERT') _write_string(file, self.name) - _write_struct(file, 'II', (len(self.vertices) // VERTEX_SIZE, len(self.indices))) + _write_struct(file, 'III', len(self.vertices) // VERTEX_SIZE, len(self.indices), len(self.meshes)) _write_array(file, self.vertices) _write_array(file, self.indices) - -class ModelData: - __slots__ = 'name', 'flags', 'mesh' - - def __init__(self, name, flags, mesh): - self.name = name - self.flags = flags - self.mesh = mesh - - @classmethod - def from_archive(cls, file): - _read_magic(file, b'MD') - name = _read_string(file) - flags, mesh = _read_struct(file, 'II') - return ModelData(name, flags, mesh) - - def to_archive(self, file): - _write_magic(file, b'MD') - _write_string(file, self.name) - _write_struct(file, 'II', (self.flags, self.mesh)) + _write_array(file, array('I', self.meshes.values())) + for name in self.meshes.keys(): + _write_string(file, name) class Archive: - __slots__ = 'textures_db', 'vertices_db', 'models_db' + __slots__ = 'textures_db', 'vertices_db' - def __init__(self, textures_db = None, vertices_db = None, models_db = None): + def __init__(self, textures_db = None, vertices_db = None): self.textures_db = textures_db or {} self.vertices_db = vertices_db or {} - self.models_db = models_db or {} def get_texture(self, name): return self.textures_db[name] @@ -204,36 +193,27 @@ class Archive: def get_vertices(self, name): return self.vertices_db[name] - def get_model(self, name): - return self.models_db[name] - @classmethod def from_archive(cls, file): textures_db = {} vertices_db = {} - models_db = {} _read_magic(file, b'RKAR') - ntextures, nvertices, nmodels = _read_struct(file, 'III') + ntextures, nvertices = _read_struct(file, 'II') for _ in range(ntextures): data = TextureData.from_archive(file) textures_db[data.name] = data for _ in range(nvertices): data = VerticesData.from_archive(file) vertices_db[data.name] = data - for _ in range(nmodels): - data = ModelData.from_archive(file) - models_db[data.name] = data - return cls(textures_db, vertices_db, models_db) + return cls(textures_db, vertices_db) def to_archive(self, file): _write_magic(file, b'RKAR') - _write_struct(file, 'III', (len(self.textures_db), len(self.vertices_db), len(self.models_db))) + _write_struct(file, 'II', len(self.textures_db), len(self.vertices_db)) for _, data in self.textures_db.items(): data.to_archive(file) for _, data in self.vertices_db.items(): data.to_archive(file) - for _, data in self.models_db.items(): - data.to_archive(file) @classmethod def load(cls, filename): diff --git a/game/vertices.py b/game/vertices.py index 2ceaae9..c399567 100644 --- a/game/vertices.py +++ b/game/vertices.py @@ -18,8 +18,8 @@ from engine import create_vertices, destroy_vertices class Vertices: __slots__ = '_vertices' - def __init__(self, format, nvertices, vertices, indices): - self._vertices = create_vertices(format, nvertices, vertices, indices) + def __init__(self, format, nvertices, vertices, indices, meshes): + self._vertices = create_vertices(format, nvertices, vertices, indices, meshes) def __del__(self): destroy_vertices(self._vertices)