bjornbytes / lovr

Lua Virtual Reality Framework
https://lovr.org
MIT License
2k stars 138 forks source link

Unexpected physics issues - box collider missing a corner #492

Closed ottworks closed 6 months ago

ottworks commented 3 years ago

Here are the issues I'm experiencing: https://user-images.githubusercontent.com/5253130/136295955-51616d9b-be93-4e0e-b5de-3a589bba6006.mp4

Here is the source code: tetra.zip

jmiskovic commented 3 years ago

I notice there are differences in the ways our drawCollider functions render the shapes. My version seems to match the underlying physics simulation. You could try to switch between the two and see differences in collider orientations.

-- call lovr.math.setRandomSeed(0) before looping over colliders in lovr.draw()

function drawCollider(collider)
  local userData = collider:getUserData()
  local shade = 0.4 + 0.4 * lovr.math.random()
  lovr.graphics.setColor(shade, shade, shade)
  local shape = collider:getShapes()[1]
  if false and shape:isSensor() then
    local r,g,b = lovr.graphics.getColor()
    lovr.graphics.setColor(r,g,b,0.8)
  end
  for _, shape in ipairs(collider:getShapes()) do
    local shapeType = shape:getType()
    local pose = mat4(collider:getPose()):translate(shape:getPosition()):rotate(shape:getOrientation())
    local x,y,z, _,_,_, angle, ax,ay,az = pose:unpack()
    -- draw primitive at collider's position with correct dimensions
    if shapeType == 'box' and shape then
      local sx, sy, sz = shape:getDimensions()
      lovr.graphics.box('fill', x,y,z, sx,sy,sz, angle, ax,ay,az)
    elseif shapeType == 'sphere' then
      local r = shape:getRadius()
      lovr.graphics.sphere(x,y,z, r)
    elseif shapeType == 'cylinder' then
      local l, r = shape:getLength(), shape:getRadius()
      lovr.graphics.cylinder(x,y,z, l, angle, ax,ay,az, r, r, true, 10)
    elseif shapeType == 'capsule' then
      local l, r = shape:getLength(), shape:getRadius()
      local m = mat4(x,y,z, 1,1,1, angle, ax,ay,az)
      lovr.graphics.cylinder(x,y,z, l, angle, ax,ay,az, r, r, false)
      lovr.graphics.sphere(vec3(m:mul(0, 0,  l/2)), r)
      lovr.graphics.sphere(vec3(m:mul(0, 0, -l/2)), r)
    end
  end
end

I haven't checked your manual calculation of mass and inertia tensor, that will become obsolete once the #490 is solved.

Then, if I increase the collider mass to 10, the physics seem to work smoother although still not correctly. This is most likely because the inertia tensor is not correctly computed from all the shapes.

We should probably merge this issue with #490.

ottworks commented 3 years ago

Thanks for the updated drawCollider code, this one works better with lighting. I've increased masses all around, and it does seem like the inertia tensor is incorrect, physical reactions to collisions are in the wrong direction (sometimes).

https://user-images.githubusercontent.com/5253130/137645871-ffc805d8-b357-431e-b218-61dd99960dcb.mp4

ottworks commented 3 years ago

Oops! setAngularDamping(0.01) fixed it! My sphere colliders were apparently spinning very rapidly. The only remaining problem is that my table is missing a corner.

bjornbytes commented 6 months ago

LÖVR uses Jolt instead of ODE now. The mass APIs are improved so this should be fixed.