vec3 has 4 elements;

This commit is contained in:
bjorn 2019-06-03 07:13:52 -07:00
parent 31e086edaf
commit 06c6b172de
17 changed files with 146 additions and 117 deletions

View File

@ -68,7 +68,7 @@ static int l_lovrAudioGetOrientation(lua_State* L) {
}
static int l_lovrAudioGetPose(lua_State* L) {
float position[3], orientation[4], angle, ax, ay, az;
float position[4], orientation[4], angle, ax, ay, az;
lovrAudioGetPosition(position);
lovrAudioGetOrientation(orientation);
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
@ -83,7 +83,7 @@ static int l_lovrAudioGetPose(lua_State* L) {
}
static int l_lovrAudioGetPosition(lua_State* L) {
float position[3];
float position[4];
lovrAudioGetPosition(position);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
@ -92,7 +92,7 @@ static int l_lovrAudioGetPosition(lua_State* L) {
}
static int l_lovrAudioGetVelocity(lua_State* L) {
float velocity[3];
float velocity[4];
lovrAudioGetVelocity(velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
@ -192,7 +192,7 @@ static int l_lovrAudioSetOrientation(lua_State* L) {
}
static int l_lovrAudioSetPose(lua_State* L) {
float position[3], orientation[4];
float position[4], orientation[4];
int index = 1;
index = luax_readvec3(L, index, position, NULL);
index = luax_readquat(L, index, orientation, NULL);
@ -202,14 +202,14 @@ static int l_lovrAudioSetPose(lua_State* L) {
}
static int l_lovrAudioSetPosition(lua_State* L) {
float position[3];
float position[4];
luax_readvec3(L, 1, position, NULL);
lovrAudioSetPosition(position);
return 0;
}
static int l_lovrAudioSetVelocity(lua_State* L) {
float velocity[3];
float velocity[4];
luax_readvec3(L, 1, velocity, NULL);
lovrAudioSetVelocity(velocity);
return 0;

View File

@ -5,7 +5,7 @@
static int l_lovrCurveEvaluate(lua_State* L) {
Curve* curve = luax_checktype(L, 1, Curve);
float t = luax_checkfloat(L, 2);
float point[3];
float point[4];
lovrCurveEvaluate(curve, t, point);
lua_pushnumber(L, point[0]);
lua_pushnumber(L, point[1]);
@ -16,7 +16,7 @@ static int l_lovrCurveEvaluate(lua_State* L) {
static int l_lovrCurveGetTangent(lua_State* L) {
Curve* curve = luax_checktype(L, 1, Curve);
float t = luax_checkfloat(L, 2);
float point[3];
float point[4];
lovrCurveGetTangent(curve, t, point);
lua_pushnumber(L, point[0]);
lua_pushnumber(L, point[1]);
@ -29,13 +29,17 @@ static int l_lovrCurveRender(lua_State* L) {
int n = luaL_optinteger(L, 2, 32);
float t1 = luax_optfloat(L, 3, 0.);
float t2 = luax_optfloat(L, 4, 1.);
float* points = malloc(3 * n * sizeof(float));
float* points = malloc(4 * n * sizeof(float));
lovrAssert(points, "Out of memory");
lovrCurveRender(curve, t1, t2, points, n);
lua_createtable(L, n, 0);
for (int i = 0; i < 3 * n; i++) {
lua_pushnumber(L, points[i]);
for (int i = 0; i < n; i += 4) {
lua_pushnumber(L, points[i + 0]);
lua_rawseti(L, -2, i + 1);
lua_pushnumber(L, points[i + 1]);
lua_rawseti(L, -2, i + 2);;
lua_pushnumber(L, points[i + 2]);
lua_rawseti(L, -2, i + 3);
}
free(points);
return 1;
@ -60,7 +64,7 @@ static int l_lovrCurveGetPoint(lua_State* L) {
Curve* curve = luax_checktype(L, 1, Curve);
int index = luaL_checkinteger(L, 2) - 1;
lovrAssert(index >= 0 && index < lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1);
float point[3];
float point[4];
lovrCurveGetPoint(curve, index, point);
lua_pushnumber(L, point[0]);
lua_pushnumber(L, point[1]);
@ -72,7 +76,7 @@ static int l_lovrCurveSetPoint(lua_State* L) {
Curve* curve = luax_checktype(L, 1, Curve);
int index = luaL_checkinteger(L, 2) - 1;
lovrAssert(index >= 0 && index < lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1);
float point[3];
float point[4];
luax_readvec3(L, 3, point, NULL);
lovrCurveSetPoint(curve, index, point);
return 0;
@ -80,7 +84,7 @@ static int l_lovrCurveSetPoint(lua_State* L) {
static int l_lovrCurveAddPoint(lua_State* L) {
Curve* curve = luax_checktype(L, 1, Curve);
float point[3];
float point[4];
int i = luax_readvec3(L, 2, point, NULL);
int index = lua_isnoneornil(L, i) ? lovrCurveGetPointCount(curve) : luaL_checkinteger(L, i) - 1;
lovrAssert(index >= 0 && index <= lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1);

View File

@ -658,7 +658,7 @@ static int l_lovrGraphicsOrigin(lua_State* L) {
}
static int l_lovrGraphicsTranslate(lua_State* L) {
float translation[3];
float translation[4];
luax_readvec3(L, 1, translation, NULL);
lovrGraphicsTranslate(translation);
return 0;
@ -672,7 +672,7 @@ static int l_lovrGraphicsRotate(lua_State* L) {
}
static int l_lovrGraphicsScale(lua_State* L) {
float scale[3];
float scale[4];
luax_readscale(L, 1, scale, 3, NULL);
lovrGraphicsScale(scale);
return 0;

View File

@ -243,7 +243,7 @@ static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) {
int l_lovrHeadsetGetPose(lua_State* L) {
Device device = luax_optdevice(L, 1);
float position[3], orientation[4];
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
float angle, ax, ay, az;
@ -263,7 +263,7 @@ int l_lovrHeadsetGetPose(lua_State* L) {
int l_lovrHeadsetGetPosition(lua_State* L) {
Device device = luax_optdevice(L, 1);
float position[3], orientation[4];
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
lua_pushnumber(L, position[0]);
@ -277,7 +277,7 @@ int l_lovrHeadsetGetPosition(lua_State* L) {
int l_lovrHeadsetGetOrientation(lua_State* L) {
Device device = luax_optdevice(L, 1);
float position[3], orientation[4];
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
float angle, ax, ay, az;
@ -294,10 +294,10 @@ int l_lovrHeadsetGetOrientation(lua_State* L) {
int l_lovrHeadsetGetDirection(lua_State* L) {
Device device = luax_optdevice(L, 1);
float position[3], orientation[4];
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getPose(device, position, orientation)) {
float v[3] = { 0.f, 0.f, -1.f };
float v[4] = { 0.f, 0.f, -1.f };
quat_rotate(orientation, v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
@ -311,7 +311,7 @@ int l_lovrHeadsetGetDirection(lua_State* L) {
int l_lovrHeadsetGetBonePose(lua_State* L) {
Device device = luax_optdevice(L, 1);
DeviceBone bone = luaL_checkoption(L, 2, NULL, DeviceBones);
float position[3], orientation[4];
float position[4], orientation[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getBonePose(device, bone, position, orientation)) {
float angle, ax, ay, az;
@ -331,7 +331,7 @@ int l_lovrHeadsetGetBonePose(lua_State* L) {
int l_lovrHeadsetGetVelocity(lua_State* L) {
Device device = luax_optdevice(L, 1);
float velocity[3], angularVelocity[3];
float velocity[4], angularVelocity[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(device, velocity, angularVelocity)) {
lua_pushnumber(L, velocity[0]);
@ -345,7 +345,7 @@ int l_lovrHeadsetGetVelocity(lua_State* L) {
int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
Device device = luax_optdevice(L, 1);
float velocity[3], angularVelocity[3];
float velocity[4], angularVelocity[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getVelocity(device, velocity, angularVelocity)) {
lua_pushnumber(L, angularVelocity[0]);
@ -359,7 +359,7 @@ int l_lovrHeadsetGetAngularVelocity(lua_State* L) {
int l_lovrHeadsetGetAcceleration(lua_State* L) {
Device device = luax_optdevice(L, 1);
float acceleration[3], angularAcceleration[3];
float acceleration[4], angularAcceleration[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getAcceleration(device, acceleration, angularAcceleration)) {
lua_pushnumber(L, acceleration[0]);
@ -373,7 +373,7 @@ int l_lovrHeadsetGetAcceleration(lua_State* L) {
int l_lovrHeadsetGetAngularAcceleration(lua_State* L) {
Device device = luax_optdevice(L, 1);
float acceleration[3], angularAcceleration[3];
float acceleration[4], angularAcceleration[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getAcceleration(device, acceleration, angularAcceleration)) {
lua_pushnumber(L, angularAcceleration[0]);
@ -414,7 +414,7 @@ int l_lovrHeadsetIsTouched(lua_State* L) {
int l_lovrHeadsetGetAxis(lua_State* L) {
Device device = luax_optdevice(L, 1);
DeviceAxis axis = luaL_checkoption(L, 2, NULL, DeviceAxes);
float value[3];
float value[4];
FOREACH_TRACKING_DRIVER(driver) {
if (driver->getAxis(device, axis, value)) {
switch (axis) {
@ -543,7 +543,7 @@ static int l_lovrHeadsetGetHands(lua_State* L) {
static int handIterator(lua_State* L) {
Device hands[] = { DEVICE_HAND_LEFT, DEVICE_HAND_RIGHT };
size_t index = lua_tointeger(L, lua_upvalueindex(1));
float position[3], orientation[4];
float position[4], orientation[4];
while (index < 2) {
FOREACH_TRACKING_DRIVER(driver) {

View File

@ -22,7 +22,7 @@ int luax_readmat4(lua_State* L, int index, mat4 m, int scaleComponents) {
} // Fall through
case LUA_TNUMBER: {
float S[3];
float S[4];
float R[4];
mat4_identity(m);
index = luax_readvec3(L, index, m + 12, "mat4, vec3, or number");
@ -44,7 +44,7 @@ static int l_lovrMat4Unpack(lua_State* L) {
return 16;
} else {
float angle, ax, ay, az;
float position[3], orientation[4], scale[3];
float position[4], orientation[4], scale[4];
mat4_getPosition(m, position);
mat4_getScale(m, scale);
mat4_getOrientation(m, orientation);
@ -150,7 +150,7 @@ static int l_lovrMat4Mul(lua_State* L) {
float x = luaL_checknumber(L, 2);
float y = luaL_optnumber(L, 3, 0.f);
float z = luaL_optnumber(L, 4, 0.f);
float v[3] = { x, y, z };
float v[4] = { x, y, z };
mat4_transform(m, v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);

View File

@ -96,7 +96,7 @@ static int l_lovrMathNewCurve(lua_State* L) {
lua_rawgeti(L, 1, i + 0);
lua_rawgeti(L, 1, i + 1);
lua_rawgeti(L, 1, i + 2);
float point[3];
float point[4];
int components = luax_readvec3(L, -3, point, "vec3 or number");
lovrCurveAddPoint(curve, point, pointIndex++);
i += 3 + components;
@ -105,7 +105,7 @@ static int l_lovrMathNewCurve(lua_State* L) {
} else {
int pointIndex = 0;
for (int i = 1; i <= top;) {
float point[3];
float point[4];
i = luax_readvec3(L, i, point, "vec3, number, or table");
lovrCurveAddPoint(curve, point, pointIndex++);
}
@ -136,9 +136,9 @@ static int l_lovrMathNewRandomGenerator(lua_State* L) {
}
static int l_lovrMathLookAt(lua_State* L) {
float from[3] = { luax_checkfloat(L, 1), luax_checkfloat(L, 2), luax_checkfloat(L, 3) };
float to[3] = { luax_checkfloat(L, 4), luax_checkfloat(L, 5), luax_checkfloat(L, 6) };
float up[3] = { luax_optfloat(L, 7, 0.f), luax_optfloat(L, 8, 1.f), luax_optfloat(L, 9, 0.f) };
float from[4] = { luax_checkfloat(L, 1), luax_checkfloat(L, 2), luax_checkfloat(L, 3) };
float to[4] = { luax_checkfloat(L, 4), luax_checkfloat(L, 5), luax_checkfloat(L, 6) };
float up[4] = { luax_optfloat(L, 7, 0.f), luax_optfloat(L, 8, 1.f), luax_optfloat(L, 9, 0.f) };
float m[16], q[4], angle, ax, ay, az;
mat4_lookAt(m, from, to, up);
quat_fromMat4(q, m);
@ -155,7 +155,7 @@ static int l_lovrMathOrientationToDirection(lua_State* L) {
float ax = luax_optfloat(L, 2, 0.f);
float ay = luax_optfloat(L, 3, 1.f);
float az = luax_optfloat(L, 4, 0.f);
float v[3];
float v[4];
lovrMathOrientationToDirection(angle, ax, ay, az, v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);

View File

@ -71,7 +71,7 @@ int l_lovrQuatSet(lua_State* L) {
vec3 u = luax_checkmathtype(L, 3, MATH_VEC3, "vec3");
quat_between(q, p, u);
} else {
quat_between(q, (float[3]) { 0.f, 0.f, -1.f }, p);
quat_between(q, (float[4]) { 0.f, 0.f, -1.f }, p);
}
} else if (type == MATH_QUAT) {
quat_init(q, p);

View File

@ -69,7 +69,7 @@ static int l_lovrSourceGetPitch(lua_State* L) {
}
static int l_lovrSourceGetPose(lua_State* L) {
float position[3], orientation[4], angle, ax, ay, az;
float position[4], orientation[4], angle, ax, ay, az;
Source* source = luax_checktype(L, 1, Source);
lovrSourceGetPosition(source, position);
lovrSourceGetOrientation(source, orientation);
@ -85,7 +85,7 @@ static int l_lovrSourceGetPose(lua_State* L) {
}
static int l_lovrSourceGetPosition(lua_State* L) {
float position[3];
float position[4];
lovrSourceGetPosition(luax_checktype(L, 1, Source), position);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
@ -106,7 +106,7 @@ static int l_lovrSourceGetType(lua_State* L) {
}
static int l_lovrSourceGetVelocity(lua_State* L) {
float velocity[3];
float velocity[4];
lovrSourceGetVelocity(luax_checktype(L, 1, Source), velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
@ -228,7 +228,7 @@ static int l_lovrSourceSetPitch(lua_State* L) {
}
static int l_lovrSourceSetPose(lua_State* L) {
float position[3], orientation[4];
float position[4], orientation[4];
int index = 2;
Source* source = luax_checktype(L, 1, Source);
index = luax_readvec3(L, index, position, NULL);
@ -240,7 +240,7 @@ static int l_lovrSourceSetPose(lua_State* L) {
static int l_lovrSourceSetPosition(lua_State* L) {
Source* source = luax_checktype(L, 1, Source);
float position[3];
float position[4];
luax_readvec3(L, 2, position, NULL);
lovrSourceSetPosition(source, position);
return 0;
@ -255,7 +255,7 @@ static int l_lovrSourceSetRelative(lua_State* L) {
static int l_lovrSourceSetVelocity(lua_State* L) {
Source* source = luax_checktype(L, 1, Source);
float velocity[3];
float velocity[4];
luax_readvec3(L, 2, velocity, NULL);
lovrSourceSetVelocity(source, velocity);
return 0;

View File

@ -66,7 +66,7 @@ static int l_lovrVec3Add(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
vec3_add(v, (float[3]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
vec3_add(v, (float[4]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
vec3_add(v, u);
@ -79,7 +79,7 @@ static int l_lovrVec3Sub(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
vec3_sub(v, (float[3]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
vec3_sub(v, (float[4]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
vec3_sub(v, u);

View File

@ -27,24 +27,29 @@ MAF vec3 vec3_set(vec3 v, float x, float y, float z) {
}
MAF vec3 vec3_init(vec3 v, const vec3 u) {
float x = u[0], y = u[1], z = u[2];
float x = u[0], y = u[1], z = u[2], w = u[3];
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}
MAF vec3 vec3_add(vec3 v, const vec3 u) {
v[0] += u[0];
v[1] += u[1];
v[2] += u[2];
float x = v[0] + u[0], y = v[1] + u[1], z = v[2] + u[2], w = v[3] + u[3];
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}
MAF vec3 vec3_sub(vec3 v, const vec3 u) {
v[0] -= u[0];
v[1] -= u[1];
v[2] -= u[2];
float x = v[0] - u[0], y = v[1] - u[1], z = v[2] - u[2], w = v[3] - u[3];
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}
@ -52,6 +57,7 @@ MAF vec3 vec3_scale(vec3 v, float s) {
v[0] *= s;
v[1] *= s;
v[2] *= s;
v[3] *= s;
return v;
}
@ -84,23 +90,38 @@ MAF vec3 vec3_cross(vec3 v, const vec3 u) {
}
MAF vec3 vec3_lerp(vec3 v, const vec3 u, float t) {
v[0] = v[0] + (u[0] - v[0]) * t;
v[1] = v[1] + (u[1] - v[1]) * t;
v[2] = v[2] + (u[2] - v[2]) * t;
float x = v[0] + (u[0] - v[0]) * t;
float y = v[1] + (u[1] - v[1]) * t;
float z = v[2] + (u[2] - v[2]) * t;
float w = v[3] + (u[3] - v[3]) * t;
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}
MAF vec3 vec3_min(vec3 v, const vec3 u) {
v[0] = MIN(v[0], u[0]);
v[1] = MIN(v[1], u[1]);
v[2] = MIN(v[2], u[2]);
float x = MIN(v[0], u[0]);
float y = MIN(v[1], u[1]);
float z = MIN(v[2], u[2]);
float w = MIN(v[3], u[3]);
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}
MAF vec3 vec3_max(vec3 v, const vec3 u) {
v[0] = MAX(v[0], u[0]);
v[1] = MAX(v[1], u[1]);
v[2] = MAX(v[2], u[2]);
float x = MAX(v[0], u[0]);
float y = MAX(v[1], u[1]);
float z = MAX(v[2], u[2]);
float w = MAX(v[3], u[3]);
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
return v;
}

View File

@ -179,8 +179,8 @@ void lovrAudioSetDopplerEffect(float factor, float speedOfSound) {
void lovrAudioSetOrientation(quat orientation) {
// Rotate the unit forward/up vectors by the quaternion derived from the specified angle/axis
float f[3] = { 0.f, 0.f, -1.f };
float u[3] = { 0.f, 1.f, 0.f };
float f[4] = { 0.f, 0.f, -1.f };
float u[4] = { 0.f, 1.f, 0.f };
quat_init(state.orientation, orientation);
quat_rotate(state.orientation, f);
quat_rotate(state.orientation, u);

View File

@ -87,7 +87,7 @@ uint32_t lovrSourceGetChannelCount(Source* source) {
}
void lovrSourceGetOrientation(Source* source, quat orientation) {
float v[3], forward[3] = { 0.f, 0.f, -1.f };
float v[4], forward[4] = { 0.f, 0.f, -1.f };
alGetSourcefv(source->id, AL_DIRECTION, v);
quat_between(orientation, forward, v);
}
@ -217,7 +217,7 @@ void lovrSourceSetCone(Source* source, float innerAngle, float outerAngle, float
}
void lovrSourceSetOrientation(Source* source, quat orientation) {
float v[3] = { 0.f, 0.f, -1.f };
float v[4] = { 0.f, 0.f, -1.f };
quat_rotate(orientation, v);
alSource3f(source->id, AL_DIRECTION, v[0], v[1], v[2]);
}

View File

@ -961,7 +961,7 @@ void lovrGraphicsCircle(DrawStyle style, Material* material, mat4 transform, int
}
void lovrGraphicsCylinder(Material* material, mat4 transform, float r1, float r2, bool capped, int segments) {
float length = vec3_length((float[3]) { transform[8], transform[9], transform[10] });
float length = vec3_length((float[4]) { transform[8], transform[9], transform[10] });
r1 /= length;
r2 /= length;

View File

@ -95,11 +95,11 @@ static bool leap_getPose(Device device, vec3 position, quat orientation) {
return false;
}
float direction[3];
float direction[4];
vec3_init(position, hand->palm.position.v);
vec3_init(direction, hand->palm.normal.v);
adjustPose(position, direction);
quat_between(orientation, (float[3]) { 0.f, 0.f, -1.f }, direction);
quat_between(orientation, (float[4]) { 0.f, 0.f, -1.f }, direction);
return true;
}
@ -118,7 +118,7 @@ static bool leap_getBonePose(Device device, DeviceBone bone, vec3 position, quat
// Assumes that enum values for non-tip bones are grouped by finger, and start after BONE_PINKY,
// could be less clever and use a switch if needed
float direction[3];
float direction[4];
if (bone <= BONE_PINKY) {
LEAP_DIGIT* finger = &hand->digits[bone];
vec3 base = finger->distal.prev_joint.v;
@ -136,7 +136,7 @@ static bool leap_getBonePose(Device device, DeviceBone bone, vec3 position, quat
}
adjustPose(position, direction);
quat_between(orientation, (float[3]) { 0.f, 0.f, -1.f }, direction);
quat_between(orientation, (float[4]) { 0.f, 0.f, -1.f }, direction);
return true;
}
@ -233,7 +233,7 @@ static void leap_update(float dt) {
}
}
float position[3], orientation[4];
float position[4], orientation[4];
if (lovrHeadsetDriver && lovrHeadsetDriver->getPose(DEVICE_HEAD, position, orientation)) {
mat4 m = state.headPose;
mat4_identity(m);

View File

@ -4,44 +4,48 @@
#include <math.h>
// Explicit curve evaluation, unroll simple cases to avoid pow overhead
static void evaluate(float* P, int n, float t, vec3 p) {
static void evaluate(float* restrict P, int n, float t, vec3 restrict p) {
if (n == 2) {
p[0] = P[0] + (P[3] - P[0]) * t;
p[1] = P[1] + (P[4] - P[1]) * t;
p[2] = P[2] + (P[5] - P[2]) * t;
p[0] = P[0] + (P[4] - P[0]) * t;
p[1] = P[1] + (P[5] - P[1]) * t;
p[2] = P[2] + (P[6] - P[2]) * t;
p[3] = P[3] + (P[7] - P[3]) * t;
} else if (n == 3) {
float t1 = (1 - t);
float a = t1 * t1;
float b = 2 * t1 * t;
float c = t * t;
p[0] = a * P[0] + b * P[3] + c * P[6];
p[1] = a * P[1] + b * P[4] + c * P[7];
p[2] = a * P[2] + b * P[5] + c * P[8];
p[0] = a * P[0] + b * P[4] + c * P[8];
p[1] = a * P[1] + b * P[5] + c * P[9];
p[2] = a * P[2] + b * P[6] + c * P[10];
p[3] = a * P[3] + b * P[7] + c * P[11];
} else if (n == 4) {
float t1 = (1 - t);
float a = t1 * t1 * t1;
float b = 3 * t1 * t1 * t;
float c = 3 * t1 * t * t;
float d = t * t * t;
p[0] = a * P[0] + b * P[3] + c * P[6] + d * P[9];
p[1] = a * P[1] + b * P[4] + c * P[7] + d * P[10];
p[2] = a * P[2] + b * P[5] + c * P[8] + d * P[11];
p[0] = a * P[0] + b * P[4] + c * P[8] + d * P[12];
p[1] = a * P[1] + b * P[5] + c * P[9] + d * P[13];
p[2] = a * P[2] + b * P[6] + c * P[10] + d * P[14];
p[3] = a * P[3] + b * P[7] + c * P[11] + d * P[15];
} else {
float b = 1.f;
p[0] = p[1] = p[2] = 0.f;
p[0] = p[1] = p[2] = p[3] = 0.f;
for (int i = 0; i < n; i++, b *= (float) (n - i) / i) {
float c1 = powf(1 - t, n - (i + 1));
float c2 = powf(t, i);
p[0] += b * c1 * c2 * P[i * 3 + 0];
p[1] += b * c1 * c2 * P[i * 3 + 1];
p[2] += b * c1 * c2 * P[i * 3 + 2];
p[0] += b * c1 * c2 * P[i * 4 + 0];
p[1] += b * c1 * c2 * P[i * 4 + 1];
p[2] += b * c1 * c2 * P[i * 4 + 2];
p[3] += b * c1 * c2 * P[i * 4 + 3];
}
}
}
Curve* lovrCurveInit(Curve* curve, int sizeHint) {
vec_init(&curve->points);
lovrAssert(!vec_reserve(&curve->points, sizeHint * 3), "Out of memory");
lovrAssert(!vec_reserve(&curve->points, sizeHint * 4), "Out of memory");
return curve;
}
@ -51,82 +55,82 @@ void lovrCurveDestroy(void* ref) {
}
void lovrCurveEvaluate(Curve* curve, float t, vec3 p) {
lovrAssert(curve->points.length >= 6, "Need at least 2 points to evaluate a Curve");
lovrAssert(t >= 0 && t <= 1, "Curve evaluation interval must be within [0, 1]");
evaluate(curve->points.data, curve->points.length / 3, t, p);
lovrAssert(curve->points.length >= 8, "Need at least 2 points to evaluate a Curve");
lovrAssert(t >= 0.f && t <= 1.f, "Curve evaluation interval must be within [0, 1]");
evaluate(curve->points.data, curve->points.length / 4, t, p);
}
void lovrCurveGetTangent(Curve* curve, float t, vec3 p) {
float q[3];
int n = curve->points.length / 3;
float q[4];
int n = curve->points.length / 4;
evaluate(curve->points.data, n - 1, t, q);
evaluate(curve->points.data + 3, n - 1, t, p);
vec3_add(p, vec3_scale(q, -1));
evaluate(curve->points.data + 4, n - 1, t, p);
vec3_add(p, vec3_scale(q, -1.f));
vec3_normalize(p);
}
void lovrCurveRender(Curve* curve, float t1, float t2, vec3 points, int n) {
lovrAssert(curve->points.length >= 6, "Need at least 2 points to render a Curve");
lovrAssert(t1 >= 0 && t2 <= 1, "Curve render interval must be within [0, 1]");
lovrAssert(curve->points.length >= 8, "Need at least 2 points to render a Curve");
lovrAssert(t1 >= 0.f && t2 <= 1.f, "Curve render interval must be within [0, 1]");
float step = 1.f / (n - 1);
for (int i = 0; i < n; i++) {
evaluate(curve->points.data, curve->points.length / 3, t1 + (t2 - t1) * i * step, points + 3 * i);
evaluate(curve->points.data, curve->points.length / 4, t1 + (t2 - t1) * i * step, points + 4 * i);
}
}
Curve* lovrCurveSlice(Curve* curve, float t1, float t2) {
lovrAssert(curve->points.length >= 6, "Need at least 2 points to slice a Curve");
lovrAssert(t1 >= 0 && t2 <= 1, "Curve slice interval must be within [0, 1]");
lovrAssert(curve->points.length >= 8, "Need at least 2 points to slice a Curve");
lovrAssert(t1 >= 0.f && t2 <= 1.f, "Curve slice interval must be within [0, 1]");
Curve* new = lovrCurveCreate(curve->points.length / 3);
Curve* new = lovrCurveCreate(curve->points.length / 4);
new->points.length = curve->points.length;
int n = curve->points.length / 3;
int n = curve->points.length / 4;
// Right half of split at t1
for (int i = 0; i < n - 1; i++) {
evaluate(curve->points.data + 3 * i, n - i, t1, new->points.data + 3 * i);
evaluate(curve->points.data + 4 * i, n - i, t1, new->points.data + 4 * i);
}
vec3_init(new->points.data + 3 * (n - 1), curve->points.data + 3 * (n - 1));
vec3_init(new->points.data + 4 * (n - 1), curve->points.data + 4 * (n - 1));
// Split segment at t2, taking left half
float t = (t2 - t1) / (1.f - t1);
for (int i = n - 1; i >= 1; i--) {
evaluate(new->points.data, i + 1, t, new->points.data + 3 * i);
evaluate(new->points.data, i + 1, t, new->points.data + 4 * i);
}
return new;
}
int lovrCurveGetPointCount(Curve* curve) {
return curve->points.length / 3;
return curve->points.length / 4;
}
void lovrCurveGetPoint(Curve* curve, int index, vec3 point) {
vec3_init(point, curve->points.data + 3 * index);
vec3_init(point, curve->points.data + 4 * index);
}
void lovrCurveSetPoint(Curve* curve, int index, vec3 point) {
vec3_init(curve->points.data + 3 * index, point);
vec3_init(curve->points.data + 4 * index, point);
}
void lovrCurveAddPoint(Curve* curve, vec3 point, int index) {
// Reserve enough memory for 3 more points, then record destination once memory is allocated
lovrAssert(!vec_reserve(&curve->points, curve->points.length + 3), "Out of memory");
float* dest = curve->points.data + index * 3;
// Reserve enough memory for 4 more floats, then record destination once memory is allocated
lovrAssert(!vec_reserve(&curve->points, curve->points.length + 4), "Out of memory");
float* dest = curve->points.data + index * 4;
// Shift remaining points over (if any) to create empty space
if (index * 3 != curve->points.length) {
memmove(dest + 3, dest, (curve->points.length - index * 3) * sizeof(float));
if (index * 4 != curve->points.length) {
memmove(dest + 4, dest, (curve->points.length - index * 4) * sizeof(float));
}
// Fill the empty space with the new point
curve->points.length += 3;
memcpy(dest, point, 3 * sizeof(float));
curve->points.length += 4;
memcpy(dest, point, 4 * sizeof(float));
}
void lovrCurveRemovePoint(Curve* curve, int index) {
vec_swapsplice(&curve->points, index * 3, 3);
vec_swapsplice(&curve->points, index * 4, 4);
}

View File

@ -299,7 +299,7 @@ local quat = {
if istype(vec3_t, y) then
C.quat_between(q, x, y)
else
local forward = new('float[3]', 0, 0, -1)
local forward = new('float[4]', 0, 0, -1)
C.quat_between(forward, x)
end
elseif istype(quat_t, x) then

View File

@ -612,7 +612,7 @@ unsigned char math_lua[] = {
0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x28, 0x27, 0x66, 0x6c, 0x6f, 0x61,
0x74, 0x5b, 0x33, 0x5d, 0x27, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
0x74, 0x5b, 0x34, 0x5d, 0x27, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
0x20, 0x2d, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x43, 0x2e, 0x71, 0x75, 0x61, 0x74, 0x5f, 0x62, 0x65, 0x74, 0x77,
0x65, 0x65, 0x6e, 0x28, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x2c,