123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- local function raycast(rayPos, rayDir, planePos, planeDir)
- local dot = rayDir:dot(planeDir)
- if math.abs(dot) < .001 then
- return nil
- else
- local distance = (planePos - rayPos):dot(planeDir) / dot
- if distance > 0 then
- return rayPos + rayDir * distance
- else
- return nil
- end
- end
- end
- local button = {
- text = 'Please click me',
- textSize = .1,
- count = 0,
- position = lovr.math.newVec3(0, 1, -3),
- width = 1.0,
- height = .4,
- hover = false,
- active = false
- }
- local tips = {}
- function lovr.update()
- button.hover, button.active = false, false
- for i, hand in ipairs(lovr.headset.getHands()) do
- tips[hand] = tips[hand] or lovr.math.newVec3()
- -- Ray info:
- local rayPosition = vec3(lovr.headset.getPosition(hand .. '/point'))
- local rayDirection = vec3(lovr.headset.getDirection(hand .. '/point'))
- -- Call the raycast helper function to get the intersection point of the ray and the button plane
- local hit = raycast(rayPosition, rayDirection, button.position, vec3(0, 0, 1))
- local inside = false
- if hit then
- local bx, by, bw, bh = button.position.x, button.position.y, button.width / 2, button.height / 2
- inside = (hit.x > bx - bw) and (hit.x < bx + bw) and (hit.y > by - bh) and (hit.y < by + bh)
- end
- -- If the ray intersects the plane, do a bounds test to make sure the x/y position of the hit
- -- is inside the button, then mark the button as hover/active based on the trigger state.
- if inside then
- if lovr.headset.isDown(hand, 'trigger') then
- button.active = true
- else
- button.hover = true
- end
- if lovr.headset.wasReleased(hand, 'trigger') then
- button.count = button.count + 1
- print('BOOP')
- end
- end
- -- Set the end position of the pointer. If the raycast produced a hit position then use that,
- -- otherwise extend the pointer's ray outwards by 50 meters and use it as the tip.
- tips[hand]:set(inside and hit or (rayPosition + rayDirection * 50))
- end
- end
- function lovr.draw(pass)
- -- Button background
- if button.active then
- pass:setColor(.4, .4, .4)
- elseif button.hover then
- pass:setColor(.2, .2, .2)
- else
- pass:setColor(.1, .1, .1)
- end
- pass:plane(button.position, button.width, button.height)
- -- Button text (add a small amount to the z to put the text slightly in front of button)
- pass:setColor(1, 1, 1)
- pass:text(button.text, button.position + vec3(0, 0, .001), button.textSize)
- pass:text('Count: ' .. button.count, button.position + vec3(0, .5, 0), .1)
- -- Pointers
- for hand, tip in pairs(tips) do
- local position = vec3(lovr.headset.getPosition(hand))
- pass:setColor(1, 1, 1)
- pass:sphere(position, .01)
- if button.active then
- pass:setColor(0, 1, 0)
- else
- pass:setColor(1, 0, 0)
- end
- pass:line(position, tip)
- end
- end
|