local glm = honey.glm local Vec3 = require 'honey.vec3' local module = {} setmetatable(module, {__index=_G}) setfenv(1, module) local RowLookup = {} function RowLookup.new(_, row, data) local self = { row=row, data=data, } setmetatable(self, RowLookup) return self end setmetatable(RowLookup, {__call=RowLookup.new}) function RowLookup.__index(self, col) return glm.mat4_get(self.data, col-1, self.row-1) end function RowLookup.__newindex(self, col, value) return glm.mat4_set(self.data, col-1, self.row-1, value) end Mat4 = {} function Mat4.new(_, self, values) local self = {} self.type = "mat4" self.data = glm.mat4_create() setmetatable(self, Mat4) if values then self[1][1] = values[1] self[1][2] = values[2] self[1][3] = values[3] self[1][4] = values[4] self[2][1] = values[5] self[2][2] = values[6] self[2][3] = values[7] self[2][4] = values[8] self[3][1] = values[9] self[3][2] = values[10] self[3][3] = values[11] self[3][4] = values[12] self[4][1] = values[13] self[4][2] = values[14] self[4][3] = values[15] self[4][4] = values[16] end return self end setmetatable(Mat4, {__call=Mat4.new}) function Mat4.__index(self, key) if type(key) == "number" then return RowLookup(key, self.data) else return Mat4[key] end end function Mat4.__tostring(self) return string.format( "/ %0.4f, %0.4f, %0.4f, %0.4f \\\n" .. "| %0.4f, %0.4f, %0.4f, %0.4f |\n" .. "| %0.4f, %0.4f, %0.4f, %0.4f |\n" .. "\\ %0.4f, %0.4f, %0.4f, %0.4f /", self[1][1], self[1][2], self[1][3], self[1][4], self[2][1], self[2][2], self[2][3], self[2][4], self[3][1], self[3][2], self[3][3], self[3][4], self[4][1], self[4][2], self[4][3], self[4][4] ) end function Mat4.__mul(self, other) if other.type == "mat4" then local dest = Mat4() glm.mat4_mul(self.data, other.data, dest.data) return dest elseif other.type == "vec4" then -- todo elseif other.type == "vec3" then local dest = Vec3() glm.mat4_mulv3(self.data, other.data, 1.0, dest.data) return dest else error(string.format("cannot multiply Mat4 by %s", type(other))) end end function Mat4.copyTo(self, dest) glm.mat4_copy(self.data, dest.data) end function Mat4.identity(self) glm.mat4_identity(self.data) return self end function Mat4.zero(self) glm.mat4_zero(self.data) return self end function Mat4.translate(self, vec) glm.translate(self.data, vec.data) return self end function Mat4.rotateX(self, angle) glm.rotate_x(self.data, angle, self.data) return self end function Mat4.rotateY(self, angle) glm.rotate_y(self.data, angle, self.data) return self end function Mat4.rotateZ(self, angle) glm.rotate_z(self.data, angle, self.data) return self end function Mat4.scale(self, vec) glm.scale(self.data, vec.data) return self end function Mat4.perspective(self, fovy, aspect, near, far) glm.perspective(fovy, aspect, near, far, self.data) return self end function Mat4.perspectiveResize(self, aspect) glm.perspective_resize(aspect, self.data) return self end return module.Mat4