summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/glm_bindings.c47
-rw-r--r--src/glm_bindings.h68
-rw-r--r--src/glm_mat3_bindings.c197
-rw-r--r--src/glm_mat4_bindings.c399
5 files changed, 710 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 96ca03d..aeeb8ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,8 @@ set(SOURCE_FILES
src/glm_bindings.c
src/glm_vec3_bindings.c
src/glm_vec4_bindings.c
+ src/glm_mat3_bindings.c
+ src/glm_mat4_bindings.c
src/camera.c
src/honey.c
src/input.c
diff --git a/src/glm_bindings.c b/src/glm_bindings.c
index 1eb3df1..41e1d4d 100644
--- a/src/glm_bindings.c
+++ b/src/glm_bindings.c
@@ -65,6 +65,50 @@ void honey_setup_glm(lua_State* L)
HONEY_FUNCTION, "__gc", honey_glm_array_destroy);
honey_glm_vec4_mt_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ /* mat3 metatable */
+ honey_lua_create_table
+ (L, 2,
+
+ HONEY_TABLE, "__index", 9,
+ HONEY_FUNCTION, "copyTo", honey_glm_mat3_copy,
+ HONEY_FUNCTION, "eye", honey_glm_mat3_eye,
+ HONEY_FUNCTION, "zero", honey_glm_mat3_zero,
+ HONEY_FUNCTION, "mul", honey_glm_mat3_mul,
+ HONEY_FUNCTION, "transpose", honey_glm_mat3_transpose,
+ HONEY_FUNCTION, "mulv", honey_glm_mat3_mulv,
+ HONEY_FUNCTION, "scale", honey_glm_mat3_scale,
+ HONEY_FUNCTION, "det", honey_glm_mat3_det,
+ HONEY_FUNCTION, "inv", honey_glm_mat3_inv,
+
+ HONEY_FUNCTION, "__gc", honey_glm_array_destroy);
+ honey_glm_mat3_mt_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* mat4 metatable */
+ honey_lua_create_table
+ (L, 2,
+
+ HONEY_TABLE, "__index", 16,
+ HONEY_FUNCTION, "copy", honey_glm_mat4_copy,
+ HONEY_FUNCTION, "eye", honey_glm_mat4_eye,
+ HONEY_FUNCTION, "zero", honey_glm_mat4_zero,
+ HONEY_FUNCTION, "mul", honey_glm_mat4_mul,
+ HONEY_FUNCTION, "transpose", honey_glm_mat4_transpose,
+ HONEY_FUNCTION, "mulv", honey_glm_mat4_mulv,
+ HONEY_FUNCTION, "scale", honey_glm_mat4_scale,
+ HONEY_FUNCTION, "det", honey_glm_mat4_det,
+ HONEY_FUNCTION, "inv", honey_glm_mat4_inv,
+ HONEY_FUNCTION, "translateX", honey_glm_translate_x,
+ HONEY_FUNCTION, "translateY", honey_glm_translate_y,
+ HONEY_FUNCTION, "translateZ", honey_glm_translate_z,
+ HONEY_FUNCTION, "scalev", honey_glm_scalev,
+ HONEY_FUNCTION, "rotateX", honey_glm_rotate_x,
+ HONEY_FUNCTION, "rotateY", honey_glm_rotate_y,
+ HONEY_FUNCTION, "rotateZ", honey_glm_rotate_z,
+ HONEY_FUNCTION, "rotate", honey_glm_rotate,
+
+ HONEY_FUNCTION, "__gc", honey_glm_array_destroy);
+ honey_glm_mat4_mt_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
/* glm table */
honey_lua_create_table
(L, 4,
@@ -167,6 +211,3 @@ int honey_glm_array_destroy(lua_State* L)
free(array->data);
return 0;
}
-
-
-
diff --git a/src/glm_bindings.h b/src/glm_bindings.h
index 45424ee..c9eaa91 100644
--- a/src/glm_bindings.h
+++ b/src/glm_bindings.h
@@ -120,4 +120,72 @@ int honey_glm_vec4_clamp(lua_State* L);
int honey_glm_vec4_lerp(lua_State* L);
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Mat3 Functions
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+int honey_glm_mat3_copy(lua_State* L);
+
+int honey_glm_mat3_eye(lua_State* L);
+
+int honey_glm_mat3_zero(lua_State* L);
+
+int honey_glm_mat3_mul(lua_State* L);
+
+int honey_glm_mat3_transpose(lua_State* L);
+
+int honey_glm_mat3_mulv(lua_State* L);
+
+int honey_glm_mat3_scale(lua_State* L);
+
+int honey_glm_mat3_det(lua_State* L);
+
+int honey_glm_mat3_inv(lua_State* L);
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Mat4 Functions
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+int honey_glm_mat4_copy(lua_State* L);
+
+int honey_glm_mat4_eye(lua_State* L);
+
+int honey_glm_mat4_zero(lua_State* L);
+
+int honey_glm_mat4_mul(lua_State* L);
+
+int honey_glm_mat4_transpose(lua_State* L);
+
+int honey_glm_mat4_mulv(lua_State* L);
+
+int honey_glm_mat4_scale(lua_State* L);
+
+int honey_glm_mat4_det(lua_State* L);
+
+int honey_glm_mat4_inv(lua_State* L);
+
+int honey_glm_translate(lua_State* L);
+
+int honey_glm_translate_x(lua_State* L);
+
+int honey_glm_translate_y(lua_State* L);
+
+int honey_glm_translate_z(lua_State* L);
+
+int honey_glm_scalev(lua_State* L);
+
+int honey_glm_rotate_x(lua_State* L);
+
+int honey_glm_rotate_y(lua_State* L);
+
+int honey_glm_rotate_z(lua_State* L);
+
+int honey_glm_rotate(lua_State* L);
+
#endif
diff --git a/src/glm_mat3_bindings.c b/src/glm_mat3_bindings.c
new file mode 100644
index 0000000..0222e47
--- /dev/null
+++ b/src/glm_mat3_bindings.c
@@ -0,0 +1,197 @@
+#include "glm_bindings.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Mat3 Functions
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+int honey_glm_mat3_copy(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ honey_lua_parse_arguments
+ (L, 1, 2,
+ HONEY_USERDATA, &self,
+ HONEY_USERDATA, &dest);
+
+ if (dest->type != MAT3)
+ honey_lua_throw_error
+ (L, "destination must be MAT3 (%d); got %d instead",
+ MAT3, dest->type);
+
+ glm_mat3_copy(self->data, dest->data);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_eye(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments
+ (L, 1, 1, HONEY_USERDATA, &self);
+
+ glm_mat3_identity(self->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_zero(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments
+ (L, 1, 1, HONEY_USERDATA, &self);
+
+ glm_mat3_zero(self->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_mul(lua_State* L)
+{
+ honey_glm_array* self, *mult, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &mult,
+ 3, HONEY_USERDATA, &self, HONEY_USERDATA, &mult, HONEY_USERDATA, &dest);
+
+ if (mult->type != MAT3)
+ honey_lua_throw_error
+ (L, "second matrix must be of type MAT3 (%d); got %d instead",
+ MAT3, mult->type);
+
+ if (choice == 1) {
+ if (dest->type != MAT3)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT3 (%d); got %d instead",
+ MAT3, dest->type);
+ }
+ else {
+ honey_glm_new_mat3(L);
+ dest = lua_touserdata(L, -1);
+ }
+
+ glm_mat3_mul(self->data, mult->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_transpose(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 1, HONEY_USERDATA, &self,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &dest);
+
+ if (choice == 1) {
+ if (dest->type != MAT3)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT3 (%d); got %d instead",
+ MAT3, dest->type);
+ }
+
+ if (choice == 0)
+ glm_mat3_transpose(self->data);
+ else
+ glm_mat3_transpose_to(self->data, dest->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_mulv(lua_State* L)
+{
+ honey_glm_array* self, *v, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &v,
+ 3, HONEY_USERDATA, &self, HONEY_USERDATA, &v, HONEY_USERDATA, &dest);
+
+ if (v->type != VEC3)
+ honey_lua_throw_error
+ (L, "vector must be of type VEC3 (%d); got %d instead",
+ VEC3, v->type);
+
+ if (choice == 0) {
+ honey_glm_new_vec3(L);
+ dest = lua_touserdata(L, -1);
+ }
+ else {
+ if (dest->type == MAT3)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT3 (%d); got %d instead",
+ MAT3, dest->type);
+ }
+
+ glm_mat3_mulv(self->data, v->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_scale(lua_State* L)
+{
+ honey_glm_array* self;
+ float s;
+ int choice = honey_lua_parse_arguments
+ (L, 1,
+ 2, HONEY_USERDATA, &self, HONEY_NUMBER, &s);
+
+ glm_mat3_scale(self->data, s);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_det(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments(L, 1, 1, HONEY_USERDATA, &self);
+
+ float det = glm_mat3_det(self->data);
+ lua_pushnumber(L, det);
+ return 1;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat3_inv(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 1, HONEY_USERDATA, &self,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &dest);
+
+ if (choice == 0) {
+ honey_glm_new_mat3(L);
+ dest = lua_touserdata(L, -1);
+ }
+ else {
+ if (dest->type == MAT3)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT3 (%d); got %d instead",
+ MAT3, dest->type);
+ }
+
+ glm_mat3_inv(self->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/src/glm_mat4_bindings.c b/src/glm_mat4_bindings.c
new file mode 100644
index 0000000..f10f954
--- /dev/null
+++ b/src/glm_mat4_bindings.c
@@ -0,0 +1,399 @@
+#include "glm_bindings.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Mat4 Functions
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+int honey_glm_mat4_copy(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ honey_lua_parse_arguments
+ (L, 1, 2,
+ HONEY_USERDATA, &self,
+ HONEY_USERDATA, &dest);
+
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination must be MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+
+ glm_mat4_copy(self->data, dest->data);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_eye(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments
+ (L, 1, 1, HONEY_USERDATA, &self);
+
+ glm_mat4_identity(self->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_zero(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments
+ (L, 1, 1, HONEY_USERDATA, &self);
+
+ glm_mat4_zero(self->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_mul(lua_State* L)
+{
+ honey_glm_array* self, *mult, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &mult,
+ 4, HONEY_USERDATA, &self, HONEY_USERDATA, &mult, HONEY_USERDATA, &dest);
+
+ if (mult->type != MAT4)
+ honey_lua_throw_error
+ (L, "second matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, mult->type);
+
+ if (choice == 1) {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+ else {
+ honey_glm_new_mat4(L);
+ dest = lua_touserdata(L, -1);
+ }
+
+ glm_mat4_mul(self->data, mult->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_transpose(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 1, HONEY_USERDATA, &self,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &dest);
+
+ if (choice == 1) {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ if (choice == 0)
+ glm_mat4_transpose(self->data);
+ else
+ glm_mat4_transpose_to(self->data, dest->data);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_mulv(lua_State* L)
+{
+ honey_glm_array* self, *v, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &v,
+ 4, HONEY_USERDATA, &self, HONEY_USERDATA, &v, HONEY_USERDATA, &dest);
+
+ if (v->type != VEC4)
+ honey_lua_throw_error
+ (L, "vector must be of type VEC4 (%d); got %d instead",
+ VEC4, v->type);
+
+ if (choice == 0) {
+ honey_glm_new_vec4(L);
+ dest = lua_touserdata(L, -1);
+ }
+ else {
+ if (dest->type == MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ glm_mat4_mulv(self->data, v->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_scale(lua_State* L)
+{
+ honey_glm_array* self;
+ float s;
+ int choice = honey_lua_parse_arguments
+ (L, 1,
+ 2, HONEY_USERDATA, &self, HONEY_NUMBER, &s);
+
+ glm_mat4_scale(self->data, s);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_det(lua_State* L)
+{
+ honey_glm_array* self;
+ honey_lua_parse_arguments(L, 1, 1, HONEY_USERDATA, &self);
+
+ float det = glm_mat4_det(self->data);
+ lua_pushnumber(L, det);
+ return 1;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_mat4_inv(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 1, HONEY_USERDATA, &self,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &dest);
+
+ if (choice == 0) {
+ honey_glm_new_mat4(L);
+ dest = lua_touserdata(L, -1);
+ }
+ else {
+ if (dest->type == MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ glm_mat4_inv(self->data, dest->data);
+
+ if (choice == 0)
+ return 1;
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Affine Transforms
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+int honey_glm_translate(lua_State* L)
+{
+ honey_glm_array *self, *v, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &v,
+ 3, HONEY_USERDATA, &self, HONEY_USERDATA, &v, HONEY_USERDATA, &dest);
+
+ if (v->type != VEC3)
+ honey_lua_throw_error
+ (L, "translation vector must be of type VEC3 (%d); got %d instead",
+ VEC3, v->type);
+
+ if (choice == 0) {
+ glm_translate(self->data, v->data);
+ }
+ else {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ glm_translate_to(self->data, v->data, dest->data);
+ }
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_translate_x(lua_State* L)
+{
+ honey_glm_array* self;
+ float s;
+ honey_lua_parse_arguments(L, 1, 2, HONEY_USERDATA, &self, HONEY_NUMBER, &s);
+
+ glm_translate_x(self->data, s);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_translate_y(lua_State* L)
+{
+ honey_glm_array* self;
+ float s;
+ honey_lua_parse_arguments(L, 1, 2, HONEY_USERDATA, &self, HONEY_NUMBER, &s);
+
+ glm_translate_y(self->data, s);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_translate_z(lua_State* L)
+{
+ honey_glm_array* self;
+ float s;
+ honey_lua_parse_arguments(L, 1, 2, HONEY_USERDATA, &self, HONEY_NUMBER, &s);
+
+ glm_translate_z(self->data, s);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_scalev(lua_State* L)
+{
+ honey_glm_array* self, *v, *dest;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_USERDATA, &v,
+ 3, HONEY_USERDATA, &self, HONEY_USERDATA, &v, HONEY_USERDATA, &dest);
+
+ if (v->type != VEC3)
+ honey_lua_throw_error
+ (L, "scale vector must be of type VEC3 (%d); got %d instead",
+ VEC3, v->type);
+
+ if (choice == 0)
+ glm_scale(self->data, v->data);
+ else {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+
+ glm_scale_to(self->data, v->data, dest->data);
+ }
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_rotate_x(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ float angle;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_NUMBER, &angle,
+ 3, HONEY_USERDATA, &self, HONEY_NUMBER, &angle, HONEY_USERDATA, &dest);
+
+ if (choice == 0)
+ dest = self;
+ else {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ glm_rotate_x(self->data, angle, dest->data);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_rotate_y(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ float angle;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_NUMBER, &angle,
+ 3, HONEY_USERDATA, &self, HONEY_NUMBER, &angle, HONEY_USERDATA, &dest);
+
+ if (choice == 0)
+ dest = self;
+ else {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ glm_rotate_y(self->data, angle, dest->data);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_rotate_z(lua_State* L)
+{
+ honey_glm_array* self, *dest;
+ float angle;
+ int choice = honey_lua_parse_arguments
+ (L, 2,
+ 2, HONEY_USERDATA, &self, HONEY_NUMBER, &angle,
+ 3, HONEY_USERDATA, &self, HONEY_NUMBER, &angle, HONEY_USERDATA, &dest);
+
+ if (choice == 0)
+ dest = self;
+ else {
+ if (dest->type != MAT4)
+ honey_lua_throw_error
+ (L, "destination matrix must be of type MAT4 (%d); got %d instead",
+ MAT4, dest->type);
+ }
+
+ glm_rotate_z(self->data, angle, dest->data);
+
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_glm_rotate(lua_State* L)
+{
+ honey_glm_array *self, *pivot, *axis;
+ float angle;
+ int choice = honey_lua_parse_arguments
+ (L, 1,
+ 4,
+ HONEY_USERDATA, &self, HONEY_USERDATA, &pivot,
+ HONEY_NUMBER, &angle, HONEY_USERDATA, &axis);
+
+ if (pivot->type != VEC3)
+ honey_lua_throw_error
+ (L, "pivot vector must be of type VEC3 (%d); got %d instead",
+ VEC3, pivot->type);
+
+ if (axis->type != VEC3)
+ honey_lua_throw_error
+ (L, "axis vector must be of type VEC3 (%d); got %d instead",
+ VEC3, axis->type);
+
+ glm_rotate_at(self->data, pivot->data, angle, axis->data);
+
+ return 0;
+}