Add support for soft bodies
This commit is contained in:
@@ -6,12 +6,15 @@
|
|||||||
[com.badlogic.gdx.physics.bullet Bullet]
|
[com.badlogic.gdx.physics.bullet Bullet]
|
||||||
[com.badlogic.gdx.physics.bullet.collision btBoxShape
|
[com.badlogic.gdx.physics.bullet.collision btBoxShape
|
||||||
btCollisionDispatcher btCylinderShape btCollisionObject
|
btCollisionDispatcher btCylinderShape btCollisionObject
|
||||||
btCollisionWorld btDefaultCollisionConfiguration btDbvtBroadphase
|
btDefaultCollisionConfiguration btDbvtBroadphase
|
||||||
btSphereShape]
|
btSphereShape]
|
||||||
[com.badlogic.gdx.physics.bullet.dynamics btDiscreteDynamicsWorld
|
[com.badlogic.gdx.physics.bullet.dynamics btDiscreteDynamicsWorld
|
||||||
btDynamicsWorld btRigidBody btRigidBody$btRigidBodyConstructionInfo
|
btDynamicsWorld btRigidBody btRigidBody$btRigidBodyConstructionInfo
|
||||||
btSequentialImpulseConstraintSolver]
|
btSequentialImpulseConstraintSolver]
|
||||||
[com.badlogic.gdx.physics.bullet.linearmath btMotionState]))
|
[com.badlogic.gdx.physics.bullet.linearmath btMotionState]
|
||||||
|
[com.badlogic.gdx.physics.bullet.softbody btSoftBody
|
||||||
|
btSoftBodyRigidBodyCollisionConfiguration btSoftBodyWorldInfo
|
||||||
|
btSoftRigidDynamicsWorld]))
|
||||||
|
|
||||||
(def ^:private init (delay (Bullet/init)))
|
(def ^:private init (delay (Bullet/init)))
|
||||||
|
|
||||||
@@ -30,51 +33,47 @@
|
|||||||
:config config
|
:config config
|
||||||
:dispatcher dispatcher
|
:dispatcher dispatcher
|
||||||
:broadphase broad
|
:broadphase broad
|
||||||
:solver solver)))
|
:constraint-solver solver)))
|
||||||
|
|
||||||
|
(defn ^:private soft-rigid-dynamics
|
||||||
|
[]
|
||||||
|
(let [config (btSoftBodyRigidBodyCollisionConfiguration.)
|
||||||
|
dispatcher (btCollisionDispatcher. config)
|
||||||
|
broad (btDbvtBroadphase.)
|
||||||
|
solver (btSequentialImpulseConstraintSolver.)]
|
||||||
|
(assoc (World3D. (btSoftRigidDynamicsWorld. dispatcher broad solver config))
|
||||||
|
:config config
|
||||||
|
:dispatcher dispatcher
|
||||||
|
:broadphase broad
|
||||||
|
:constraint-solver solver)))
|
||||||
|
|
||||||
(defn bullet-3d*
|
(defn bullet-3d*
|
||||||
[type]
|
[type]
|
||||||
@init
|
@init
|
||||||
(case type
|
(case type
|
||||||
:discrete-dynamics (discrete-dynamics)
|
:rigid (discrete-dynamics)
|
||||||
|
:soft-rigid (soft-rigid-dynamics)
|
||||||
(u/throw-key-not-found type)))
|
(u/throw-key-not-found type)))
|
||||||
|
|
||||||
(defmacro bullet-3d
|
(defmacro bullet-3d
|
||||||
"Returns a world based on btCollisionWorld.
|
"Returns a world based on btDynamicsWorld.
|
||||||
|
|
||||||
(bullet-3d :discrete-dynamics)"
|
(bullet-3d :rigid) ; can only handle rigid bodies
|
||||||
|
(bullet-3d :soft-rigid) ; can handle soft and rigid bodies"
|
||||||
[type & options]
|
[type & options]
|
||||||
`(let [world# (bullet-3d* ~type)
|
`(let [world# (bullet-3d* ~type)
|
||||||
^btCollisionWorld object# (:object world#)]
|
^btDynamicsWorld object# (:object world#)]
|
||||||
(u/calls! object# ~@options)
|
(u/calls! object# ~@options)
|
||||||
world#))
|
world#))
|
||||||
|
|
||||||
(defmacro bullet-3d!
|
(defmacro bullet-3d!
|
||||||
"Calls a single method on a `bullet-3d`."
|
"Calls a single method on a `bullet-3d`."
|
||||||
[screen k & options]
|
[screen k & options]
|
||||||
`(let [^btCollisionWorld object# (:object (u/get-obj ~screen :world))]
|
`(let [^btDynamicsWorld object# (:object (u/get-obj ~screen :world))]
|
||||||
(u/call! object# ~k ~@options)))
|
(u/call! object# ~k ~@options)))
|
||||||
|
|
||||||
; bodies
|
; bodies
|
||||||
|
|
||||||
(defn basic-body*
|
|
||||||
[]
|
|
||||||
(Body3D. (btCollisionObject.)))
|
|
||||||
|
|
||||||
(defmacro basic-body
|
|
||||||
"Returns a body based on btCollisionObject."
|
|
||||||
[& options]
|
|
||||||
`(let [body# (basic-body*)
|
|
||||||
^btCollisionObject object# (:object body#)]
|
|
||||||
(u/calls! object# ~@options)
|
|
||||||
body#))
|
|
||||||
|
|
||||||
(defmacro basic-body!
|
|
||||||
"Calls a single method on a `basic-body`."
|
|
||||||
[object k & options]
|
|
||||||
`(let [^btCollisionObject object# (:object (u/get-obj ~object :body))]
|
|
||||||
(u/call! object# ~k ~@options)))
|
|
||||||
|
|
||||||
(defn rigid-body*
|
(defn rigid-body*
|
||||||
[info]
|
[info]
|
||||||
(assoc (Body3D. (btRigidBody. info))
|
(assoc (Body3D. (btRigidBody. info))
|
||||||
@@ -100,10 +99,29 @@
|
|||||||
(btRigidBody$btRigidBodyConstructionInfo.
|
(btRigidBody$btRigidBodyConstructionInfo.
|
||||||
mass motion-state collision-shape local-inertia))
|
mass motion-state collision-shape local-inertia))
|
||||||
|
|
||||||
(defmacro rigid-body-info!
|
(defn soft-body*
|
||||||
"Calls a single method on a `rigid-body-info`."
|
[info]
|
||||||
|
(assoc (Body3D. (btSoftBody. info))
|
||||||
|
:info info))
|
||||||
|
|
||||||
|
(defmacro soft-body
|
||||||
|
"Returns a body based on btSoftBody."
|
||||||
|
[info & options]
|
||||||
|
`(let [body# (soft-body* ~info)
|
||||||
|
^btSoftBody object# (:object body#)]
|
||||||
|
(u/calls! object# ~@options)
|
||||||
|
body#))
|
||||||
|
|
||||||
|
(defmacro soft-body!
|
||||||
|
"Calls a single method on a `soft-body`."
|
||||||
[object k & options]
|
[object k & options]
|
||||||
`(u/call! ^btRigidBody$btRigidBodyConstructionInfo ~object ~k ~@options))
|
`(let [^btSoftBody object# (:object (u/get-obj ~object :body))]
|
||||||
|
(u/call! object# ~k ~@options)))
|
||||||
|
|
||||||
|
(defn soft-body-info
|
||||||
|
"Returns a btSoftBodyWorldInfo."
|
||||||
|
[]
|
||||||
|
(btSoftBodyWorldInfo.))
|
||||||
|
|
||||||
(defn ^:private body-x
|
(defn ^:private body-x
|
||||||
[entity]
|
[entity]
|
||||||
@@ -195,8 +213,8 @@
|
|||||||
(cond
|
(cond
|
||||||
(isa? (type (:object body)) btRigidBody)
|
(isa? (type (:object body)) btRigidBody)
|
||||||
(bullet-3d! screen :add-rigid-body (:object body))
|
(bullet-3d! screen :add-rigid-body (:object body))
|
||||||
:else
|
(isa? (type (:object body)) btSoftBody)
|
||||||
(bullet-3d! screen :add-collision-object (:object body)))
|
(bullet-3d! screen :add-soft-body (:object body)))
|
||||||
body)
|
body)
|
||||||
|
|
||||||
(defn ^:private get-bodies
|
(defn ^:private get-bodies
|
||||||
@@ -208,31 +226,27 @@
|
|||||||
(defmethod c/update-physics!
|
(defmethod c/update-physics!
|
||||||
World3D
|
World3D
|
||||||
[screen & [entities]]
|
[screen & [entities]]
|
||||||
; initialize bodies
|
; initialize bodies if necessary
|
||||||
(doseq [e entities]
|
(doseq [e entities]
|
||||||
(let [object (u/get-obj e :object)
|
(let [object (u/get-obj e :object)
|
||||||
body (u/get-obj e :body)]
|
body (u/get-obj e :body)]
|
||||||
(when (and object body)
|
(when (and object (isa? (type (:object body)) btRigidBody))
|
||||||
(cond
|
(when-not (rigid-body! e :get-motion-state)
|
||||||
(isa? (type (:object body)) btRigidBody)
|
(->> (proxy [btMotionState] []
|
||||||
(when-not (rigid-body! e :get-motion-state)
|
(getWorldTransform [world-t])
|
||||||
(rigid-body! e
|
(setWorldTransform [world-t]
|
||||||
:set-motion-state
|
(m/matrix-4! (. object transform) :set world-t)))
|
||||||
(proxy [btMotionState] []
|
(rigid-body! e :set-motion-state))))))
|
||||||
(getWorldTransform [world-t])
|
|
||||||
(setWorldTransform [world-t]
|
|
||||||
(m/matrix-4! (. object transform) :set world-t)))))
|
|
||||||
:else
|
|
||||||
(basic-body! e :set-world-transform (. object transform))))))
|
|
||||||
; remove bodies that no longer exist
|
; remove bodies that no longer exist
|
||||||
(when entities
|
(when entities
|
||||||
(doseq [body (get-bodies screen)]
|
(doseq [^btCollisionObject body (get-bodies screen)]
|
||||||
(when-not (some #(= body (-> % :body :object)) entities)
|
(when-not (some #(= body (-> % :body :object)) entities)
|
||||||
(cond
|
(cond
|
||||||
(isa? (type body) btRigidBody)
|
(isa? (type body) btRigidBody)
|
||||||
(bullet-3d! screen :remove-rigid-body body)
|
(bullet-3d! screen :remove-rigid-body body)
|
||||||
:else
|
(isa? (type body) btSoftBody)
|
||||||
(bullet-3d! screen :remove-collision-object body))))))
|
(bullet-3d! screen :remove-soft-body body))
|
||||||
|
(.dispose body)))))
|
||||||
|
|
||||||
(defmethod c/step!
|
(defmethod c/step!
|
||||||
World3D
|
World3D
|
||||||
@@ -240,14 +254,13 @@
|
|||||||
:or {max-sub-steps 5 time-step (/ 1 60)}
|
:or {max-sub-steps 5 time-step (/ 1 60)}
|
||||||
:as screen}
|
:as screen}
|
||||||
& [entities]]
|
& [entities]]
|
||||||
(when (isa? (type (:object (u/get-obj screen :world))) btDynamicsWorld)
|
(bullet-3d! screen :step-simulation delta-time max-sub-steps time-step)
|
||||||
(bullet-3d! screen :step-simulation delta-time max-sub-steps time-step)
|
(when entities
|
||||||
(when entities
|
(map (fn [e]
|
||||||
(map (fn [e]
|
(if (u/get-obj e :body)
|
||||||
(if (u/get-obj e :body)
|
(assoc e
|
||||||
(assoc e
|
:x (body-x e)
|
||||||
:x (body-x e)
|
:y (body-y e)
|
||||||
:y (body-y e)
|
:z (body-z e))
|
||||||
:z (body-z e))
|
e))
|
||||||
e))
|
entities)))
|
||||||
entities))))
|
|
||||||
|
|||||||
Reference in New Issue
Block a user