Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when a Shape's center is inside a MeshShape, they're not reported as colliding #672

Closed
KelseyHigham opened this issue Jun 7, 2023 · 4 comments
Labels
bug uh oh

Comments

@KelseyHigham
Copy link
Contributor

demonstration

mesh-capsule-collision-bug.mp4

code for that demonstration

--                             ▄                       █      
--    ▄▀█ ▄▀▄ █▀▄ ▄▀▄ █▄▀ ▄▀█ ▀█▀ ▄▀▄    █▀▄▀▄ ▄▀▄ ▄▀▀ █▀▄    
--    ▀▄█ ▀█▄ █ █ ▀█▄ █   ▀▄█  ▀▄ ▀█▄    █ █ █ ▀█▄ ▄█▀ █ █    
--    ▄▄▀                                                     



local vertices = {
  {0, 0, 0},
  {1, 0, 0},
  {0, 1, 0},
  {0, 0, 1}
}
local indices = {
  1,3,2,
  1,2,4,
  1,4,3,
  2,3,4
}
local vertex_format = {
  {type = 'vec3', location = 'VertexPosition'}
}
local index_format = {
  {type = 'index16', location = 'VertexIndex'}
}
local triangle_buffer = lovr.graphics.newBuffer(vertices, vertex_format)
local index_buffer = lovr.graphics.newBuffer(indices, index_format)
local world = lovr.physics.newWorld()
local tetrahedron = world:newMeshCollider(vertices, indices)
tetrahedron:setPosition(0, 1, -1)
tetrahedron:setGravityIgnored(true)

capsule = world:newCapsuleCollider(0,0,0, .05, 1)
capsule:getShapes()[1]:setSensor(true)

left  = world:newSphereCollider(0,0,0, .05)
right = world:newSphereCollider(0,0,0, .05)



--      █               ▄▀▄     █ █ ▀   █            
--    ▄▀█ █▄▀ ▄▀█ █ █ █ █   ▄▀▄ █ █ █ ▄▀█ ▄▀▄ █▄▀    
--    ▀▄█ █   ▀▄█  █ █  ▀▄▀ ▀▄▀ █ █ █ ▀▄█ ▀█▄ █      
--    from Josip



function drawCollider(collider, pass)
  local shape = collider:getShapes()[1]
  local shapeType = shape:getType()
  local x,y,z, angle, ax,ay,az = collider:getPose()
  -- draw shape at collider's position with correct dimensions
  if shapeType == 'box' then
    local sx, sy, sz = shape:getDimensions()
    pass:box(x,y,z, sx,sy,sz, angle, ax,ay,az)
  elseif shapeType == 'sphere' then
    pass:sphere(x,y,z, shape:getRadius())
  elseif shapeType == 'cylinder' then
    local l, r = shape:getLength(), shape:getRadius()
    local x,y,z, angle, ax,ay,az = collider:getPose()
    pass:cylinder(x,y,z, r, l, angle, ax,ay,az)
  elseif shapeType == 'capsule' then
    local l, r = shape:getLength(), shape:getRadius()
    local x,y,z, angle, ax,ay,az = collider:getPose()
    local m = mat4(x,y,z, 1,1,1, angle, ax,ay,az)
    pass:cylinder(x,y,z, r, l, angle, ax,ay,az, false)
    pass:sphere(vec3(m:mul(0, 0,  l/2)), r)
    pass:sphere(vec3(m:mul(0, 0, -l/2)), r)
  end
end



--              █      ▄         
--    █ █ █▀▄ ▄▀█ ▄▀█ ▀█▀ ▄▀▄    
--    ▀▄█ █▄▀ ▀▄█ ▀▄█  ▀▄ ▀█▄    
--



function lovr.update(dt)
  -- position capsule between hands
  local leftPos  = vec3(lovr.headset.getPosition('left'))
  local rightPos = vec3(lovr.headset.getPosition('right'))
  local delta = rightPos - leftPos
  if delta:length() > 0 then
    capsule:getShapes()[1]:setLength(delta:length())
  end
  capsule:setPosition((leftPos + delta:mul(0.5)):unpack())
  local orientation = quat(vec3(delta):normalize())
  capsule:setOrientation(orientation)

  left:setPosition(vec3(lovr.headset.getPosition('left')))
  right:setPosition(lovr.headset.getPosition('right'))
end



--
--    ▄▀█ █▄▀ ▄▀█ █ █ █    
--    ▀▄█ █   ▀▄█  █ █     



function lovr.draw( pass )
  pass:setCullMode('back')
  pass:mesh(triangle_buffer, index_buffer, mat4(tetrahedron:getPose()))

  pass:setDepthWrite(false)

  pass:setColor(0,1,0,.5)
  if world:collide(tetrahedron:getShapes()[1], capsule:getShapes()[1]) then
    pass:setColor(1,0,0,.5)
  end
  drawCollider(capsule, pass)

  pass:setColor(0,1,0,.5)
  if world:collide(tetrahedron:getShapes()[1], left:getShapes()[1]) then
    pass:setColor(1,0,0,.5)
  end
  drawCollider(left, pass)

  pass:setColor(0,1,0,.5)
  if world:collide(tetrahedron:getShapes()[1], right:getShapes()[1]) then
    pass:setColor(1,0,0,.5)
  end
  drawCollider(right, pass)
end
@bjornbytes
Copy link
Owner

After some investigation in chat this seems to be an intentional behavior of ODE. ODE doesn't support the case where the center of mass of an object gets inside a triangle mesh. It's sort of like triangle meshes are considered "lists of triangles" instead of a solid object? The behavior is still surprising and not very friendly, to a point where this should be considered a bug. Some thoughts:

  • If no action is taken, this discovery should at the very least be documented as a limitation of the physics module.
  • ODE could be modified to detect intersections with triangles even when the shape's center is behind the triangle.
    • I think this would still fail to detect if a shape is entirely "inside" a mesh shape, so it's not really sufficient.
  • ODE has another shape which is a convex hull, which at a glance appears to be more efficient/robust.
    • If this replaced MeshShape then there would be a regression in functionality.
    • It could be added as a new Shape instead.
  • An attempt to "glue" together 2 mesh shapes with different windings was unsuccessful (ODE complained about mass)

@KelseyHigham
Copy link
Contributor Author

i think doing a combination of 1 and 2 would be a big improvement. i'm curious why ODE doesn't do 2 by default – would it mess up the normal calculation, and push shapes towards the inside of the mesh?

@bjornbytes
Copy link
Owner

JoltPhysics has a mBackFaceMode option that can be set when doing collision queries. It can be IgnoreBackFaces (the default) or CollideWithBackFaces 👀

@bjornbytes
Copy link
Owner

LÖVR uses Jolt now. MeshShapes still aren't treated as solid objects, by design. However A) there is a ConvexShape which is a solid shape that can be created from a triangle mesh and B) raycasts/shapecasts treat MeshShape triangles as being double-sided instead of single-sided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug uh oh
Projects
None yet
Development

No branches or pull requests

2 participants