diff --git a/__init__.py b/__init__.py index 9626fbc..f95d8f1 100644 --- a/__init__.py +++ b/__init__.py @@ -47,6 +47,11 @@ def _float_addr(x): class vec3(ctypes.Structure): _fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float) + def __iter__(self): + yield self.x + yield self.y + yield self.z + def set(self, x, y, z): self.x = x self.y = y @@ -55,6 +60,12 @@ class vec3(ctypes.Structure): class vec4(ctypes.Structure): _fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float), ('w', ctypes.c_float) + def __iter__(self): + yield self.x + yield self.y + yield self.z + yield self.w + def set(self, x, y, z, w): self.x = x self.y = y @@ -62,10 +73,59 @@ class vec4(ctypes.Structure): self.w = w class mat3(ctypes.Structure): - _fields_ = ('x', vec3), ('y', vec3), ('z', vec3) + _fields_ = ('right', vec3), ('forward', vec3), ('up', vec3) + + def __iter__(self): + yield self.right + yield self.forward + yield self.up + + def set(self, right, forward, up): + self.right = right + self.forward = forward + self.up = up class mat4(ctypes.Structure): - _fields_ = ('x', vec4), ('y', vec4), ('z', vec4), ('w', vec4) + _fields_ = ('right', vec4), ('forward', vec4), ('up', vec4), ('origin', vec4) + + def __iter__(self): + yield self.right + yield self.forward + yield self.up + yield self.origin + + def set(self, right, forward, up, origin): + self.right = right + self.forward = forward + self.up = up + self.origin = origin + + def set_mat3_vec3(self, axes, origin): + self.right.set(*axes.right, 0.0) + self.forward.set(*axes.forward, 0.0) + self.up.set(*axes.up, 0.0) + self.origin.set(*origin, 1.0) + + def set_axes(self, right, forward, up): + self.right = right + self.forward = forward + self.up = up + + def set_axes_mat3(self, axes): + self.right.set(*axes.right, 0.0) + self.forward.set(*axes.forward, 0.0) + self.up.set(*axes.up, 0.0) + + def set_origin(self, origin): + self.origin = origin + + def set_origin_vec3(self, origin): + self.origin.set(*origin, 1.0) + +assert ctypes.sizeof(vec3) == ctypes.sizeof(ctypes.c_float) * 3 +assert ctypes.sizeof(vec4) == ctypes.sizeof(ctypes.c_float) * 4 +assert ctypes.sizeof(mat3) == ctypes.sizeof(vec3) * 3 +assert ctypes.sizeof(mat4) == ctypes.sizeof(vec4) * 4 _vec3_p = ctypes.POINTER(vec3) _vec4_p = ctypes.POINTER(vec4) @@ -75,6 +135,23 @@ _mat4_p = ctypes.POINTER(mat4) 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) +vec3_origin = vec3(0.0, 0.0, 0.0) + +vec4_right = vec4(1.0, 0.0, 0.0, 0.0) +vec4_forward = vec4(0.0, 1.0, 0.0, 0.0) +vec4_up = vec4(0.0, 0.0, 1.0, 0.0) +vec4_origin = vec4(0.0, 0.0, 0.0, 1.0) + +mat3_identity = mat3( + vec3_right, + vec3_forward, + vec3_up) + +mat4_identity = mat4( + vec4_right, + vec4_forward, + vec4_up, + vec4_origin) vec3_rotate = _engine.rk_vec3_rotate vec3_rotate.argtypes = ( @@ -185,6 +262,8 @@ def vertex_format(*format): PARAM_FORMAT_VEC3_FLOAT = 1 PARAM_FORMAT_VEC3_SHORT = 2 PARAM_FORMAT_VEC3_INT10 = 3 +PARAM_FORMAT_MAT3_FLOAT = 4 +PARAM_FORMAT_MAT3_INT10 = 5 PARAM_FORMAT_NORMALIZE = _flag(7) def params_format(*format): diff --git a/cpp/render.hpp b/cpp/render.hpp index 2307cd3..a2d4b54 100644 --- a/cpp/render.hpp +++ b/cpp/render.hpp @@ -55,7 +55,9 @@ enum : rk_ubyte { RK_VERTEX_FORMAT_MASK = RK_VERTEX_FORMAT_NORMALIZE - 1 }; enum rk_param_format : rk_ubyte { RK_PARAM_FORMAT_VEC3_FLOAT = 1, RK_PARAM_FORMAT_VEC3_SHORT = 2, - RK_PARAM_FORMAT_VEC3_INT10 = 3 + RK_PARAM_FORMAT_VEC3_INT10 = 3, + RK_PARAM_FORMAT_MAT3_FLOAT = 4, + RK_PARAM_FORMAT_MAT3_INT10 = 5 }; enum : rk_ubyte { RK_PARAM_FORMAT_NORMALIZE = RK_FLAG(7) }; diff --git a/cpp/render/render_opengles.cpp b/cpp/render/render_opengles.cpp index ba28fe8..746e67a 100644 --- a/cpp/render/render_opengles.cpp +++ b/cpp/render/render_opengles.cpp @@ -290,18 +290,18 @@ rk_vertices_t rk_create_vertices( unsigned offset = 0; for (rk_vertex_format const * f = format; *f; ++f, ++vertices->layout) { glEnableVertexAttribArray(vertices->layout); - GLboolean const normalize = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0; + GLboolean const norm = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0; switch (*f & RK_VERTEX_FORMAT_MASK) { case RK_VERTEX_FORMAT_VEC3_FLOAT: - glVertexAttribFormat(vertices->layout, 3, GL_FLOAT, normalize, offset); + glVertexAttribFormat(vertices->layout, 3, GL_FLOAT, norm, offset); offset += sizeof(rk_vec3); break; case RK_VERTEX_FORMAT_VEC3_INT10: - glVertexAttribFormat(vertices->layout, 4, GL_INT_2_10_10_10_REV, normalize, offset); + glVertexAttribFormat(vertices->layout, 4, GL_INT_2_10_10_10_REV, norm, offset); offset += sizeof(rk_int); break; case RK_VERTEX_FORMAT_VEC3_UINT10: - glVertexAttribFormat(vertices->layout, 4, GL_UNSIGNED_INT_2_10_10_10_REV, normalize, offset); + glVertexAttribFormat(vertices->layout, 4, GL_UNSIGNED_INT_2_10_10_10_REV, norm, offset); offset += sizeof(rk_uint); break; } @@ -315,35 +315,77 @@ rk_vertices_t rk_create_vertices( return vertices; } -static void rk_pack_vec3( - rk_pack_dst dst, - rk_pack_src src) { - *dst.vec3_ptr = *src.vec3_ptr; +static void rk_pack_vec3_float( + rk_pack_dst const dst, + rk_pack_src const src) { + *dst.vec3_float = *src.vec3_float; } -static void rk_pack_vec3s( - rk_pack_dst dst, - rk_pack_src src) { - dst.vec3s_ptr->x = static_cast(src.vec3_ptr->x); - dst.vec3s_ptr->y = static_cast(src.vec3_ptr->y); - dst.vec3s_ptr->z = static_cast(src.vec3_ptr->z); +static void rk_pack_vec3_short( + rk_pack_dst const dst, + rk_pack_src const src) { + dst.vec3_short->x = static_cast(src.vec3_float->x); + dst.vec3_short->y = static_cast(src.vec3_float->y); + dst.vec3_short->z = static_cast(src.vec3_float->z); } -static void rk_pack_vec3s_norm( - rk_pack_dst dst, - rk_pack_src src) { +static void rk_pack_vec3_short_norm( + rk_pack_dst const dst, + rk_pack_src const src) { #define _convert(s) (static_cast((s) * ((s) < 0.f ? 32768.f : 32767.f))) - dst.vec3s_ptr->x = _convert(src.vec3_ptr->x); - dst.vec3s_ptr->y = _convert(src.vec3_ptr->y); - dst.vec3s_ptr->z = _convert(src.vec3_ptr->z); + dst.vec3_short->x = _convert(src.vec3_float->x); + dst.vec3_short->y = _convert(src.vec3_float->y); + dst.vec3_short->z = _convert(src.vec3_float->z); #undef _convert } static void rk_pack_vec3_int10( - rk_pack_dst dst, - rk_pack_src src) { + rk_pack_dst const dst, + rk_pack_src const src) { + #define _convert(s) (static_cast((s)) & 1023) + *dst.vec3_int10 = + _convert(src.vec3_float->x) | (_convert(src.vec3_float->y) << 10) | (_convert(src.vec3_float->z) << 20); + #undef _convert +} + +static void rk_pack_vec3_int10_norm( + rk_pack_dst const dst, + rk_pack_src const src) { #define _convert(s) (static_cast((s) * ((s) < 0.f ? 512.f : 511.f)) & 1023) - *dst.int_ptr = _convert(src.vec3_ptr->x) | (_convert(src.vec3_ptr->y) << 10) | (_convert(src.vec3_ptr->z) << 20); + *dst.vec3_int10 = + _convert(src.vec3_float->x) | (_convert(src.vec3_float->y) << 10) | (_convert(src.vec3_float->z) << 20); + #undef _convert +} + +static void rk_pack_mat3_float( + rk_pack_dst const dst, + rk_pack_src const src) { + *dst.mat3_float = *src.mat3_float; +} + +static void rk_pack_mat3_int10( + rk_pack_dst const dst, + rk_pack_src const src) { + #define _convert(s) (static_cast((s)) & 1023) + dst.mat3_int10->x = + _convert(src.mat3_float->x.x) | (_convert(src.mat3_float->x.y) << 10) | (_convert(src.mat3_float->x.z) << 20); + dst.mat3_int10->y = + _convert(src.mat3_float->y.x) | (_convert(src.mat3_float->y.y) << 10) | (_convert(src.mat3_float->y.z) << 20); + dst.mat3_int10->z = + _convert(src.mat3_float->z.x) | (_convert(src.mat3_float->z.y) << 10) | (_convert(src.mat3_float->z.z) << 20); + #undef _convert +} + +static void rk_pack_mat3_int10_norm( + rk_pack_dst const dst, + rk_pack_src const src) { + #define _convert(s) (static_cast((s) * ((s) < 0.f ? 512.f : 511.f)) & 1023) + dst.mat3_int10->x = + _convert(src.mat3_float->x.x) | (_convert(src.mat3_float->x.y) << 10) | (_convert(src.mat3_float->x.z) << 20); + dst.mat3_int10->y = + _convert(src.mat3_float->y.x) | (_convert(src.mat3_float->y.y) << 10) | (_convert(src.mat3_float->y.z) << 20); + dst.mat3_int10->z = + _convert(src.mat3_float->z.x) | (_convert(src.mat3_float->z.y) << 10) | (_convert(src.mat3_float->z.z) << 20); #undef _convert } @@ -363,16 +405,24 @@ rk_batch_t rk_create_batch( for (rk_param_format const * f = params_format; *f; ++f, ++nparams) { switch (*f & RK_PARAM_FORMAT_MASK) { case RK_PARAM_FORMAT_VEC3_FLOAT: - params_size += sizeof(rk_vec3); - packed_size += sizeof(rk_vec3); + params_size += sizeof(rk_vec3_float); + packed_size += sizeof(rk_vec3_float); break; case RK_PARAM_FORMAT_VEC3_SHORT: - params_size += sizeof(rk_vec3); - packed_size += sizeof(rk_vec3s); + params_size += sizeof(rk_vec3_float); + packed_size += sizeof(rk_vec3_short); break; case RK_PARAM_FORMAT_VEC3_INT10: - params_size += sizeof(rk_vec3); - packed_size += sizeof(rk_int); + params_size += sizeof(rk_vec3_float); + packed_size += sizeof(rk_vec3_int10); + break; + case RK_PARAM_FORMAT_MAT3_FLOAT: + params_size += sizeof(rk_mat3_float); + packed_size += sizeof(rk_mat3_float); + break; + case RK_PARAM_FORMAT_MAT3_INT10: + params_size += sizeof(rk_mat3_float); + packed_size += sizeof(rk_mat3_int10); break; default: rk_printf("rk_create_batch(): invalid param format."); @@ -391,39 +441,65 @@ rk_batch_t rk_create_batch( batch->packers = new rk_packer[nparams]; batch->params = new rk_ubyte[max_size * packed_size]; glGenBuffers(1, &batch->params_buffer); - unsigned layout = vertices->layout; rk_packer * packer = batch->packers; + unsigned layout = vertices->layout; unsigned offset = 0; glBindVertexArray(vertices->array); - for (rk_param_format const * f = params_format; *f; ++f, ++layout, ++packer) { - GLboolean const normalize = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; - glEnableVertexAttribArray(layout); + for (rk_param_format const * f = params_format; *f; ++f, ++packer) { + GLboolean const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; switch (*f & RK_PARAM_FORMAT_MASK) { case RK_PARAM_FORMAT_VEC3_FLOAT: - glVertexAttribFormat(layout, 3, GL_FLOAT, normalize, offset); - packer->pack = rk_pack_vec3; - packer->dst_incr = sizeof(rk_vec3); - packer->src_incr = sizeof(rk_vec3); + glVertexAttribFormat(layout++, 3, GL_FLOAT, GL_FALSE, offset); + packer->pack = rk_pack_vec3_float; + packer->src_incr = sizeof(rk_vec3_float); + packer->dst_incr = sizeof(rk_vec3_float); break; case RK_PARAM_FORMAT_VEC3_SHORT: - glVertexAttribFormat(layout, 3, GL_SHORT, normalize, offset); - if (normalize) { - packer->pack = rk_pack_vec3s_norm; + glVertexAttribFormat(layout++, 3, GL_SHORT, norm, offset); + if (norm) { + packer->pack = rk_pack_vec3_short_norm; } else { - packer->pack = rk_pack_vec3s; + packer->pack = rk_pack_vec3_short; } - packer->dst_incr = sizeof(rk_vec3s); - packer->src_incr = sizeof(rk_vec3); + packer->src_incr = sizeof(rk_vec3_float); + packer->dst_incr = sizeof(rk_vec3_short); break; case RK_PARAM_FORMAT_VEC3_INT10: - glVertexAttribFormat(layout, 4, GL_INT_2_10_10_10_REV, normalize, offset); - packer->pack = rk_pack_vec3_int10; - packer->dst_incr = sizeof(rk_int); - packer->src_incr = sizeof(rk_vec3); + glVertexAttribFormat(layout++, 4, GL_INT_2_10_10_10_REV, norm, offset); + if (norm) { + packer->pack = rk_pack_vec3_int10_norm; + } else { + packer->pack = rk_pack_vec3_int10; + } + packer->src_incr = sizeof(rk_vec3_float); + packer->dst_incr = sizeof(rk_vec3_int10); + break; + case RK_PARAM_FORMAT_MAT3_FLOAT: + glVertexAttribFormat(layout++, 3, GL_FLOAT, GL_FALSE, offset + offsetof(rk_mat3_float, x)); + glVertexAttribFormat(layout++, 3, GL_FLOAT, GL_FALSE, offset + offsetof(rk_mat3_float, y)); + glVertexAttribFormat(layout++, 3, GL_FLOAT, GL_FALSE, offset + offsetof(rk_mat3_float, z)); + packer->pack = rk_pack_mat3_float; + packer->src_incr = sizeof(rk_mat3_float); + packer->dst_incr = sizeof(rk_mat3_float); + break; + case RK_PARAM_FORMAT_MAT3_INT10: + glVertexAttribFormat(layout++, 4, GL_INT_2_10_10_10_REV, norm, offset + offsetof(rk_mat3_int10, x)); + glVertexAttribFormat(layout++, 4, GL_INT_2_10_10_10_REV, norm, offset + offsetof(rk_mat3_int10, y)); + glVertexAttribFormat(layout++, 4, GL_INT_2_10_10_10_REV, norm, offset + offsetof(rk_mat3_int10, z)); + if (norm) { + packer->pack = rk_pack_mat3_int10_norm; + } else { + packer->pack = rk_pack_mat3_int10; + } + packer->src_incr = sizeof(rk_mat3_float); + packer->dst_incr = sizeof(rk_mat3_int10); break; } offset += packer->dst_incr; - glVertexAttribBinding(layout, RK_PARAMS_BINDING); + } + for (unsigned attrib = vertices->layout; attrib < layout; ++attrib) { + glEnableVertexAttribArray(attrib); + glVertexAttribBinding(attrib, RK_PARAMS_BINDING); } glVertexBindingDivisor(RK_PARAMS_BINDING, 1); glBindVertexBuffer(RK_PARAMS_BINDING, batch->params_buffer, 0, batch->packed_size); @@ -580,8 +656,8 @@ static void rk_batch_pack( rk_pack_src src(¶ms[batch.params_size * (*index)]); for (rk_packer const * packer = batch.packers; packer < last_packer; ++packer) { packer->pack(dst, src); - dst.ptr += packer->dst_incr; src.ptr += packer->src_incr; + dst.ptr += packer->dst_incr; } } } diff --git a/cpp/render/render_opengles.hpp b/cpp/render/render_opengles.hpp index d3a1186..1ae4048 100644 --- a/cpp/render/render_opengles.hpp +++ b/cpp/render/render_opengles.hpp @@ -51,16 +51,37 @@ struct rk_vertices { GLuint indices; }; -struct rk_vec3s { +struct rk_vec3_float { + float x; + float y; + float z; +}; + +struct rk_vec3_short { rk_short x; rk_short y; rk_short z; rk_short pad; }; +typedef rk_int rk_vec3_int10; + +struct rk_mat3_float { + rk_vec3_float x; + rk_vec3_float y; + rk_vec3_float z; +}; + +struct rk_mat3_int10 { + rk_vec3_int10 x; + rk_vec3_int10 y; + rk_vec3_int10 z; +}; + union rk_pack_src { rk_ubyte const * __restrict ptr; - rk_vec3 const * __restrict vec3_ptr; + rk_vec3_float const * __restrict vec3_float; + rk_mat3_float const * __restrict mat3_float; inline rk_pack_src() {} inline rk_pack_src(rk_ubyte const * const __restrict src) : ptr(src) {} @@ -68,20 +89,22 @@ union rk_pack_src { union rk_pack_dst { rk_ubyte * __restrict ptr; - rk_vec3 * __restrict vec3_ptr; - rk_vec3s * __restrict vec3s_ptr; - rk_int * __restrict int_ptr; + rk_vec3_float * __restrict vec3_float; + rk_vec3_short * __restrict vec3_short; + rk_vec3_int10 * __restrict vec3_int10; + rk_mat3_float * __restrict mat3_float; + rk_mat3_int10 * __restrict mat3_int10; inline rk_pack_dst() {} inline rk_pack_dst(rk_ubyte * const __restrict dst) : ptr(dst) {} }; -typedef void (*rk_packer_fn)(rk_pack_dst, rk_pack_src); +typedef void (*rk_packer_fn)(rk_pack_dst const, rk_pack_src const); struct rk_packer { rk_packer_fn pack; - unsigned dst_incr; unsigned src_incr; + unsigned dst_incr; }; struct rk_command {