diff --git a/src/api/l_vectors.c b/src/api/l_vectors.c index be33d32e..40cca6eb 100644 --- a/src/api/l_vectors.c +++ b/src/api/l_vectors.c @@ -1524,6 +1524,10 @@ static int l_lovrMat4Mul(lua_State* L) { mat4_transform(m, n); lua_settop(L, 2); return 1; + } else if (n && type == V_VEC4) { + mat4_multiplyVec4(m, n); + lua_settop(L, 2); + return 1; } else if (lua_type(L, 2) == LUA_TNUMBER) { float x = luaL_checknumber(L, 2); float y = luaL_optnumber(L, 3, 0.f); @@ -1648,14 +1652,20 @@ static int l_lovrMat4__mul(lua_State* L) { mat4 m = luax_checkvector(L, 1, V_MAT4, NULL); VectorType type; float* n = luax_tovector(L, 2, &type); - if (!n || type == V_QUAT) return luaL_typerror(L, 2, "mat4 or vec3"); + if (!n || (type == V_VEC2 || type == V_QUAT)) return luaL_typerror(L, 2, "mat4, vec3, or vec4"); if (type == V_MAT4) { mat4 out = luax_newtempvector(L, V_MAT4); mat4_multiply(mat4_init(out, m), n); - } else { + } else if (type == V_VEC3) { vec3 out = luax_newtempvector(L, V_VEC3); vec3_init(out, n); mat4_transform(m, n); + } else if (type == V_VEC4) { + float* out = luax_newtempvector(L, V_VEC4); + memcpy(out, n, 4 * sizeof(float)); + mat4_multiplyVec4(m, out); + } else { + lovrThrow("Unreachable"); } return 1; } diff --git a/src/core/maf.h b/src/core/maf.h index e4f96946..0f2949d8 100644 --- a/src/core/maf.h +++ b/src/core/maf.h @@ -513,6 +513,18 @@ MAF mat4 mat4_multiply(mat4 m, mat4 n) { return m; } +MAF float* mat4_multiplyVec4(mat4 m, float* v) { + float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12]; + float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13]; + float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14]; + float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15]; + v[0] = x; + v[1] = y; + v[2] = z; + v[3] = w; + return v; +} + MAF mat4 mat4_translate(mat4 m, float x, float y, float z) { m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];