main.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. -- left grip + right grip: grab VR space and move / stretch / rotate
  2. -- left grip + right grip + right trigger: reset the view
  3. local motion = {
  4. pose = lovr.math.newMat4(0,0,0, 1,1,1, 0, 0,1,0),
  5. left_anchor_vr = lovr.math.newVec3(),
  6. right_anchor_vr = lovr.math.newVec3(),
  7. }
  8. local palette = {0x0d2b45, 0x203c56, 0x544e68, 0x8d697a, 0xd08159, 0xffaa5e, 0xffd4a3, 0xffecd6}
  9. lovr.graphics.setBackgroundColor(palette[1])
  10. function lovr.update(dt)
  11. local left_vr = vec3(motion.pose:mul(lovr.headset.getPosition('hand/left')))
  12. local right_vr = vec3(motion.pose:mul(lovr.headset.getPosition('hand/right')))
  13. if lovr.headset.wasPressed('hand/left', 'grip') then
  14. motion.left_anchor_vr:set(left_vr)
  15. end
  16. if lovr.headset.wasPressed('hand/right', 'grip') then
  17. motion.right_anchor_vr:set(right_vr)
  18. end
  19. if lovr.headset.isDown('hand/left', 'grip') and
  20. lovr.headset.isDown('hand/right', 'grip') then
  21. local x, y, z, scale, _, _, angle, ax, ay, az = motion.pose:unpack()
  22. -- Scale: get the ratio of distances between anchors over current controllers distance
  23. local offset_scale = motion.left_anchor_vr:distance(motion.right_anchor_vr) / left_vr:distance(right_vr)
  24. offset_scale = 1 + (offset_scale - 1)
  25. scale = scale * offset_scale
  26. -- the change of scale must also affect the viewpoint location
  27. x, y, z = x * offset_scale, y * offset_scale, z * offset_scale
  28. -- Position: the mid-point of anchors is compared to midpoint of current controllers position
  29. local midpoint_anchor = vec3(motion.left_anchor_vr):lerp(motion.right_anchor_vr, 0.5)
  30. local midpoint_controller = vec3(left_vr):lerp(right_vr, 0.5)
  31. local offset_position = vec3(midpoint_anchor):sub(midpoint_controller)
  32. x, y, z = x + offset_position.x, y + offset_position.y, z + offset_position.z
  33. motion.pose:set(x, y, z, scale, scale, scale, angle, ax, ay, az) -- apply transition and scaling
  34. -- Rotation: get angle between current controllers and anchors in XZ
  35. local l_to_r_anchor = vec3(motion.right_anchor_vr):sub(motion.left_anchor_vr)
  36. local l_to_r_controller = vec3(right_vr):sub(left_vr)
  37. local sign = 1
  38. if vec3(l_to_r_controller):cross(vec3(l_to_r_anchor)):dot(vec3(0, 1, 0)) < 0 then
  39. sign = -1
  40. end
  41. l_to_r_anchor = l_to_r_anchor.xz:normalize()
  42. l_to_r_controller = l_to_r_controller.xz:normalize()
  43. local cos_angle = l_to_r_controller:dot(l_to_r_anchor)
  44. cos_angle = math.max(-1, math.min(1, cos_angle))
  45. local offset_rotation = math.acos(cos_angle) * sign
  46. motion.pose:rotate(offset_rotation, 0,1,0) -- apply rotation
  47. -- pose & anchor reset
  48. if lovr.headset.isDown('hand/right', 'trigger') then
  49. motion.pose:set()
  50. motion.left_anchor_vr:set(left_vr)
  51. motion.right_anchor_vr:set(right_vr)
  52. end
  53. end
  54. end
  55. function lovr.draw(pass)
  56. pass:transform(mat4(motion.pose):invert())
  57. -- Render hands
  58. for _, hand in ipairs(lovr.headset.getHands()) do
  59. -- Whenever pose of hand or head is used, need to account for VR movement
  60. local poseRW = mat4(lovr.headset.getPose(hand))
  61. local poseVR = mat4(motion.pose):mul(poseRW)
  62. if lovr.headset.isDown(hand, 'grip') then
  63. pass:setColor(palette[6])
  64. else
  65. pass:setColor(palette[8])
  66. end
  67. poseVR:scale(0.02)
  68. pass:sphere(poseVR)
  69. end
  70. -- An example scene
  71. local t = lovr.timer.getTime()
  72. pass:setCullMode('back')
  73. local step = 0.5
  74. for x = -5, 5, step do
  75. for z = -5, 5, step do
  76. local y = 0.5 * math.sin(t * 0.2 + (x * 0.5)^2 + (z * 0.5)^2)
  77. pass:setColor(palette[2 + math.floor(y * 10) % (#palette - 1)])
  78. pass:sphere(x, y, z, step / 2)
  79. end
  80. end
  81. end