Implement scale to mat4.from_transform method

This commit is contained in:
aki-cat 2021-12-10 00:31:57 -03:00
parent a3aacc354c
commit d7c257387d
2 changed files with 46 additions and 18 deletions

View File

@ -160,23 +160,29 @@ end
-- @tparam vec3 scale Scale vector
-- @treturn mat4 out
function mat4.from_transform(trans, rot, scale)
local angle, axis = rot:to_angle_axis()
local l = axis:len()
local rx, ry, rz, rw = rot.x, rot.y, rot.z, rot.w
if l == 0 then
return new()
end
local x, y, z = axis.x / l, axis.y / l, axis.z / l
local c = cos(angle)
local s = sin(angle)
return new {
x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0,
x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0,
x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0,
trans.x, trans.y, trans.z, 1
local sm = new {
scale.x, 0, 0, 0,
0, scale.y, 0, 0,
0, 0, scale.z, 0,
0, 0, 0, 1,
}
local rm = new {
1-2*(ry*ry+rz*rz), 2*(rx*ry-rz*rw), 2*(rx*rz+ry*rw), 0,
2*(rx*ry+rz*rw), 1-2*(rx*rx+rz*rz), 2*(ry*rz-rx*rw), 0,
2*(rx*rz-ry*rw), 2*(ry*rz+rx*rw), 1-2*(rx*rx+ry*ry), 0,
0, 0, 0, 1
}
local rsm = rm * sm
rsm[13] = trans.x
rsm[14] = trans.y
rsm[15] = trans.z
return rsm
end
--- Create matrix from orthogonal.

View File

@ -1,6 +1,8 @@
local mat4 = require "modules.mat4"
local vec3 = require "modules.vec3"
local utils = require "modules.utils"
local mat4 = require "modules.mat4"
local vec3 = require "modules.vec3"
local quat = require "modules.quat"
local utils = require "modules.utils"
local FLT_EPSILON = require("modules.constants").FLT_EPSILON
describe("mat4:", function()
it("creates an identity matrix", function()
@ -484,6 +486,26 @@ describe("mat4:", function()
)
assert.is.equal(s, a)
end)
it("creates a matrix out of transform values", function()
local scale = vec3(1, 2, 3)
local rot = quat.from_angle_axis(math.pi * 0.5, vec3(0, 1, 0))
local trans = vec3(3, 4, 5)
local a = mat4.from_transform(trans, rot, scale)
local v = vec3(-2, 3, 4)
-- scaled, rotated, then translated
-- v * mT * mR * mS
local result = a * v
local expected = vec3(-9, 10, 3)
-- float margin is considered
assert.is_true(math.abs(expected.x - result.x) < FLT_EPSILON)
assert.is_true(math.abs(expected.y - result.y) < FLT_EPSILON)
assert.is_true(math.abs(expected.z - result.z) < FLT_EPSILON)
end)
end)
--[[