FFI'd color

This commit is contained in:
karai17 2016-07-23 23:16:10 -03:00
parent 864ac736de
commit 375f748c1f
3 changed files with 89 additions and 17 deletions

View File

@ -7,7 +7,9 @@ local color = {}
local color_mt = {}
local function new(r, g, b, a)
return setmetatable({ r, g, b, a }, color)
local c = { r, g, b, a }
c._c = c
return setmetatable(c, color)
end
-- HSV utilities (adapted from http://www.cs.rit.edu/~ncs/color/t_convert.html)
@ -93,6 +95,16 @@ local function color_to_hsv(c)
return { h, s, v, a }
end
-- Do the check to see if JIT is enabled. If so use the optimized FFI structs.
local status, ffi, the_type
if type(jit) == "table" and jit.status() then
status, ffi = pcall(require, "ffi")
if status then
ffi.cdef "typedef struct { double _c[4]; } cpml_color;"
new = ffi.typeof("cpml_color")
end
end
function color.new(r, g, b, a)
-- number, number, number, number
if r and g and b and a then
@ -254,11 +266,52 @@ function color.linear_to_gamma(r, g, b, a)
end
end
function color.is_color(a)
if type(a) == "cdata" then
return ffi.istype("cpml_color", a)
end
if type(a) ~= "table" then
return false
end
for i = 1, 4 do
if type(a[i]) ~= "number" then
return false
end
end
return true
end
function color.to_string(a)
return string.format("[ %3.0f, %3.0f, %3.0f, %3.0f ]", a[1], a[2], a[3], a[4])
end
color_mt.__index = color
function color_mt.__index(t, k)
if type(t) == "cdata" then
if type(k) == "number" then
return t._c[k-1]
end
elseif type(k) == "number" then
return t._c[k]
end
return rawget(color, k)
end
function color_mt.__newindex(t, k, v)
if type(t) == "cdata" then
if type(k) == "number" then
t._c[k-1] = v
end
elseif type(k) == "number" then
t._c[k] = v
end
rawset(color, k, v)
end
color_mt.__tostring = color.to_string
function color_mt.__call(_, r, g, b, a)
@ -283,4 +336,8 @@ function color_mt.__mul(a, b)
end
end
if status then
ffi.metatype(new, color_mt)
end
return setmetatable({}, color_mt)

View File

@ -79,8 +79,8 @@ function mat4.new(a)
return out
end
function mat4.identity()
return identity(new())
function mat4.identity(a)
return identity(a or new())
end
function mat4.from_angle_axis(angle, axis)
@ -399,16 +399,11 @@ function mat4.shear(out, a, yx, zx, xy, zy, xz, yz)
return out:mul(tmp, a)
end
local forward, side, new_up = vec3(), vec3(), vec3()
function mat4.look_at(out, a, eye, center, up)
local forward = vec3():normalize(center - eye)
local side = vec3()
:cross(forward, up)
:normalize(side)
local new_up = vec3()
:cross(side, forward)
:normalize(new_up)
forward:normalize(center - eye)
side:cross(forward, up):normalize(side)
new_up:cross(side, forward):normalize(new_up)
identity(tmp)
tmp[1] = side.x
@ -512,9 +507,9 @@ end
function mat4.to_string(a)
local str = "[ "
for i=1, 16 do
for i = 1, 16 do
str = str .. string.format("%+0.3f", a[i])
if i < #a then
if i < 16 then
str = str .. ", "
end
end
@ -641,7 +636,6 @@ function mat4.to_frustum(a, infinite)
return frustum
end
--mat4_mt.__index = mat4
function mat4_mt.__index(t, k)
if type(t) == "cdata" then
if type(k) == "number" then

View File

@ -212,6 +212,28 @@ describe("mat4:", function()
assert.is.equal(b[16], 4)
end)
it("tests shear", function()
local a = mat4()
local yx, zx, xy, zy, xz, yz = 1, 1, 1, -1, -1, -1
local b = mat4():shear(a, yx, zx, xy, zy, xz, yz)
assert.is.equal(b[1], 1)
assert.is.equal(b[2], 1)
assert.is.equal(b[3], 1)
assert.is.equal(b[4], 0)
assert.is.equal(b[5], 1)
assert.is.equal(b[6], 1)
assert.is.equal(b[7], -1)
assert.is.equal(b[8], 0)
assert.is.equal(b[9], -1)
assert.is.equal(b[10], -1)
assert.is.equal(b[11], 1)
assert.is.equal(b[12], 0)
assert.is.equal(b[13], 0)
assert.is.equal(b[14], 0)
assert.is.equal(b[15], 0)
assert.is.equal(b[16], 1)
end)
it("tests projections", function()
local a = mat4()
local b = mat4.from_perspective(45, 1, 0.1, 1000)
@ -275,7 +297,6 @@ end)
from_ortho
from_perspective
from_hmd_perspective
shear
look_at
to_frustum
--]]