rk_engine/__init__.py

432 lines
11 KiB
Python
Raw Normal View History

2022-08-28 04:23:13 +02:00
# 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/>.
import ctypes
from array import array
2022-09-20 02:47:07 +02:00
from pathlib import Path
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
_engine = ctypes.cdll.LoadLibrary(Path(__file__).parent / "engine.so")
2022-08-28 04:23:13 +02:00
# types.hpp
def _flag(x):
return 1 << x
def buffer(type, size):
return (type * size)()
def _voidp(x):
return x.buffer_info()[0]
def _ubytep(x):
assert x.typecode == 'B'
return x.buffer_info()[0]
def _ushortp(x):
assert x.typecode == 'H'
return x.buffer_info()[0]
def _floatp(x):
assert x.typecode == 'f'
return x.buffer_info()[0]
# math.hpp
2022-12-20 13:34:07 +01:00
class vec3(ctypes.Structure):
_fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float)
def set(self, x, y, z):
self.x = x
self.y = y
self.z = z
class vec4(ctypes.Structure):
_fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float), ('w', ctypes.c_float)
def set(self, x, y, z, w):
self.x = x
self.y = y
self.z = z
self.w = w
class mat3(ctypes.Structure):
_fields_ = ('x', vec3), ('y', vec3), ('z', vec3)
class mat4(ctypes.Structure):
_fields_ = ('x', vec4), ('y', vec4), ('z', vec4), ('w', vec4)
_vec3p = ctypes.POINTER(vec3)
_vec4p = ctypes.POINTER(vec4)
_mat3p = ctypes.POINTER(mat3)
_mat4p = ctypes.POINTER(mat4)
2022-08-28 04:23:13 +02:00
vec3_right = vec3(1.0, 0.0, 0.0)
vec3_forward = vec3(0.0, 1.0, 0.0)
vec3_up = vec3(0.0, 0.0, 1.0)
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
vec3_rotate = _engine.rk_vec3_rotate
2022-12-20 15:26:53 +01:00
vec3_rotate.argtypes = (
_vec3p, # ret
_vec3p, # vec3
_vec3p, # axis
ctypes.c_float) # angle
2022-12-23 10:13:24 +01:00
vec3_mul_vec3 = _engine.rk_vec3_mul_vec3
2022-12-20 15:26:53 +01:00
vec3_mul_vec3.argtypes = (
_vec3p, # ret
_vec3p, # a
_vec3p) # b
2022-12-23 10:13:24 +01:00
mat3_rotation = _engine.rk_mat3_rotation
2022-12-20 13:34:07 +01:00
mat3_rotation.argtypes = (
_mat3p, # ret
_vec3p, # axis
2022-08-28 04:23:13 +02:00
ctypes.c_float) # angle
2022-12-23 10:13:24 +01:00
mat3_mul_vec3 = _engine.rk_mat3_mul_vec3
2022-12-20 13:34:07 +01:00
mat3_mul_vec3.argtypes = (
_vec3p, # ret
_mat3p, # a
_vec3p) # b
2022-12-23 10:13:24 +01:00
mat3_mul_mat3 = _engine.rk_mat3_mul_mat3
2022-12-20 13:34:07 +01:00
mat3_mul_mat3.argtypes = (
_mat3p, # ret
_mat3p, # a
_mat3p) # b
2022-12-23 10:13:24 +01:00
mat4_projection = _engine.rk_mat4_projection
2022-12-20 13:34:07 +01:00
mat4_projection.argtypes = (
_mat4p, # ret
2022-09-20 02:54:59 +02:00
ctypes.c_float, # hfov
ctypes.c_float, # ratio
ctypes.c_float, # near
ctypes.c_float) # far
2022-12-23 10:13:24 +01:00
mat4_lookat = _engine.rk_mat4_lookat
2022-12-20 13:34:07 +01:00
mat4_lookat.argtypes = (
_mat4p, # ret
_vec3p, # position
_vec3p) # lookat
2022-12-23 10:13:24 +01:00
mat4_mul_vec3 = _engine.rk_mat4_mul_vec3
2022-12-20 13:34:07 +01:00
mat4_mul_vec3.argtypes = (
_vec3p, # ret
_mat4p, # a
_vec3p, # b
2022-11-29 03:05:34 +01:00
ctypes.c_float) # w
2022-12-23 10:13:24 +01:00
mat4_mul_vec4 = _engine.rk_mat4_mul_vec4
2022-12-20 13:34:07 +01:00
mat4_mul_vec4.argtypes = (
_vec4p, # ret
_mat4p, # a
_vec4p) # b
2022-11-29 03:05:34 +01:00
2022-12-23 10:13:24 +01:00
mat4_mul_mat4 = _engine.rk_mat4_mul_mat4
2022-12-20 13:34:07 +01:00
mat4_mul_mat4.argtypes = (
_mat4p, # ret
_mat4p, # a
_mat4p) # b
2022-08-28 04:23:13 +02:00
# display.hpp
create_display = _engine.rk_create_display
create_display.restype = ctypes.c_void_p
create_display.argtypes = (
ctypes.c_char_p, # name
ctypes.c_uint, # width
ctypes.c_uint) # height
2022-08-28 04:23:13 +02:00
destroy_display = _engine.rk_destroy_display
destroy_display.argtypes = (
ctypes.c_void_p,) # display
swap_buffers = _engine.rk_swap_buffers
swap_buffers.argtypes = (
ctypes.c_void_p,) # display
# render.hpp
TEXTURE_FORMAT_SRGB8_A8 = 0
TEXTURE_FORMAT_RGBA8 = 1
TEXTURE_FORMAT_RGB10_A2 = 2
TEXTURE_FORMAT_32F = 3
TEXTURE_FORMAT_TYPECODE = ('B', 'B', 'I', 'f')
TEXTURE_FORMAT_NELEMS = (4, 4, 1, 1)
TEXTURE_FLAG_3D = _flag(0)
TEXTURE_FLAG_MIPMAPS = _flag(1)
TEXTURE_FLAG_MIN_NEAREST = 0
TEXTURE_FLAG_MIN_LINEAR = _flag(2)
TEXTURE_FLAG_MAG_NEAREST = 0
TEXTURE_FLAG_MAG_LINEAR = _flag(3)
VERTEX_FORMAT_VEC3_FLOAT = 1
VERTEX_FORMAT_VEC3_INT10 = 2
VERTEX_FORMAT_VEC3_UINT10 = 3
VERTEX_FORMAT_NORMALIZE = _flag(7)
def vertex_format(*format):
return array('B', format).tobytes()
PARAM_FORMAT_VEC3_FLOAT = 1
PARAM_FORMAT_VEC3_SHORT = 2
PARAM_FORMAT_VEC3_INT10 = 3
PARAM_FORMAT_NORMALIZE = _flag(7)
def params_format(*format):
return array('B', format).tobytes()
INSTANCE_FLAG_SPAWNED = _flag(0)
INSTANCE_FLAG_VISIBLE = _flag(1)
BATCH_MAX_SIZE = 65536
render_initialize = _engine.rk_render_initialize
render_terminate = _engine.rk_render_terminate
2022-12-23 10:13:24 +01:00
_load_shader = _engine.rk_load_shader
2022-08-28 04:23:13 +02:00
_load_shader.restype = ctypes.c_void_p
_load_shader.argtypes = (
2022-12-04 03:16:01 +01:00
ctypes.c_uint, # vert_nlines
ctypes.c_void_p, # vert_lines
ctypes.c_uint, # frag_nlines
ctypes.c_void_p) # frag_lines
def load_shader(vert_lines, frag_lines):
vert_nlines = len(vert_lines)
vert_type = ctypes.c_char_p * vert_nlines
vert_lines = vert_type(*map(ctypes.c_char_p, vert_lines))
frag_nlines = len(frag_lines)
frag_type = ctypes.c_char_p * frag_nlines
frag_lines = frag_type(*map(ctypes.c_char_p, frag_lines))
return _load_shader(
vert_nlines, ctypes.addressof(vert_lines),
frag_nlines, ctypes.addressof(frag_lines))
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
resolve_input = _engine.rk_resolve_input
2022-12-17 04:58:19 +01:00
resolve_input.restype = ctypes.c_void_p
2022-08-28 04:23:13 +02:00
resolve_input.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # shader
ctypes.c_char_p) # name
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
resolve_param = _engine.rk_resolve_param
resolve_param.restype = ctypes.c_void_p
resolve_param.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # shader
ctypes.c_char_p) # name
2022-12-23 10:13:24 +01:00
_create_texture = _engine.rk_create_texture
2022-08-28 04:23:13 +02:00
_create_texture.restype = ctypes.c_void_p
_create_texture.argtypes = (
ctypes.c_uint, # format
ctypes.c_uint, # width
ctypes.c_uint, # height
ctypes.c_uint, # nlevels
ctypes.c_uint, # flags
ctypes.c_void_p) # pixels
2022-12-19 06:27:34 +01:00
def create_texture(format, width, height, nlevels, flags, pixels):
2022-08-28 04:23:13 +02:00
assert pixels.typecode == TEXTURE_FORMAT_TYPECODE[format]
assert len(pixels) == width * height * max(1, nlevels) * TEXTURE_FORMAT_NELEMS[format]
2022-12-19 06:27:34 +01:00
return _create_texture(format, width, height, nlevels, flags, _voidp(pixels))
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
_create_triangles = _engine.rk_create_triangles
2022-08-28 04:23:13 +02:00
_create_triangles.restype = ctypes.c_void_p
_create_triangles.argtypes = (
ctypes.c_uint, # nvertices
ctypes.c_void_p) # vertices
def create_triangles(vertices):
assert len(vertices) % 9 == 0
return _create_triangles(len(vertices) // 3, _floatp(vertices))
2022-12-23 10:13:24 +01:00
_create_vertices = _engine.rk_create_vertices
2022-08-28 04:23:13 +02:00
_create_vertices.restype = ctypes.c_void_p
_create_vertices.argtypes = (
ctypes.c_char_p, # format
ctypes.c_uint, # nvertices
ctypes.c_void_p, # vertices
ctypes.c_uint, # nindices
ctypes.c_void_p) # indices
def create_vertices(format, nvertices, vertices, indices):
return _create_vertices(format, nvertices, _ubytep(vertices), len(indices), _ushortp(indices))
2022-12-23 10:13:24 +01:00
create_batch = _engine.rk_create_batch
2022-08-28 04:23:13 +02:00
create_batch.restype = ctypes.c_void_p
create_batch.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # vertices
2022-08-28 04:23:13 +02:00
ctypes.c_uint, # max_size
2022-12-17 04:58:19 +01:00
ctypes.c_char_p) # params_format
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
begin_frame = _engine.rk_begin_frame
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
select_shader = _engine.rk_select_shader
2022-12-18 03:39:34 +01:00
select_shader.argtypes = (
ctypes.c_void_p,) # shader
2022-12-23 10:13:24 +01:00
set_input_float = _engine.rk_set_input_float
2022-12-18 03:39:34 +01:00
set_input_float.argtypes = (
ctypes.c_void_p, # input
ctypes.c_float) # value
2022-12-23 10:13:24 +01:00
set_input_vec3 = _engine.rk_set_input_vec3
2022-12-20 13:34:07 +01:00
set_input_vec3.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # input
2022-12-20 13:34:07 +01:00
_vec3p) # value
2022-12-18 03:39:34 +01:00
2022-12-23 10:13:24 +01:00
set_input_mat3 = _engine.rk_set_input_mat3
2022-12-20 13:34:07 +01:00
set_input_mat3.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # input
2022-12-20 13:34:07 +01:00
_mat3p) # value
2022-12-18 03:39:34 +01:00
2022-12-23 10:13:24 +01:00
set_input_mat4 = _engine.rk_set_input_mat4
2022-12-20 13:34:07 +01:00
set_input_mat4.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # input
2022-12-20 13:34:07 +01:00
_mat4p) # value
2022-12-18 03:39:34 +01:00
2022-12-23 10:13:24 +01:00
set_param_vec3 = _engine.rk_set_param_vec3
2022-12-20 13:34:07 +01:00
set_param_vec3.argtypes = (
2022-12-18 03:39:34 +01:00
ctypes.c_uint, # layout
2022-12-20 13:34:07 +01:00
_vec3p) # value
2022-12-18 03:39:34 +01:00
2022-12-23 10:13:24 +01:00
select_texture = _engine.rk_select_texture
2022-08-28 04:23:13 +02:00
select_texture.argtypes = (
2022-12-19 06:27:34 +01:00
ctypes.c_uint, # slot
2022-12-18 03:39:34 +01:00
ctypes.c_void_p, # texture
ctypes.c_void_p) # sampler
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
draw_triangles = _engine.rk_draw_triangles
2022-08-28 04:23:13 +02:00
draw_triangles.argtypes = (
ctypes.c_void_p,) # triangles
2022-12-23 10:13:24 +01:00
select_vertices = _engine.rk_select_vertices
2022-08-28 04:23:13 +02:00
select_vertices.argtypes = (
ctypes.c_void_p,) # vertices
2022-12-23 10:13:24 +01:00
draw_batch = _engine.rk_draw_batch
2022-12-20 14:37:27 +01:00
draw_batch.argtypes = (
2022-08-28 04:23:13 +02:00
ctypes.c_void_p, # batch
ctypes.c_uint, # size
2022-12-20 14:37:27 +01:00
ctypes.POINTER(ctypes.c_ubyte), # flags
ctypes.POINTER(ctypes.c_uint), # meshes
2022-12-17 04:58:19 +01:00
ctypes.c_void_p) # params
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
unselect_vertices = _engine.rk_unselect_vertices
2022-08-28 04:23:13 +02:00
unselect_vertices.argtypes = (
ctypes.c_void_p,) # vertices
2022-12-23 10:13:24 +01:00
unselect_texture = _engine.rk_unselect_texture
2022-08-28 04:23:13 +02:00
unselect_texture.argtypes = (
2022-12-19 06:27:34 +01:00
ctypes.c_uint, # slot
ctypes.c_void_p) # texture
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
unselect_shader = _engine.rk_unselect_shader
2022-08-28 04:23:13 +02:00
unselect_shader.argtypes = (
ctypes.c_void_p,) # shader
2022-12-23 10:13:24 +01:00
end_frame = _engine.rk_end_frame
2022-08-28 04:23:13 +02:00
2022-12-23 10:13:24 +01:00
destroy_batch = _engine.rk_destroy_batch
2022-08-28 04:23:13 +02:00
destroy_batch.argtypes = (
ctypes.c_void_p,) # batch
2022-12-23 10:13:24 +01:00
destroy_triangles = _engine.rk_destroy_triangles
2022-08-28 04:23:13 +02:00
destroy_triangles.argtypes = (
ctypes.c_void_p,) # triangles
2022-12-23 10:13:24 +01:00
destroy_vertices = _engine.rk_destroy_vertices
2022-08-28 04:23:13 +02:00
destroy_vertices.argtypes = (
ctypes.c_void_p,) # vertices
2022-12-23 10:13:24 +01:00
destroy_texture = _engine.rk_destroy_texture
2022-08-28 04:23:13 +02:00
destroy_texture.argtypes = (
ctypes.c_void_p,) # texture
2022-12-23 10:13:24 +01:00
destroy_shader = _engine.rk_destroy_shader
2022-08-28 04:23:13 +02:00
destroy_shader.argtypes = (
ctypes.c_void_p,) # shader
# events.hpp
2022-12-24 06:36:20 +01:00
EVENT_FOCUS_IN = 0
EVENT_FOCUS_OUT = 1
EVENT_KEY_PRESS = 2
EVENT_KEY_RELEASE = 3
EVENT_BUTTON_PRESS = 4
EVENT_BUTTON_RELEASE = 5
EVENT_MOTION = 6
BUTTON_LEFT = 1
BUTTON_MIDDLE = 2
BUTTON_RIGHT = 3
BUTTON_WHEEL_UP = 4
BUTTON_WHEEL_DOWN = 5
class _EventKey(ctypes.Structure):
2022-12-24 06:36:20 +01:00
_fields_ = (
('code', ctypes.c_uint),
('symbol', ctypes.c_uint),
('character', ctypes.c_wchar))
class _EventButton(ctypes.Structure):
_fields_ = ('index', ctypes.c_uint),
class _EventMotion(ctypes.Structure):
_fields_ = (
('x', ctypes.c_int),
('y', ctypes.c_int))
2022-12-23 13:28:29 +01:00
class _Events(ctypes.Union):
_fields_ = (
('key', _EventKey),
2022-12-24 06:36:20 +01:00
('button', _EventButton),
('motion', _EventMotion))
class Event(ctypes.Structure):
2022-12-23 13:28:29 +01:00
_fields_ = ('type', ctypes.c_uint), ('data', _Events)
create_events = _engine.rk_create_events
create_events.restype = ctypes.c_void_p
create_events.argtypes = (
ctypes.c_void_p,) # display
destroy_events = _engine.rk_destroy_events
destroy_events.argtypes = (
ctypes.c_void_p, # display
ctypes.c_void_p) # events
set_key_autorepeat = _engine.rk_set_key_autorepeat
set_key_autorepeat.argtypes = (
ctypes.c_void_p, # events
ctypes.c_bool) # autorepeat
2022-12-24 06:36:20 +01:00
set_motion_acceleration = _engine.rk_set_motion_acceleration
set_motion_acceleration.argtypes = (
ctypes.c_void_p, # events
2022-12-24 06:36:20 +01:00
ctypes.c_uint, # numerator
ctypes.c_uint, # denominator
ctypes.c_uint) # threshold
consume_events = _engine.rk_consume_events
consume_events.restype = ctypes.c_uint
consume_events.argtypes = (
ctypes.c_void_p, # events
ctypes.POINTER(Event), # buffer
ctypes.c_uint) # max_events