mirror of
https://github.com/luau-lang/luau.git
synced 2025-01-20 09:48:08 +00:00
292 lines
7.1 KiB
C++
292 lines
7.1 KiB
C++
|
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
||
|
#include "lualib.h"
|
||
|
|
||
|
#include "lcommon.h"
|
||
|
#include "lnumutils.h"
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
static int vector_create(lua_State* L)
|
||
|
{
|
||
|
double x = luaL_checknumber(L, 1);
|
||
|
double y = luaL_checknumber(L, 2);
|
||
|
double z = luaL_checknumber(L, 3);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
// checking argument count to avoid accepting 'nil' as a valid value
|
||
|
double w = lua_gettop(L) >= 4 ? luaL_checknumber(L, 4) : 0.0;
|
||
|
|
||
|
lua_pushvector(L, float(x), float(y), float(z), float(w));
|
||
|
#else
|
||
|
lua_pushvector(L, float(x), float(y), float(z));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_magnitude(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]));
|
||
|
#else
|
||
|
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_normalize(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
float invSqrt = 1.0f / sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
|
||
|
|
||
|
lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt, v[3] * invSqrt);
|
||
|
#else
|
||
|
float invSqrt = 1.0f / sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||
|
|
||
|
lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_cross(lua_State* L)
|
||
|
{
|
||
|
const float* a = luaL_checkvector(L, 1);
|
||
|
const float* b = luaL_checkvector(L, 2);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0f);
|
||
|
#else
|
||
|
lua_pushvector(L, a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_dot(lua_State* L)
|
||
|
{
|
||
|
const float* a = luaL_checkvector(L, 1);
|
||
|
const float* b = luaL_checkvector(L, 2);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushnumber(L, a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]);
|
||
|
#else
|
||
|
lua_pushnumber(L, a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_angle(lua_State* L)
|
||
|
{
|
||
|
const float* a = luaL_checkvector(L, 1);
|
||
|
const float* b = luaL_checkvector(L, 2);
|
||
|
const float* axis = luaL_optvector(L, 3, nullptr);
|
||
|
|
||
|
// cross(a, b)
|
||
|
float cross[] = {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]};
|
||
|
|
||
|
double sinA = sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]);
|
||
|
double cosA = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||
|
double angle = atan2(sinA, cosA);
|
||
|
|
||
|
if (axis)
|
||
|
{
|
||
|
if (cross[0] * axis[0] + cross[1] * axis[1] + cross[2] * axis[2] < 0.0f)
|
||
|
angle = -angle;
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(L, angle);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_floor(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, floorf(v[0]), floorf(v[1]), floorf(v[2]), floorf(v[3]));
|
||
|
#else
|
||
|
lua_pushvector(L, floorf(v[0]), floorf(v[1]), floorf(v[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_ceil(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, ceilf(v[0]), ceilf(v[1]), ceilf(v[2]), ceilf(v[3]));
|
||
|
#else
|
||
|
lua_pushvector(L, ceilf(v[0]), ceilf(v[1]), ceilf(v[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_abs(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, fabsf(v[0]), fabsf(v[1]), fabsf(v[2]), fabsf(v[3]));
|
||
|
#else
|
||
|
lua_pushvector(L, fabsf(v[0]), fabsf(v[1]), fabsf(v[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_sign(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, luaui_signf(v[0]), luaui_signf(v[1]), luaui_signf(v[2]), luaui_signf(v[3]));
|
||
|
#else
|
||
|
lua_pushvector(L, luaui_signf(v[0]), luaui_signf(v[1]), luaui_signf(v[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_clamp(lua_State* L)
|
||
|
{
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
const float* min = luaL_checkvector(L, 2);
|
||
|
const float* max = luaL_checkvector(L, 3);
|
||
|
|
||
|
luaL_argcheck(L, min[0] <= max[0], 3, "max.x must be greater than or equal to min.x");
|
||
|
luaL_argcheck(L, min[1] <= max[1], 3, "max.y must be greater than or equal to min.y");
|
||
|
luaL_argcheck(L, min[2] <= max[2], 3, "max.z must be greater than or equal to min.z");
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(
|
||
|
L,
|
||
|
luaui_clampf(v[0], min[0], max[0]),
|
||
|
luaui_clampf(v[1], min[1], max[1]),
|
||
|
luaui_clampf(v[2], min[2], max[2]),
|
||
|
luaui_clampf(v[3], min[3], max[3])
|
||
|
);
|
||
|
#else
|
||
|
lua_pushvector(L, luaui_clampf(v[0], min[0], max[0]), luaui_clampf(v[1], min[1], max[1]), luaui_clampf(v[2], min[2], max[2]));
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_min(lua_State* L)
|
||
|
{
|
||
|
int n = lua_gettop(L);
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
float result[] = {v[0], v[1], v[2], v[3]};
|
||
|
#else
|
||
|
float result[] = {v[0], v[1], v[2]};
|
||
|
#endif
|
||
|
|
||
|
for (int i = 2; i <= n; i++)
|
||
|
{
|
||
|
const float* b = luaL_checkvector(L, i);
|
||
|
|
||
|
if (b[0] < result[0])
|
||
|
result[0] = b[0];
|
||
|
if (b[1] < result[1])
|
||
|
result[1] = b[1];
|
||
|
if (b[2] < result[2])
|
||
|
result[2] = b[2];
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
if (b[3] < result[3])
|
||
|
result[3] = b[3];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, result[0], result[1], result[2], result[3]);
|
||
|
#else
|
||
|
lua_pushvector(L, result[0], result[1], result[2]);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int vector_max(lua_State* L)
|
||
|
{
|
||
|
int n = lua_gettop(L);
|
||
|
const float* v = luaL_checkvector(L, 1);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
float result[] = {v[0], v[1], v[2], v[3]};
|
||
|
#else
|
||
|
float result[] = {v[0], v[1], v[2]};
|
||
|
#endif
|
||
|
|
||
|
for (int i = 2; i <= n; i++)
|
||
|
{
|
||
|
const float* b = luaL_checkvector(L, i);
|
||
|
|
||
|
if (b[0] > result[0])
|
||
|
result[0] = b[0];
|
||
|
if (b[1] > result[1])
|
||
|
result[1] = b[1];
|
||
|
if (b[2] > result[2])
|
||
|
result[2] = b[2];
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
if (b[3] > result[3])
|
||
|
result[3] = b[3];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, result[0], result[1], result[2], result[3]);
|
||
|
#else
|
||
|
lua_pushvector(L, result[0], result[1], result[2]);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static const luaL_Reg vectorlib[] = {
|
||
|
{"create", vector_create},
|
||
|
{"magnitude", vector_magnitude},
|
||
|
{"normalize", vector_normalize},
|
||
|
{"cross", vector_cross},
|
||
|
{"dot", vector_dot},
|
||
|
{"angle", vector_angle},
|
||
|
{"floor", vector_floor},
|
||
|
{"ceil", vector_ceil},
|
||
|
{"abs", vector_abs},
|
||
|
{"sign", vector_sign},
|
||
|
{"clamp", vector_clamp},
|
||
|
{"max", vector_max},
|
||
|
{"min", vector_min},
|
||
|
{NULL, NULL},
|
||
|
};
|
||
|
|
||
|
int luaopen_vector(lua_State* L)
|
||
|
{
|
||
|
luaL_register(L, LUA_VECLIBNAME, vectorlib);
|
||
|
|
||
|
#if LUA_VECTOR_SIZE == 4
|
||
|
lua_pushvector(L, 0.0f, 0.0f, 0.0f, 0.0f);
|
||
|
lua_setfield(L, -2, "zero");
|
||
|
lua_pushvector(L, 1.0f, 1.0f, 1.0f, 1.0f);
|
||
|
lua_setfield(L, -2, "one");
|
||
|
#else
|
||
|
lua_pushvector(L, 0.0f, 0.0f, 0.0f);
|
||
|
lua_setfield(L, -2, "zero");
|
||
|
lua_pushvector(L, 1.0f, 1.0f, 1.0f);
|
||
|
lua_setfield(L, -2, "one");
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|