123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- Xform = {}
- Xform.__index = Xform
- local function index_of(list, o)
- for i,v in pairs(list) do
- if v == o then
- return i
- end
- end
- end
- function remove(list, o)
- table.remove(list, index_of(list, o))
- return list
- end
- local function append(list, o)
- list[#list + 1] = o
- end
- local function copy_v3(s, t)
- t.x = s.x
- t.y = s.y
- t.z = s.z
- return t
- end
- local function copy_quat(s, t)
- t.x = s.x
- t.y = s.y
- t.z = s.z
- t.w = s.w
- return t
- end
- local function is_xform(o)
- return o['__members'] and o.__members.type == "Xform"
- end
- local function update(xform)
- xform.mat4:set(xform.position, xform.scale, xform.rotation)
- if xform.parent then
- xform.mat4:set(xform.parent.mat4 * xform.mat4)
- end
- for i, child in ipairs(xform.__members.children) do
- update(child)
- end
- end
- local function mount(child, parent)
- assert(parent == nil or is_xform(parent), "parent must be an Xform")
- local _parent = parent
- while _parent do
- assert(_parent ~= child, "cyclical scene graph")
- _parent = _parent.parent
- end
-
- if child['parent'] == parent then return end
- if child['parent'] and child.parent ~= parent then
- remove(child.parent.__members.children, child)
- end
- child.__members.parent = parent
- if parent then
- append(parent.__members.children, child)
- end
- update(child)
- end
- function Xform:new(position, scale, rotation)
- local o = {
- __members = {
- type = "Xform",
- mat4 = lovr.math.newMat4(),
- parent = nil,
- children = {},
- position = position and copy_v3(position, lovr.math.newVec3())
- or lovr.math.newVec3(),
- scale = scale and copy_v3(scale, lovr.math.newVec3(1))
- or lovr.math.newVec3(1),
- rotation = rotation and copy_quat(rotation, lovr.math.newQuat())
- or lovr.math.newQuat()
- }
- }
- setmetatable(o, Xform)
- update(o)
- return o
- end
- function Xform:__newindex(index, value)
- if index == "position" or index == "scale" then
- copy_v3(value, self.__members[index])
- update(self)
- elseif index == "rotation" then
- copy_quat(value, self.__members[index])
- update(self)
- elseif index == "parent" then
- mount(self, value)
- elseif index == "children" or
- index == "mat4" then
- elseif index ~= "__members" then
- rawset(self, index, value)
- end
- end
- function Xform:__index(index)
- if index == "children" then
- return {unpack(self.__members.children)}
- else
- return self.__members[index]
- end
- end
- return Xform
|