main.lua 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. local function solve(root, target, control, lengths)
  2. local T = vec3(target - root)
  3. local C = vec3(control - root)
  4. local R = vec3(0)
  5. -- Basis
  6. local bx = vec3(T):normalize()
  7. local by = (C - bx * (C:dot(bx))):normalize()
  8. local bz = vec3(bx):cross(by)
  9. -- Matrix from basis
  10. local transform = mat4(
  11. bx.x, by.x, bz.x, 0,
  12. bx.y, by.y, bz.y, 0,
  13. bx.z, by.z, bz.z, 0,
  14. 0, 0, 0, 1
  15. ):transpose()
  16. local distance = #T
  17. local x = (distance + (lengths[1] ^ 2 - lengths[2] ^ 2) / distance) / 2
  18. local y = math.sqrt(lengths[1] ^ 2 - x ^ 2)
  19. local solution = vec4(x, y, 0, 1)
  20. return root + (transform * solution).xyz
  21. end
  22. function lovr.load()
  23. boneLengths = { .3, .3 }
  24. root = lovr.math.newVec3(-.2, 1.5, -.5)
  25. target = lovr.math.newVec3(.2, 1.5, -.7)
  26. control = lovr.math.newVec3(0, 1.8, -.6)
  27. pointSize = .04
  28. drags = {}
  29. end
  30. function lovr.update(dt)
  31. -- Allow hands to drag any of the points
  32. local points = { root, target, control }
  33. for i, hand in ipairs(lovr.headset.getHands()) do
  34. local handPosition = vec3(lovr.headset.getPosition(hand .. '/point'))
  35. if lovr.headset.wasPressed(hand, 'trigger') then
  36. for j, point in ipairs(points) do
  37. if handPosition:distance(point) < pointSize then
  38. drags[hand] = point
  39. end
  40. end
  41. elseif lovr.headset.wasReleased(hand, 'trigger') then
  42. drags[hand] = nil
  43. end
  44. if drags[hand] then
  45. drags[hand]:set(handPosition)
  46. end
  47. end
  48. end
  49. function lovr.draw(pass)
  50. -- Draw the joints and the control point
  51. pass:setColor(0xff80ff)
  52. pass:sphere(root, pointSize / 2)
  53. pass:sphere(target, pointSize / 2)
  54. pass:setColor(0x80ffff)
  55. pass:sphere(control, pointSize / 2)
  56. -- Draw the hand
  57. pass:setColor(0xffffff)
  58. for _, hand in ipairs(lovr.headset.getHands()) do
  59. pass:cube(mat4(lovr.headset.getPose(hand .. '/point')):scale(.01))
  60. end
  61. -- Draw a line from the root to the result from the IK solver, then to the target
  62. pass:line(root, solve(root, target, control, boneLengths), target)
  63. end