Compare commits
No commits in common. "758ed8c7f4bf1d06b45990e915e8ea870e3633bd" and "1ac12ea9ea5115d159034957ee7cce3177488e50" have entirely different histories.
758ed8c7f4
...
1ac12ea9ea
2
engine
2
engine
@ -1 +1 @@
|
|||||||
Subproject commit 33abfd834ad5c9541796ef3f8a4999539a2f91f8
|
Subproject commit 269d7821c82757cf994370f9ed4b2a6d36e34983
|
@ -13,7 +13,13 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from engine import vec3_origin, mat4, mat4_projection, mat4_orbit, resolve_input, set_input_mat4
|
from engine import (
|
||||||
|
vec3, vec3_mul_vec3,
|
||||||
|
mat3, mat3_rotation, mat3_mul_vec3,
|
||||||
|
mat4, mat4_projection, mat4_lookat,
|
||||||
|
resolve_input, set_input_mat4)
|
||||||
|
|
||||||
|
_m2km = vec3(0.001, 0.001, 0.001)
|
||||||
|
|
||||||
class _Inputs:
|
class _Inputs:
|
||||||
__slots__ = 'projection', 'view'
|
__slots__ = 'projection', 'view'
|
||||||
@ -23,26 +29,30 @@ class _Inputs:
|
|||||||
self.view = resolve_input(shader, view)
|
self.view = resolve_input(shader, view)
|
||||||
|
|
||||||
class Camera:
|
class Camera:
|
||||||
__slots__ = 'yaw', 'pitch', 'distance', 'projection', 'view'
|
__slots__ = 'origin', 'lookat', 'rotation', 'projection', 'view'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.yaw = 0.0
|
self.origin = vec3()
|
||||||
self.pitch = 0.0
|
self.lookat = vec3()
|
||||||
self.distance = 0.0
|
self.rotation = mat3()
|
||||||
self.projection = mat4()
|
self.projection = mat4()
|
||||||
self.view = mat4()
|
self.view = mat4()
|
||||||
|
|
||||||
def set_projection(self, half_fov, ratio, near_z, far_z):
|
def set_projection(self, half_fov, ratio, near_z, far_z):
|
||||||
mat4_projection(self.projection, half_fov, ratio, near_z, far_z)
|
mat4_projection(self.projection, half_fov, ratio, near_z, far_z)
|
||||||
|
|
||||||
def set_view(self, yaw, pitch, distance):
|
def set_view(self, origin, lookat, axis, angle):
|
||||||
self.yaw = yaw
|
self.origin.set(*origin)
|
||||||
self.pitch = pitch
|
self.lookat.set(*lookat)
|
||||||
self.distance = distance
|
mat3_rotation(self.rotation, axis, angle)
|
||||||
mat4_orbit(self.view, vec3_origin, yaw, pitch, distance)
|
mat3_mul_vec3(self.origin, self.rotation, self.origin)
|
||||||
|
mat3_mul_vec3(self.lookat, self.rotation, self.lookat)
|
||||||
|
mat4_lookat(self.view, self.origin, self.lookat)
|
||||||
|
|
||||||
def to_km(self):
|
def to_km(self):
|
||||||
mat4_orbit(self.view, vec3_origin, self.yaw, self.pitch, self.distance * 0.001)
|
vec3_mul_vec3(self.origin, _m2km, self.origin)
|
||||||
|
vec3_mul_vec3(self.lookat, _m2km, self.lookat)
|
||||||
|
mat4_lookat(self.view, self.origin, self.lookat)
|
||||||
|
|
||||||
def resolve_inputs(self, shader, projection = b'u_projection', view = b'u_view'):
|
def resolve_inputs(self, shader, projection = b'u_projection', view = b'u_view'):
|
||||||
return _Inputs(shader, projection, view)
|
return _Inputs(shader, projection, view)
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
from engine import (
|
|
||||||
buffer,
|
|
||||||
EVENT_FOCUS_IN, EVENT_FOCUS_OUT,
|
|
||||||
EVENT_KEY_PRESS, EVENT_KEY_RELEASE,
|
|
||||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE,
|
|
||||||
EVENT_MOTION,
|
|
||||||
Event, create_events, destroy_events, consume_events)
|
|
||||||
|
|
||||||
_max_type = max(
|
|
||||||
EVENT_FOCUS_IN, EVENT_FOCUS_OUT,
|
|
||||||
EVENT_KEY_PRESS, EVENT_KEY_RELEASE,
|
|
||||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE,
|
|
||||||
EVENT_MOTION)
|
|
||||||
|
|
||||||
_max_events = 64
|
|
||||||
|
|
||||||
class Events:
|
|
||||||
__slots__ = '_display', '_events', '_buffer', '_handlers'
|
|
||||||
|
|
||||||
def __init__(self, display):
|
|
||||||
self._display = display
|
|
||||||
self._events = create_events(display)
|
|
||||||
self._buffer = buffer(Event, _max_events)
|
|
||||||
self._handlers = [[] for _ in range(_max_type + 1)]
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
destroy_events(self._display, self._events)
|
|
||||||
|
|
||||||
def register(self, type, handler):
|
|
||||||
assert type <= _max_type
|
|
||||||
self._handlers[type].append(handler)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
nevents = consume_events(self._events, self._buffer, _max_events)
|
|
||||||
if nevents:
|
|
||||||
for event in self._buffer[:nevents]:
|
|
||||||
data = event.data
|
|
||||||
for handler in self._handlers[event.type]:
|
|
||||||
handler(data)
|
|
63
game/game.py
63
game/game.py
@ -28,15 +28,15 @@ from game.resources import RuntimeArchive
|
|||||||
from game.batch import Batch
|
from game.batch import Batch
|
||||||
from game.camera import Camera
|
from game.camera import Camera
|
||||||
from game.environment import Environment
|
from game.environment import Environment
|
||||||
from game.events import Events
|
|
||||||
from game.mouse import Mouse
|
|
||||||
from game.keyboard import Keyboard
|
|
||||||
|
|
||||||
proj_hfov = pi * 0.25
|
proj_hfov = pi * 0.25
|
||||||
proj_ratio = 16.0 / 9.0
|
proj_ratio = 16.0 / 9.0
|
||||||
proj_near_z = 8.0
|
proj_near_z = 8.0
|
||||||
proj_far_z = 3000.0
|
proj_far_z = 3000.0
|
||||||
|
|
||||||
|
camera_origin = (0.0, -1200.0, 500.0)
|
||||||
|
camera_lookat = (0.0, 500.0, -500.0)
|
||||||
|
|
||||||
sun_direction = math.vec3_normalize((1.0, 0.0, 1.0))
|
sun_direction = math.vec3_normalize((1.0, 0.0, 1.0))
|
||||||
sun_power = 1.0
|
sun_power = 1.0
|
||||||
|
|
||||||
@ -48,10 +48,8 @@ def main():
|
|||||||
print("Done: ", round(gen_end - gen_begin, 2), "seconds")
|
print("Done: ", round(gen_end - gen_begin, 2), "seconds")
|
||||||
|
|
||||||
print("Initializing...")
|
print("Initializing...")
|
||||||
display = create_display(b'RK Island - Drag to rotate, wheel to zoom, q to quit', 1600, 900)
|
display = create_display(b'RK Island', 1600, 900)
|
||||||
events = Events(display)
|
events = create_events(display)
|
||||||
mouse = Mouse(events, wheel = 60, wheel_min = 20)
|
|
||||||
keyboard = Keyboard(events)
|
|
||||||
render_initialize()
|
render_initialize()
|
||||||
terrain_shader = shader.load('terrain', 'common')
|
terrain_shader = shader.load('terrain', 'common')
|
||||||
tests_shader = shader.load('tests', 'common')
|
tests_shader = shader.load('tests', 'common')
|
||||||
@ -159,7 +157,7 @@ def main():
|
|||||||
cube_orientation = tests_batch.params[cube_id].orientation
|
cube_orientation = tests_batch.params[cube_id].orientation
|
||||||
clouds_orientation = tests_batch.params[clouds_id].orientation
|
clouds_orientation = tests_batch.params[clouds_id].orientation
|
||||||
|
|
||||||
print("Running... Ctrl+c to quit")
|
print("Running... Click or press q to quit")
|
||||||
start_time = time.monotonic()
|
start_time = time.monotonic()
|
||||||
current_time = 0.0
|
current_time = 0.0
|
||||||
frame_min = 10000.0
|
frame_min = 10000.0
|
||||||
@ -169,21 +167,22 @@ def main():
|
|||||||
draw_max = 0.0
|
draw_max = 0.0
|
||||||
draw_avg = 0.0
|
draw_avg = 0.0
|
||||||
perf_count = 0
|
perf_count = 0
|
||||||
|
events_buffer = buffer(Event, 16)
|
||||||
try:
|
try:
|
||||||
for frame in range(10000):
|
for frame in range(10000):
|
||||||
current_time = time.monotonic() - start_time
|
current_time = time.monotonic() - start_time
|
||||||
frame_begin = time.thread_time()
|
|
||||||
|
|
||||||
events.update()
|
|
||||||
if keyboard.quit:
|
|
||||||
break
|
|
||||||
|
|
||||||
begin_frame()
|
begin_frame()
|
||||||
|
frame_begin = time.thread_time()
|
||||||
|
|
||||||
camera_distance = mouse.wheel * 20.0
|
rotation = mat3()
|
||||||
camera_yaw = mouse.drag[0] * 0.001
|
mat3_rotation(rotation, vec3_up, (current_time * 0.21) % tau)
|
||||||
camera_pitch = mouse.drag[1] * 0.001 + pi * 0.25
|
mat3_mul_vec3(blob_translation, rotation, blob_spawn_translation)
|
||||||
camera.set_view(camera_yaw, camera_pitch, camera_distance)
|
mat3_mul_vec3(cube_translation, rotation, cube_spawn_translation)
|
||||||
|
mat3_rotation(cube_orientation, vec3_up, (current_time * 0.43) % tau)
|
||||||
|
mat3_rotation(clouds_orientation, vec3_up, (current_time * -0.037) % tau)
|
||||||
|
|
||||||
|
camera.set_view(camera_origin, camera_lookat, vec3_up, (current_time * 0.05) % tau)
|
||||||
environment.from_sun(camera.view, sun_direction, sun_power)
|
environment.from_sun(camera.view, sun_direction, sun_power)
|
||||||
|
|
||||||
select_shader(terrain_shader)
|
select_shader(terrain_shader)
|
||||||
@ -202,13 +201,6 @@ def main():
|
|||||||
unselect_texture(2, normalmap)
|
unselect_texture(2, normalmap)
|
||||||
unselect_shader(terrain_shader)
|
unselect_shader(terrain_shader)
|
||||||
|
|
||||||
rotation = mat3()
|
|
||||||
mat3_rotation(rotation, vec3_up, (current_time * 0.21) % tau)
|
|
||||||
mat3_mul_vec3(blob_translation, rotation, blob_spawn_translation)
|
|
||||||
mat3_mul_vec3(cube_translation, rotation, cube_spawn_translation)
|
|
||||||
mat3_rotation(cube_orientation, vec3_up, (current_time * 0.43) % tau)
|
|
||||||
mat3_rotation(clouds_orientation, vec3_up, (current_time * -0.037) % tau)
|
|
||||||
|
|
||||||
select_shader(tests_shader)
|
select_shader(tests_shader)
|
||||||
camera.update_inputs(tests_camera_inputs)
|
camera.update_inputs(tests_camera_inputs)
|
||||||
environment.update_inputs(tests_environment_inputs)
|
environment.update_inputs(tests_environment_inputs)
|
||||||
@ -251,6 +243,23 @@ def main():
|
|||||||
frame_avg += frame_ms
|
frame_avg += frame_ms
|
||||||
perf_count += 1
|
perf_count += 1
|
||||||
|
|
||||||
|
stop = False
|
||||||
|
while True:
|
||||||
|
nevents = consume_events(events, events_buffer, len(events_buffer))
|
||||||
|
if not nevents:
|
||||||
|
break
|
||||||
|
for event in events_buffer[:nevents]:
|
||||||
|
if event.type == EVENT_FOCUS_IN:
|
||||||
|
print("EVENT_FOCUS_IN")
|
||||||
|
elif event.type == EVENT_FOCUS_OUT:
|
||||||
|
print("EVENT_FOCUS_OUT")
|
||||||
|
elif event.type == EVENT_KEY_PRESS and event.data.key.character == 'q':
|
||||||
|
stop = True
|
||||||
|
elif event.type == EVENT_BUTTON_RELEASE:
|
||||||
|
stop = True
|
||||||
|
if stop:
|
||||||
|
break
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -265,6 +274,10 @@ def main():
|
|||||||
", avg =", round((frame_avg / perf_count) * 1000.0, 2), "ms")
|
", avg =", round((frame_avg / perf_count) * 1000.0, 2), "ms")
|
||||||
|
|
||||||
# seed 666
|
# seed 666
|
||||||
|
# camera_origin = vec3((0.0, -1200.0, 500.0))
|
||||||
|
# camera_lookat = vec3((0.0, 500.0, -500.0))
|
||||||
|
# for x in range(10000)
|
||||||
|
# current_time = 0
|
||||||
|
|
||||||
# Draw * 9999 : min = 0.2 , max = 1.32 , avg = 0.27 ms
|
# Draw * 9999 : min = 0.2 , max = 1.32 , avg = 0.27 ms
|
||||||
# Draw * 9999 : min = 0.2 , max = 1.34 , avg = 0.27 ms
|
# Draw * 9999 : min = 0.2 , max = 1.34 , avg = 0.27 ms
|
||||||
@ -287,5 +300,5 @@ def main():
|
|||||||
destroy_shader(tests_shader)
|
destroy_shader(tests_shader)
|
||||||
destroy_shader(sky_shader)
|
destroy_shader(sky_shader)
|
||||||
render_terminate()
|
render_terminate()
|
||||||
del events
|
destroy_events(display, events)
|
||||||
destroy_display(display)
|
destroy_display(display)
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
from engine import EVENT_KEY_PRESS
|
|
||||||
|
|
||||||
class Keyboard:
|
|
||||||
__slots__ = 'quit'
|
|
||||||
|
|
||||||
def __init__(self, events):
|
|
||||||
self.quit = False
|
|
||||||
events.register(EVENT_KEY_PRESS, self.key_press_handler)
|
|
||||||
|
|
||||||
def key_press_handler(self, data):
|
|
||||||
if data.key.character == 'q':
|
|
||||||
self.quit = True
|
|
@ -1,52 +0,0 @@
|
|||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
from engine import (
|
|
||||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE, EVENT_MOTION, BUTTON_LEFT, BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN)
|
|
||||||
|
|
||||||
class Mouse:
|
|
||||||
__slots__ = 'buttons', 'wheel', 'wheel_min', 'position', 'drag'
|
|
||||||
|
|
||||||
def __init__(self, events, wheel = 0, wheel_min = None):
|
|
||||||
self.buttons = 0
|
|
||||||
self.wheel = wheel
|
|
||||||
self.wheel_min = wheel_min
|
|
||||||
self.position = None
|
|
||||||
self.drag = (0, 0)
|
|
||||||
events.register(EVENT_BUTTON_PRESS, self.button_press_handler)
|
|
||||||
events.register(EVENT_BUTTON_RELEASE, self.button_release_handler)
|
|
||||||
events.register(EVENT_MOTION, self.motion_handler)
|
|
||||||
|
|
||||||
def button_press_handler(self, data):
|
|
||||||
button = data.button.index
|
|
||||||
self.buttons |= 1 << button
|
|
||||||
if button == BUTTON_WHEEL_UP:
|
|
||||||
self.wheel -= 1
|
|
||||||
if self.wheel_min is not None and self.wheel < self.wheel_min:
|
|
||||||
self.wheel = self.wheel_min
|
|
||||||
elif button == BUTTON_WHEEL_DOWN:
|
|
||||||
self.wheel += 1
|
|
||||||
|
|
||||||
def button_release_handler(self, data):
|
|
||||||
self.buttons &= ~(1 << data.button.index)
|
|
||||||
|
|
||||||
def motion_handler(self, data):
|
|
||||||
new_x = data.motion.x
|
|
||||||
new_y = data.motion.y
|
|
||||||
if self.position and (self.buttons & (1 << BUTTON_LEFT)):
|
|
||||||
prev_x, prev_y = self.position
|
|
||||||
prev_dx, prev_dy = self.drag
|
|
||||||
self.drag = (prev_dx + (new_x - prev_x), prev_dy + (new_y - prev_y))
|
|
||||||
self.position = (new_x, new_y)
|
|
Loading…
Reference in New Issue
Block a user