-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnode.lua
123 lines (106 loc) · 2.93 KB
/
node.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
-- A basic scenegraph node
local Node = {
selected = false,
parent = nil,
heldBy = nil,
}
local Node_mt = {
__index = Node
}
function Node:new(o)
o = o or {}
setmetatable(o, Node_mt)
o.transform = o.transform or lovr.math.newMat4()
o.size = o.size or lovr.math.newVec3(0.01, 0.01, 0.01)
o.offset = lovr.math.newMat4()
o.collider = letters.world:newBoxCollider(-o.size.x/2, -o.size.y/2, -o.size.z/2, o.size.x, o.size.y, o.size.z)
o.collider:setUserData(o)
o.children = {}
return o
end
function Node:addChild(c)
table.insert(self.children, c)
c.parent = self
return c
end
function Node:removeFromParent()
for i, c in ipairs(self.parent.children) do
if c == self then
table.remove(self.parent.children, i)
self.parent = nil
return
end
end
end
function Node:destroy()
for i, c in ipairs(self.children) do
c:destroy()
end
self.collider:destroy()
end
function Node:transformInWorld()
if self.parent then
return lovr.math.mat4(self.parent:transformInWorld()):mul(self.transform)
else
return lovr.math.mat4(self.transform)
end
end
function Node.convert(m, a, b)
local worldFromA = a and a:transformInWorld() or lovr.math.mat4()
local worldFromB = b and b:transformInWorld() or lovr.math.mat4()
local bFromWorld = worldFromB:invert()
local bFromA = bFromWorld * worldFromA
return bFromA * m
end
function Node:transformAndDraw()
lovr.graphics.push()
lovr.graphics.transform(self.transform)
self:draw()
for _, child in ipairs(self.children) do
child:transformAndDraw()
end
lovr.graphics.pop()
end
function Node:draw()
end
function Node:grab(hand)
if self.canBeGrabbed then
print("grab2")
self:ungrab(self.heldBy) -- if held by another hand
self.selected = true
self.heldBy = hand
local handTransform = lovr.math.mat4(letters.headset.getPose(hand.device))
self.offset:set(handTransform:invert()):mul(self:transformInWorld())
return true
end
return false
end
function Node:ungrab(hand)
if self.heldBy == hand then
self.selected = false
self.heldBy = nil
end
end
function Node:update()
if self.heldBy then
stickX, stickY = letters.headset.getAxis(self.heldBy.device, "thumbstick")
if math.abs(stickY) > 0.05 then
local translation = lovr.math.mat4():translate(0,0,-stickY*0.1)
local newOffset = translation * self.offset
if newOffset:mul(lovr.math.vec3()).z < 0 then
self.offset:set(newOffset)
end
end
local handTransform = lovr.math.mat4(letters.headset.getPose(self.heldBy.device))
local newInWorld = handTransform:mul(self.offset)
local newInLocal = Node.convert(newInWorld, nil, self.parent)
self.transform:set(newInLocal)
end
local x, y, z, w, h, d, a, ax, ay, az = self:transformInWorld():unpack()
w, h, d = self.size:unpack()
self.collider:setPose(x, y, z, a, ax, ay, az)
for _, child in ipairs(self.children) do
child:update()
end
end
return Node