diff --git a/game/batch.py b/game/batch.py index 9912c55..b06b0ab 100644 --- a/game/batch.py +++ b/game/batch.py @@ -19,14 +19,15 @@ from engine import (vec3, mat3, buffer, INSTANCE_FLAG_SPAWNED, BATCH_MAX_SIZE, param_type, params_format, create_batch, draw_batch, destroy_batch) class Batch: - __slots__ = '_batch', 'size', 'max_size', 'flags', 'meshes', 'params', '_params', '__dict__' + __slots__ = '_batch', 'vertices', 'size', 'max_size', 'flags', 'meshes', 'params', '_params', '__dict__' def __init__(self, vertices, max_size, max_meshes, **params_decls): assert max_size <= BATCH_MAX_SIZE nparams = len(params_decls) names = params_decls.keys() formats = params_decls.values() - self._batch = create_batch(vertices, max_size, max_meshes, params_format(*formats)) + self._batch = create_batch(vertices._vertices, max_size, max_meshes, params_format(*formats)) + self.vertices = vertices self.size = 0 self.max_size = max_size self.flags = buffer(c_ubyte, max_size) diff --git a/game/game.py b/game/game.py index e77834d..1f3c1fd 100644 --- a/game/game.py +++ b/game/game.py @@ -23,9 +23,10 @@ from game.events import Events from game.mouse import Mouse from game.keyboard import Keyboard from game.generator import Generator -from game.resources import RuntimeArchive +from game.resources import Archive from game.texture import Texture from game.shader import Shader +from game.vertices import Vertices from game.camera import Camera from game.environment import Environment from game.inputs import InputFloat @@ -60,14 +61,7 @@ def update_sea(time, camera, sea_phase): camera.to_km() sea_phase.update((time.current * 0.023) % 1.0) -def main(): - print("Initializing...") - display = create_display(b'RK Island - Drag to rotate, wheel to zoom, q to quit', 1600, 900) - events = Events(display) - mouse = Mouse(events, wheel = 60, wheel_min = 20) - keyboard = Keyboard(events) - render_initialize(__debug__) - +def create_scene(keyboard, mouse): tiles_shader = Shader('tiles', 'common') tests_shader = Shader('tests', 'common') sea_shader = Shader('sea') @@ -88,11 +82,11 @@ def main(): generated.packed_normals) print("Loading resources...") - archive = RuntimeArchive.load('data/rk_island.rkar') + archive = Archive.load('data/rk_island.rkar') print("Building tiles...") - tiles_texture = archive.get_texture('tiles') - tiles_vertices = archive.get_vertices('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') @@ -133,8 +127,8 @@ def main(): model = rock_model model.spawn(tiles_batch, vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0)) - tests_texture = archive.get_texture('tests') - tests_vertices = archive.get_vertices('tests') + 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') @@ -159,7 +153,7 @@ def main(): sea_detail_texture = sea.load_detail_texture('data/sea_bump.png') sea_triangles = sea.sea_triangles(64, proj_far_z - 0.1, proj_ratio) - scene = SceneNode( + return SceneNode( FuncNode(update_camera, (mouse, camera, environment)), TextureNode((tiles_texture, heightmap, normalmap), ShaderNode(tiles_shader, @@ -187,31 +181,29 @@ def main(): ) ) +def loop(display): + events = Events(display) + keyboard = Keyboard(events) + mouse = Mouse(events, wheel = 60, wheel_min = 20) + scene = create_scene(keyboard, mouse) print("Running... Ctrl+c to quit") time = Time() try: while not keyboard.quit: events.update() - begin_frame() time.update() + begin_frame() scene.draw(time) end_frame() swap_buffers(display) except KeyboardInterrupt: pass +def main(): + print("Initializing...") + display = create_display(b'RK Island - Drag to rotate, wheel to zoom, q to quit', 1600, 900) + render_initialize(__debug__) + loop(display) print("Quitting...") - del tests_batch - del tiles_batch - del sea_triangles - del sea_polar_textures - del sea_detail_texture - del heightmap - del normalmap - archive.destroy() - del tiles_shader - del tests_shader - del sea_shader render_terminate() - del events destroy_display(display) diff --git a/game/resources.py b/game/resources.py index 98848f6..8d92bf6 100644 --- a/game/resources.py +++ b/game/resources.py @@ -16,11 +16,8 @@ import struct from array import array from pathlib import Path - import png - import engine -from game.texture import Texture VERTEX_SIZE = 20 VERTEX_FORMAT = engine.vertex_format( @@ -117,6 +114,14 @@ class TextureData: self.flags = flags self.pixels = pixels + def __iter__(self): + yield self.format + yield self.width + yield self.height + yield self.nlevels + yield self.flags + yield self.pixels + @classmethod def from_archive(cls, file): _read_magic(file, b'TX') @@ -133,9 +138,6 @@ class TextureData: _write_struct(file, 'IIIII', (self.format, self.width, self.height, self.nlevels, self.flags)) _write_blob(file, self.pixels) -def create_texture(data): - return Texture(data.format, data.width, data.height, data.nlevels, data.flags, data.pixels) - class VerticesData: __slots__ = 'name', 'vertices', 'indices' @@ -146,6 +148,12 @@ class VerticesData: self.vertices = vertices self.indices = indices + def __iter__(self): + yield VERTEX_FORMAT + yield len(self.vertices) // VERTEX_SIZE + yield self.vertices + yield self.indices + @classmethod def from_archive(cls, file): _read_magic(file, b'VT') @@ -162,9 +170,6 @@ class VerticesData: _write_array(file, self.vertices) _write_array(file, self.indices) -def create_vertices(data): - return engine.create_vertices(VERTEX_FORMAT, len(data.vertices) // VERTEX_SIZE, data.vertices, data.indices) - class ModelData: __slots__ = 'name', 'flags', 'mesh' @@ -185,19 +190,9 @@ class ModelData: _write_string(file, self.name) _write_struct(file, 'II', (self.flags, self.mesh)) -class Model: - __slots__ = 'flags', 'mesh' - - def __init__(self, flags, mesh): - self.flags = flags - self.mesh = mesh - def spawn(self, batch, *params): return batch.append(self.flags, self.mesh, params) -def create_model(data): - return Model(data.flags, data.mesh) - class Archive: __slots__ = 'textures_db', 'vertices_db', 'models_db' @@ -206,13 +201,6 @@ class Archive: self.vertices_db = vertices_db or {} self.models_db = models_db or {} - def destroy(self): - for vertices in self.vertices_db.values(): - engine.destroy_vertices(vertices) - self.textures_db.clear() - self.vertices_db.clear() - self.models_db.clear() - def get_texture(self, name): return self.textures_db[name] @@ -222,18 +210,6 @@ class Archive: def get_model(self, name): return self.models_db[name] - @classmethod - def _new_texture(cls, data): - return data - - @classmethod - def _new_vertices(cls, data): - return data - - @classmethod - def _new_model(cls, data): - return data - @classmethod def from_archive(cls, file): textures_db = {} @@ -243,22 +219,15 @@ class Archive: ntextures, nvertices, nmodels = _read_struct(file, 'III') for _ in range(ntextures): data = TextureData.from_archive(file) - textures_db[data.name] = cls._new_texture(data) + textures_db[data.name] = data for _ in range(nvertices): data = VerticesData.from_archive(file) - vertices_db[data.name] = cls._new_vertices(data) + vertices_db[data.name] = data for _ in range(nmodels): data = ModelData.from_archive(file) - models_db[data.name] = cls._new_model(data) + models_db[data.name] = data return cls(textures_db, vertices_db, models_db) - @classmethod - def load(cls, filename): - file = open(Path(filename), 'rb') - archive = cls.from_archive(file) - file.close() - return archive - 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))) @@ -269,20 +238,14 @@ class Archive: for _, data in self.models_db.items(): data.to_archive(file) + @classmethod + def load(cls, filename): + file = open(Path(filename), 'rb') + archive = cls.from_archive(file) + file.close() + return archive + def save(self, filename): file = open(Path(filename), 'wb') self.to_archive(file) file.close() - -class RuntimeArchive(Archive): - @classmethod - def _new_texture(cls, data): - return create_texture(data) - - @classmethod - def _new_vertices(cls, data): - return create_vertices(data) - - @classmethod - def _new_model(cls, data): - return create_model(data) diff --git a/game/vertices.py b/game/vertices.py new file mode 100644 index 0000000..2ceaae9 --- /dev/null +++ b/game/vertices.py @@ -0,0 +1,25 @@ +# Copyright (C) 2022 RozK +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +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 __del__(self): + destroy_vertices(self._vertices)