--column major! local love = assert( love ) local ffi = require('ffi') ffi.cdef[[ typedef struct{ float m[4][4]; } mat4_t ]] local ctype = ffi.typeof( "mat4_t*" ) local t = {} --this is actually the argument we need to send to shader:send --and to newMesh local data = love.data.newByteData( ffi.sizeof( "mat4_t" ) * 1024 ) t.data = data local ptr = data:getFFIPointer() print( "size", data:getSize() ) function t.__tostring( idx ) assert( idx < 1024 ) local ptr = ffi.cast( ctype, data:getFFIPointer() ) local m = ptr[ idx ].m return ([[ %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f ]]):format( m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]) end function t.lTRS( x, y, z, a, b, g, dx, dy, dz ) local c, s = math.cos, math.sin local ca, sa, cb, sb, cg, sg = c(a), s(a), c(b), s(b), c(g), s(g) return { {x*ca*cb, y*sa*cb, z*(-sb), 0}, {x*(ca*sb*sg - sa*cg), y*(sa*sb*sg+ca*cg), z*(cb*sg), 0}, {x*(ca*sb*cg+sa*sg), y*(sa*sb*cg-ca*sg), z*cb*cg, 0}, {dx, dy, dz, 1}} end function t.transpose( A ) for i = 1, 4 do for j = 1, 4 do A[i][j] = A[j][i] end end end function t.TRS( idx, x, y, z, a, b, g, dx, dy, dz ) assert( idx < 1024 ) local ptr = ffi.cast( ctype, data:getFFIPointer() ) local m = ptr[ idx ].m local c, s = math.cos, math.sin local ca, sa, cb, sb, cg, sg = c(a), s(a), c(b), s(b), c(g), s(g) m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], m[2][0], m[2][1], m[2][2], m[2][3], m[3][0], m[3][1], m[3][2], m[3][3] = x*ca*cb, x*(ca*sb*sg - sa*cg), x*(ca*sb*cg+sa*sg), dx, y*sa*cb, y*(sa*sb*sg+ca*cg), y*(sa*sb*cg-ca*sg), dy, z*(-sb), z*(cb*sg), z*cb*cg, dz, 0, 0, 0, 1 do local p, m = ptr, m end --keep alive return idx end function t.__mul( A, B ) local C = ffi.gc(cmat4(),nil) for j = 1, 4 do for i = 1, 4 do C.x[j][i] = A.x[1][i] * B.x[j][1] + A.x[2][i] * B.x[j][2] + A.x[3][i] * B.x[j][3] + A.x[4][i] * B.x[j][4] end end return C end function t.__add( A, B ) local C = cmat4() for i = 1, 4 do for j = 1, 4 do C[i][j] = A.x[i][j] + B.x[i][j] end end return C end function t.randomise( start, len ) start = start or 0 len = len or 1023 for i = start, start + len do t.TRS( i, --scale 1, 1, 1, 0, 0, 0, --pos 0, 0, -4 ) end end function t.id() local ptr = ffi.cast( ctype, data:getFFIPointer() ) for i = 1, 1024 do local m = ptr[ i ].m m[0][0], m[1][1], m[2][2], m[3][3] = 1, 1, 1, 1 do local p, m = ptr, m end --keep alive end end do --tests local math = math --[[ for i = 0, 1023 do t.TRS( i, 0.5 + math.random(), 0.5 + math.random(), 0.5 + math.random(), 2 * math.pi * math.random(), 2 * math.pi * math.random(), 2 * math.pi * math.random(), 10 * math.random(), 10 * math.random(), 10 * math.random() ) end]] end return t