Browse Source

Modernize saloon doors with motorized hinges

Josip Miskovic 2 months ago
parent
commit
0d99e0f9f8
1 changed files with 38 additions and 25 deletions
  1. 38 25
      examples/Physics/Saloon_Door/main.lua

+ 38 - 25
examples/Physics/Saloon_Door/main.lua

@@ -1,41 +1,54 @@
--- Saloon doors attached with hinge joint to frame, and with distance joint to each other
+-- Physics construct of saloon doors using the motorized hinge joint
 
 
 local world
 local world
-local door1, door2
+local doorR, doorL
+local passenger
 
 
 function lovr.load()
 function lovr.load()
   world = lovr.physics.newWorld(0, -9.8, 0, false)
   world = lovr.physics.newWorld(0, -9.8, 0, false)
   -- a static geometry that functions as door frame
   -- a static geometry that functions as door frame
-  local frame = world:newBoxCollider(vec3(0, -0.1, -1), vec3(2.2, 0.05, 0.2))
-  frame:setKinematic(true)
-  door1 = world:newBoxCollider(vec3( 0.55, 0.5, -1), vec3(1, 1, 0.2))
-  door2 = world:newBoxCollider(vec3(-0.55, 0.5, -1), vec3(1, 1, 0.2))
-  door1:setAngularDamping(0.01)
-  door2:setAngularDamping(0.01)
-  -- attach doors to frame, with hinges being oriented vertically (up vector is 0,1,0)
-  lovr.physics.newHingeJoint(frame, door1, vec3( 1, 0, -1), vec3(0,1,0))
-  lovr.physics.newHingeJoint(frame, door2, vec3(-1, 0, -1), vec3(0,1,0))
-  -- model door springiness by attaching loose distance joint between two doors
-  local joint = lovr.physics.newDistanceJoint(door1, door2, vec3(door1:getPosition()), vec3(door2:getPosition()))
-  joint:setTightness(0.2)
-  joint:setResponseTime(10)
-  lovr.graphics.setBackgroundColor(0.1, 0.1, 0.1)
+  doorR = world:newBoxCollider(vec3( 0.55, 0.5, -1), vec3(1, 1, 0.2))
+  doorL = world:newBoxCollider(vec3(-0.55, 0.5, -1), vec3(1, 1, 0.2))
+  -- attach doors with vertical hinges
+  local hingeR = lovr.physics.newHingeJoint(nil, doorR, vec3( 1, 0, -1), vec3(0,1,0))
+  local hingeL = lovr.physics.newHingeJoint(nil, doorL, vec3(-1, 0, -1), vec3(0,1,0))
+  -- set up motors to return the doors to their initial orientation
+  hingeR:setMotorMode('position')
+  hingeL:setMotorMode('position')
+  hingeR:setMotorTarget(0)
+  hingeL:setMotorTarget(0)
+  -- a controlled capsule that moves in and out pushing the door both ways
+  passenger = world:newCapsuleCollider(0, 0, 0,  0.4, 1)
+  passenger:getShape():setOffset(0, 0.5, 0,  math.pi/2, 1, 0, 0)
+  passenger:setKinematic(true)
+  passenger:moveKinematic(vec3(0, 0, -4), nil, 3)
 end
 end
 
 
 function lovr.draw(pass)
 function lovr.draw(pass)
-  for i, boxCollider in ipairs(world:getColliders()) do
+  for i, collider in ipairs(world:getColliders()) do
     pass:setColor(i / 3, i / 3, i / 3)
     pass:setColor(i / 3, i / 3, i / 3)
-    local pose = mat4(boxCollider:getPose())
-    local size = vec3(boxCollider:getShapes()[1]:getDimensions())
-    pass:box(pose:scale(size))
+    local shape = collider:getShape()
+    local pose = mat4(collider:getPose()) * mat4(shape:getOffset())
+    local shape_type = shape:getType()
+    if shape_type == 'box' then
+      local size = vec3(collider:getShape():getDimensions())
+      pass:box(pose:scale(size))
+    elseif shape_type == 'capsule' then
+      local l, r = shape:getLength(), shape:getRadius()
+      pose:scale(r, r, l)
+      pass:capsule(pose, segments)
+    end
   end
   end
 end
 end
 
 
 function lovr.update(dt)
 function lovr.update(dt)
-  world:update(dt)
-  -- every few seconds simulate a push
-  if lovr.timer.getTime() % 3 < dt then
-    door1:applyForce(0, 0, -50)
-    door2:applyForce(0, 0, -50)
+  local t = lovr.timer.getTime()
+  -- every 3 seconds change the moving direction of capsule collider
+  if t % 3 < dt then
+    local _, _, z = passenger:getPosition()
+    z = z > -1 and -4 or 2
+    -- moveKinematic is prefered over setPosition as it will correctly set the passenger's velocity
+    passenger:moveKinematic(vec3(0, 0, z), nil, 3)
   end
   end
+  world:update(dt)
 end
 end