From dc31605db6d9ad1cc070661d4b4256e5bab0a51a Mon Sep 17 00:00:00 2001 From: karai17 Date: Sun, 24 Jul 2016 23:42:44 -0300 Subject: [PATCH] Fixed mat4.look_at --- modules/mat4.lua | 65 ++++++++++++++++++++++++++++++++++++++++------ spec/mat4_spec.lua | 40 ++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/modules/mat4.lua b/modules/mat4.lua index 0ebee7a..c2a295c 100644 --- a/modules/mat4.lua +++ b/modules/mat4.lua @@ -101,11 +101,11 @@ function mat4.identity(a) return identity(a or new()) end +--- Create a matrix from an angle/axis pair. +-- @tparam number angle Angle of rotation +-- @tparam vec3 axis Axis of rotation +-- @treturn mat4 out function mat4.from_angle_axis(angle, axis) - if type(angle) == "table" then - angle, axis = angle:to_angle_axis() - end - local l = axis:len() if l == 0 then return new() @@ -123,6 +123,17 @@ function mat4.from_angle_axis(angle, axis) } end +--- Create a matrix from a quaternion. +-- @tparam quat q Rotation quaternion +-- @treturn mat4 out +function mat4.from_quaternion(q) + return mat4.from_angle_axis(q:to_angle_axis()) +end + +--- Create a matrix from a direction/up pair. +-- @tparam vec3 direction Vector direction +-- @tparam vec3 up Up direction +-- @treturn mat4 out function mat4.from_direction(direction, up) local forward = vec3():normalize(direction) @@ -149,6 +160,11 @@ function mat4.from_direction(direction, up) return out end +--- Create a matrix from a transform. +-- @tparam vec3 trans Translation vector +-- @tparam quat rot Rotation quaternion +-- @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() @@ -169,6 +185,14 @@ function mat4.from_transform(trans, rot, scale) } end +--- Create matrix from orthogonal. +-- @tparam number left +-- @tparam number right +-- @tparam number top +-- @tparam number bottom +-- @tparam number near +-- @tparam number far +-- @treturn mat4 out function mat4.from_ortho(left, right, top, bottom, near, far) local out = new() out[1] = 2 / (right - left) @@ -182,6 +206,12 @@ function mat4.from_ortho(left, right, top, bottom, near, far) return out end +--- Create matrix from perspective. +-- @tparam number fovy Field of view +-- @tparam number aspect Aspect ratio +-- @tparam number near Near plane +-- @tparam number far Far plane +-- @treturn mat4 out function mat4.from_perspective(fovy, aspect, near, far) assert(aspect ~= 0) assert(near ~= far) @@ -199,6 +229,13 @@ function mat4.from_perspective(fovy, aspect, near, far) end -- Adapted from the Oculus SDK. +--- Create matrix from HMD perspective. +-- @tparam number tanHalfFov Tangent of half of the field of view +-- @tparam number zNear Near plane +-- @tparam number zFar Far plane +-- @tparam boolean flipZ Z axis is flipped or not +-- @tparam boolean farAtInfinity Far plane is infinite or not +-- @treturn mat4 out function mat4.from_hmd_perspective(tanHalfFov, zNear, zFar, flipZ, farAtInfinity) -- CPML is right-handed and intended for GL, so these don't need to be arguments. local rightHanded = true @@ -460,10 +497,17 @@ function mat4.shear(out, a, yx, zx, xy, zy, xz, yz) return out:mul(tmp, a) end +--- Transform matrix to look at a point. +-- @tparam mat4 out Matrix to store result +-- @tparam mat4 a Matrix to transform +-- @tparam vec3 eye Location of viewer's view plane +-- @tparam vec3 center Location of object to view +-- @tparam vec3 up Up direction +-- @treturn mat4 out function mat4.look_at(out, a, eye, center, up) forward:normalize(center - eye) side:cross(forward, up):normalize(side) - new_up:cross(side, forward):normalize(new_up) + new_up:cross(side, forward) identity(tmp) tmp[1] = side.x @@ -475,11 +519,16 @@ function mat4.look_at(out, a, eye, center, up) tmp[3] = -forward.x tmp[7] = -forward.y tmp[11] = -forward.z + tmp[13] = -side:dot(eye) + tmp[14] = -new_up:dot(eye) + tmp[15] = forward:dot(eye) + tmp[16] = 1 + + for i = 1, 16 do + out[i] = tmp[i] + end return out - :translate(-eye - forward) - :mul(out, tmp) - :mul(out, a) end --- Transpose a matrix. diff --git a/spec/mat4_spec.lua b/spec/mat4_spec.lua index 7bac16e..a7b5ab1 100644 --- a/spec/mat4_spec.lua +++ b/spec/mat4_spec.lua @@ -98,6 +98,15 @@ describe("mat4:", function() assert.is.equal(1, a[16]) end) + it("creates a matrix from perspective", function() + local a = mat4.from_perspective(45, 1, 0.1, 1000) + assert.is_true(utils.tolerance( 2.414-a[1], 0.001)) + assert.is_true(utils.tolerance( 2.414-a[6], 0.001)) + assert.is_true(utils.tolerance(-1 -a[11], 0.001)) + assert.is_true(utils.tolerance(-1 -a[12], 0.001)) + assert.is_true(utils.tolerance(-0.2 -a[15], 0.001)) + end) + it("clones a matrix", function() local a = mat4.identity() local b = a:clone() @@ -263,6 +272,34 @@ describe("mat4:", function() assert.is_true(utils.tolerance(v.z-d.z, 0.001)) end) + it("transforms a matrix to look at a point", function() + local a = mat4() + local e = vec3(0, 0, 1.55) + local c = vec3(4, 7, 1) + local u = vec3(0, 0, 1) + local b = mat4():look_at(a, e, c, u) + + assert.is_true(utils.tolerance( 0.868-b[1], 0.001)) + assert.is_true(utils.tolerance( 0.034-b[2], 0.001)) + assert.is_true(utils.tolerance(-0.495-b[3], 0.001)) + assert.is_true(utils.tolerance( 0 -b[4], 0.001)) + + assert.is_true(utils.tolerance(-0.496-b[5], 0.001)) + assert.is_true(utils.tolerance( 0.059-b[6], 0.001)) + assert.is_true(utils.tolerance(-0.866-b[7], 0.001)) + assert.is_true(utils.tolerance( 0 -b[8], 0.001)) + + assert.is_true(utils.tolerance( 0 -b[9], 0.001)) + assert.is_true(utils.tolerance( 0.998-b[10], 0.001)) + assert.is_true(utils.tolerance( 0.068-b[11], 0.001)) + assert.is_true(utils.tolerance( 0 -b[12], 0.001)) + + assert.is_true(utils.tolerance( 0 -b[13], 0.001)) + assert.is_true(utils.tolerance(-1.546-b[14], 0.001)) + assert.is_true(utils.tolerance(-0.106-b[15], 0.001)) + assert.is_true(utils.tolerance( 1 -b[16], 0.001)) + end) + it("converts a matrix to vec4s", function() local a = mat4() local v = a:to_vec4s() @@ -367,10 +404,9 @@ end) --[[ from_angle_axis + from_quaternion from_direction from_transform from_ortho - from_perspective from_hmd_perspective - look_at --]]