mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-06 17:41:04 +00:00
more stuff
This commit is contained in:
parent
0b8edb8019
commit
3de3bead7b
6 changed files with 75 additions and 42 deletions
|
@ -4209,7 +4209,7 @@ Methods
|
||||||
`Rotation.compose()` is an alias for `Rotation.identity()`,
|
`Rotation.compose()` is an alias for `Rotation.identity()`,
|
||||||
`Rotation:compose()` copies the rotation.
|
`Rotation:compose()` copies the rotation.
|
||||||
* `Rotation:invert()`: Returns the inverse rotation.
|
* `Rotation:invert()`: Returns the inverse rotation.
|
||||||
* `Rotation:slerp(from, to, time)`: Interpolate from one rotation to another.
|
* `Rotation.slerp(from, to, time)`: Interpolate from one rotation to another.
|
||||||
* `time = 0` is all `from`, `time = 1` is all `to`.
|
* `time = 0` is all `from`, `time = 1` is all `to`.
|
||||||
* `Rotation:angle_to(other)`: Returns the absolute angle between two quaternions.
|
* `Rotation:angle_to(other)`: Returns the absolute angle between two quaternions.
|
||||||
* Useful to measure similarity.
|
* Useful to measure similarity.
|
||||||
|
|
|
@ -50,7 +50,7 @@ end
|
||||||
|
|
||||||
function test_env.it(name, func)
|
function test_env.it(name, func)
|
||||||
table.insert(full_test_name, name)
|
table.insert(full_test_name, name)
|
||||||
unittests.register(table.concat(full_test_name, " "), func, {})
|
unittests.register(table.concat(full_test_name, " "), func, {random = true})
|
||||||
table.remove(full_test_name)
|
table.remove(full_test_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ dofile(modpath .. "/color.lua")
|
||||||
|
|
||||||
local bustitute = dofile(modpath .. "/bustitute.lua")
|
local bustitute = dofile(modpath .. "/bustitute.lua")
|
||||||
bustitute.register("matrix4")
|
bustitute.register("matrix4")
|
||||||
|
bustitute.register("rotation")
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
local function describe(_, func)
|
local function assert_close(expected, got)
|
||||||
func()
|
if expected:angle_to(got) > 1e-3 then
|
||||||
|
error("expected +-" .. tostring(expected) .. " got " .. tostring(got))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function it(section_name, func)
|
local function assert_close_vec(expected, got)
|
||||||
print("Running test: " .. section_name)
|
if expected:distance(got) > 1e-4 then
|
||||||
func()
|
error("expected " .. tostring(expected) .. " got " .. tostring(got))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function assert_close(expected, actual)
|
local function srandom(n)
|
||||||
assert(expected:angle_to(actual) < 1e-4)
|
if n == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return 2 * math.random() - 1, srandom(n - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function random_rotation()
|
||||||
|
return Rotation.quaternion(srandom(4))
|
||||||
end
|
end
|
||||||
|
|
||||||
describe("constructors", function()
|
describe("constructors", function()
|
||||||
|
@ -17,13 +27,37 @@ describe("constructors", function()
|
||||||
assert.same({0, 0, 0, 1}, {rot:to_quaternion()})
|
assert.same({0, 0, 0, 1}, {rot:to_quaternion()})
|
||||||
end)
|
end)
|
||||||
it("quaternion", function()
|
it("quaternion", function()
|
||||||
local rot = Rotation.quaternion(0, 0, 0, 1)
|
assert_close(Rotation.identity(), Rotation.quaternion(0, 0, 0, 1))
|
||||||
assert_close(rot, Rotation.identity())
|
end)
|
||||||
|
it("axis-angle", function()
|
||||||
|
assert_close(Rotation.quaternion(1, 1, 1, 0),
|
||||||
|
Rotation.axis_angle(vector.new(1, 1, 1), math.pi))
|
||||||
end)
|
end)
|
||||||
it("axis angle", function() end)
|
|
||||||
it("axis-angle shorthands", function()
|
it("axis-angle shorthands", function()
|
||||||
|
local angle = math.pi
|
||||||
|
assert_close(Rotation.quaternion(1, 0, 0, 0), Rotation.x(angle))
|
||||||
|
assert_close(Rotation.quaternion(0, 1, 0, 0), Rotation.y(angle))
|
||||||
|
assert_close(Rotation.quaternion(0, 0, 1, 0), Rotation.z(angle))
|
||||||
end)
|
end)
|
||||||
|
it("euler angles", function()
|
||||||
|
local pitch, yaw, roll = 1, 2, 3
|
||||||
|
assert_close(Rotation.compose(Rotation.z(roll), Rotation.y(yaw), Rotation.x(pitch)),
|
||||||
|
Rotation.euler_angles(pitch, yaw, roll))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("conversions", function()
|
||||||
|
local function test_roundtrip(name)
|
||||||
|
it(name, function()
|
||||||
|
for _ = 1, 100 do
|
||||||
|
local rot = random_rotation()
|
||||||
|
assert_close(rot, Rotation[name](rot["to_" .. name](rot)))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
test_roundtrip("quaternion")
|
||||||
|
test_roundtrip("axis_angle")
|
||||||
|
test_roundtrip("euler_angles")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("composition", function()
|
describe("composition", function()
|
||||||
|
@ -35,33 +69,29 @@ describe("composition", function()
|
||||||
assert_close(rot, rot:compose())
|
assert_close(rot, rot:compose())
|
||||||
end)
|
end)
|
||||||
it("is consistent with application", function()
|
it("is consistent with application", function()
|
||||||
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function random_quaternion()
|
|
||||||
local x = math.random()
|
|
||||||
local y = math.random()
|
|
||||||
local z = math.random()
|
|
||||||
local w = math.random()
|
|
||||||
return Rotation.quaternion(x, y, z, w)
|
|
||||||
end
|
|
||||||
|
|
||||||
describe("inversion", function()
|
|
||||||
it("random quaternions", function()
|
|
||||||
for _ = 1, 100 do
|
for _ = 1, 100 do
|
||||||
local rot = random_quaternion()
|
local r1, r2 = random_rotation(), random_rotation()
|
||||||
assert_close(Rotation.identity(), rot:inverse():compose(rot))
|
local v = vector.new(srandom(3))
|
||||||
assert_close(Rotation.identity(), rot:compose(rot:inverse()))
|
assert_close_vec(r1:apply(r2:apply(v)), r1:compose(r2):apply(v))
|
||||||
end
|
|
||||||
end)
|
|
||||||
it("inverts the angle", function()
|
|
||||||
for _ = 1, 100 do
|
|
||||||
local rot = random_quaternion()
|
|
||||||
local axis, angle = rot:axis_angle()
|
|
||||||
local inv_axis, inv_angle = rot:inverse():axis_angle()
|
|
||||||
assert(axis:distance(inv_axis) < 1e-4)
|
|
||||||
assert(math.abs(angle + inv_angle) < 1e-4)
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("application", function()
|
||||||
|
assert_close_vec(vector.new(-2, 1, 3), Rotation.z(math.pi / 2):apply(vector.new(1, 2, 3)))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("inversion", function()
|
||||||
|
assert_close(Rotation.x(-math.pi / 2), Rotation.x(math.pi / 2):invert())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("slerp", function()
|
||||||
|
local from, to = Rotation.identity(), Rotation.x(2)
|
||||||
|
assert_close(Rotation.identity(), from:slerp(to, 0))
|
||||||
|
assert_close(Rotation.x(1), from:slerp(to, 0.5))
|
||||||
|
assert_close(Rotation.x(2), from:slerp(to, 1))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("tostring", function()
|
||||||
|
assert(type(tostring(Rotation.identity())) == "string")
|
||||||
|
end)
|
||||||
|
|
|
@ -219,7 +219,7 @@ public:
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const quaternion& q)
|
inline std::ostream& operator<<(std::ostream& os, const quaternion& q)
|
||||||
{
|
{
|
||||||
os << q.X << "\t" << q.Y << "\t" << q.Z << "\t" << q.W;
|
os << "(" << q.X << "\t" << q.Y << "\t" << q.Z << "\t" << q.W << ")";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,11 @@ int LuaRotation::l_fixed_axis_angle(lua_State *L)
|
||||||
|
|
||||||
int LuaRotation::l_euler_angles(lua_State *L)
|
int LuaRotation::l_euler_angles(lua_State *L)
|
||||||
{
|
{
|
||||||
v3f euler = readParam<v3f>(L, 1);
|
f32 pitch = readFiniteParam<f32>(L, 1);
|
||||||
|
f32 yaw = readFiniteParam<f32>(L, 2);
|
||||||
|
f32 roll = readFiniteParam<f32>(L, 3);
|
||||||
core::quaternion quaternion;
|
core::quaternion quaternion;
|
||||||
quaternion.set(euler.X, euler.Y, euler.Z);
|
quaternion.set(pitch, yaw, roll);
|
||||||
create(L, quaternion);
|
create(L, quaternion);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue