body.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package physics
  5. import (
  6. "github.com/g3n/engine/graphic"
  7. "github.com/g3n/engine/math32"
  8. )
  9. // Body represents a physics-driven body.
  10. type Body struct {
  11. *graphic.Graphic // TODO future - embed core.Node instead and calculate properties recursively
  12. simulation *Simulation // Reference to the simulation the body is living in\
  13. material *Material // Physics material specifying friction and restitution
  14. index int
  15. // Mass properties
  16. mass float32 // Total mass
  17. invMass float32
  18. invMassEff float32 // Effective inverse mass
  19. // Rotational inertia and related properties
  20. rotInertia *math32.Matrix3 // Angular mass i.e. moment of inertia in local coordinates
  21. invRotInertia *math32.Matrix3 // Inverse rotational inertia in local coordinates
  22. invRotInertiaEff *math32.Matrix3 // Effective inverse rotational inertia in local coordinates
  23. invRotInertiaWorld *math32.Matrix3 // Inverse rotational inertia in world coordinates
  24. invRotInertiaWorldEff *math32.Matrix3 // Effective rotational inertia in world coordinates
  25. fixedRotation bool // Set to true if you don't want the body to rotate. Make sure to run .updateMassProperties() after changing this.
  26. // Position
  27. position *math32.Vector3 // World position of the center of gravity (World space position of the body.)
  28. initPosition *math32.Vector3 // Initial position of the body.
  29. prevPosition *math32.Vector3 // Previous position
  30. interpPosition *math32.Vector3 // Interpolated position of the body.
  31. // Rotation
  32. quaternion *math32.Quaternion // World space orientation of the body.
  33. initQuaternion *math32.Quaternion
  34. prevQuaternion *math32.Quaternion
  35. interpQuaternion *math32.Quaternion // Interpolated orientation of the body.
  36. // Linear and angular velocities
  37. velocity *math32.Vector3 // Linear velocity (World space velocity of the body.)
  38. initVelocity *math32.Vector3 // Initial linear velocity (World space velocity of the body.)
  39. angularVelocity *math32.Vector3 // Angular velocity of the body, in world space. Think of the angular velocity as a vector, which the body rotates around. The length of this vector determines how fast (in radians per second) the body rotates.
  40. initAngularVelocity *math32.Vector3
  41. // Force and torque
  42. force *math32.Vector3 // Linear force on the body in world space.
  43. torque *math32.Vector3 // World space rotational force on the body, around center of mass.
  44. // Damping and factors
  45. linearDamping float32
  46. angularDamping float32
  47. linearFactor *math32.Vector3 // Use this property to limit the motion along any world axis. (1,1,1) will allow motion along all axes while (0,0,0) allows none.
  48. angularFactor *math32.Vector3 // Use this property to limit the rotational motion along any world axis. (1,1,1) will allow rotation along all axes while (0,0,0) allows none.
  49. // Body type and sleep settings
  50. bodyType BodyType
  51. sleepState BodySleepState // Current sleep state.
  52. allowSleep bool // If true, the body will automatically fall to sleep.
  53. sleepSpeedLimit float32 // If the speed (the norm of the velocity) is smaller than this value, the body is considered sleepy.
  54. sleepTimeLimit float32 // If the body has been sleepy for this sleepTimeLimit seconds, it is considered sleeping.
  55. timeLastSleepy float32
  56. wakeUpAfterNarrowphase bool
  57. // Collision settings
  58. collisionFilterGroup int
  59. collisionFilterMask int
  60. collisionResponse bool // Whether to produce contact forces when in contact with other bodies. Note that contacts will be generated, but they will be disabled.
  61. aabb *math32.Box3 // World space bounding box of the body and its shapes.
  62. aabbNeedsUpdate bool // Indicates if the AABB needs to be updated before use.
  63. boundingRadius float32 // Total bounding radius of the body (TODO including its shapes, relative to body.position.)
  64. // TODO future (for now a body is a single graphic with a single geometry)
  65. // shapes []*Shape
  66. // shapeOffsets []float32 // Position of each Shape in the body, given in local Body space.
  67. // shapeOrientations [] ?
  68. }
  69. // BodyType specifies how the body is affected during the simulation.
  70. type BodyType int
  71. const (
  72. // A static body does not move during simulation and behaves as if it has infinite mass.
  73. // Static bodies can be moved manually by setting the position of the body.
  74. // The velocity of a static body is always zero.
  75. // Static bodies do not collide with other static or kinematic bodies.
  76. Static = BodyType(iota)
  77. // A kinematic body moves under simulation according to its velocity.
  78. // They do not respond to forces.
  79. // They can be moved manually, but normally a kinematic body is moved by setting its velocity.
  80. // A kinematic body behaves as if it has infinite mass.
  81. // Kinematic bodies do not collide with other static or kinematic bodies.
  82. Kinematic
  83. // A dynamic body is fully simulated.
  84. // Can be moved manually by the user, but normally they move according to forces.
  85. // A dynamic body can collide with all body types.
  86. // A dynamic body always has finite, non-zero mass.
  87. Dynamic
  88. )
  89. // BodyStatus specifies
  90. type BodySleepState int
  91. const (
  92. Awake = BodySleepState(iota)
  93. Sleepy
  94. Sleeping
  95. )
  96. // Events
  97. const (
  98. SleepyEvent = "physics.SleepyEvent" // Dispatched after a body has gone in to the sleepy state.
  99. SleepEvent = "physics.SleepEvent" // Dispatched after a body has fallen asleep.
  100. WakeUpEvent = "physics.WakeUpEvent" // Dispatched after a sleeping body has woken up.
  101. CollideEvent = "physics.CollideEvent" // Dispatched after two bodies collide. This event is dispatched on each of the two bodies involved in the collision.
  102. )
  103. // NewBody creates and returns a pointer to a new RigidBody.
  104. func NewBody(igraphic graphic.IGraphic) *Body {
  105. b := new(Body)
  106. b.Graphic = igraphic.GetGraphic()
  107. // TODO mass setter/getter
  108. b.mass = 1 // cannon.js default is 0
  109. if b.mass > 0 {
  110. b.invMass = 1.0 / b.mass
  111. } else {
  112. b.invMass = 0
  113. }
  114. b.bodyType = Dynamic // TODO auto set to Static if mass == 0
  115. // Rotational inertia and related properties
  116. b.rotInertia = math32.NewMatrix3()
  117. b.invRotInertia = math32.NewMatrix3()
  118. b.invRotInertiaEff = math32.NewMatrix3()
  119. b.invRotInertiaWorld = math32.NewMatrix3()
  120. b.invRotInertiaWorldEff = math32.NewMatrix3()
  121. // Position
  122. pos := b.GetNode().Position()
  123. b.position = pos.Clone()
  124. b.prevPosition = pos.Clone()
  125. b.interpPosition = pos.Clone()
  126. b.initPosition = pos.Clone()
  127. // Rotation
  128. quat := b.GetNode().Quaternion()
  129. b.quaternion = quat.Clone()
  130. b.prevQuaternion = quat.Clone()
  131. b.interpQuaternion = quat.Clone()
  132. b.initQuaternion = quat.Clone()
  133. // Linear and angular velocities
  134. b.velocity = math32.NewVec3()
  135. b.initVelocity = math32.NewVec3()
  136. b.angularVelocity = math32.NewVec3()
  137. b.initAngularVelocity = math32.NewVec3()
  138. // Force and torque
  139. b.force = math32.NewVec3()
  140. b.torque = math32.NewVec3()
  141. // Damping and factors
  142. b.linearDamping = 0.01
  143. b.angularDamping = 0.01
  144. b.linearFactor = math32.NewVector3(1, 1, 1)
  145. b.angularFactor = math32.NewVector3(1, 1, 1)
  146. b.allowSleep = true
  147. b.sleepState = Awake
  148. b.sleepSpeedLimit = 0.1
  149. b.sleepTimeLimit = 1
  150. b.timeLastSleepy = 0
  151. b.collisionFilterGroup = 1
  152. b.collisionFilterMask = -1
  153. b.wakeUpAfterNarrowphase = false
  154. b.UpdateMassProperties()
  155. return b
  156. }
  157. func (b *Body) InvMassEff() float32 {
  158. return b.invMassEff
  159. }
  160. func (b *Body) InvRotInertiaWorldEff() *math32.Matrix3 {
  161. return b.invRotInertiaWorldEff
  162. }
  163. func (b *Body) Position() math32.Vector3 {
  164. return *b.position
  165. }
  166. func (b *Body) Quaternion() *math32.Quaternion {
  167. return b.quaternion
  168. }
  169. func (b *Body) SetVelocity(vel *math32.Vector3) {
  170. b.velocity = vel
  171. }
  172. func (b *Body) Velocity() math32.Vector3 {
  173. return *b.velocity
  174. }
  175. func (b *Body) SetAngularVelocity(vel *math32.Vector3) {
  176. b.angularVelocity = vel
  177. }
  178. func (b *Body) AngularVelocity() math32.Vector3 {
  179. return *b.angularVelocity
  180. }
  181. func (b *Body) Force() math32.Vector3 {
  182. return *b.force
  183. }
  184. func (b *Body) Torque() math32.Vector3 {
  185. return *b.torque
  186. }
  187. func (b *Body) LinearDamping() float32 {
  188. return b.linearDamping
  189. }
  190. func (b *Body) AngularDamping() float32 {
  191. return b.angularDamping
  192. }
  193. func (b *Body) LinearFactor() *math32.Vector3 {
  194. return b.linearFactor
  195. }
  196. func (b *Body) AngularFactor() *math32.Vector3 {
  197. return b.angularFactor
  198. }
  199. // WakeUp wakes the body up.
  200. func (b *Body) WakeUp() {
  201. state := b.sleepState
  202. b.sleepState = Awake
  203. b.wakeUpAfterNarrowphase = false
  204. if state == Sleeping {
  205. b.Dispatch(WakeUpEvent, nil)
  206. }
  207. }
  208. // Sleep forces the body to sleep.
  209. func (b *Body) Sleep() {
  210. b.sleepState = Sleeping
  211. b.velocity.Set(0, 0, 0)
  212. b.angularVelocity.Set(0, 0, 0)
  213. b.wakeUpAfterNarrowphase = false
  214. }
  215. // Called every timestep to update internal sleep timer and change sleep state if needed.
  216. // time: The world time in seconds
  217. func (b *Body) SleepTick(time float32) {
  218. if b.allowSleep {
  219. speedSquared := b.velocity.LengthSq() + b.angularVelocity.LengthSq()
  220. speedLimitSquared := math32.Pow(b.sleepSpeedLimit, 2)
  221. if b.sleepState == Awake && speedSquared < speedLimitSquared {
  222. b.sleepState = Sleepy
  223. b.timeLastSleepy = time
  224. b.Dispatch(SleepyEvent, nil)
  225. } else if b.sleepState == Sleepy && speedSquared > speedLimitSquared {
  226. b.WakeUp() // Wake up
  227. } else if b.sleepState == Sleepy && (time-b.timeLastSleepy) > b.sleepTimeLimit {
  228. b.Sleep() // Sleeping
  229. b.Dispatch(SleepEvent, nil)
  230. }
  231. }
  232. }
  233. // PointToLocal converts a world point to local body frame. TODO maybe move to Node
  234. func (b *Body) PointToLocal(worldPoint *math32.Vector3) math32.Vector3 {
  235. return *worldPoint.Clone().Sub(b.position).ApplyQuaternion(b.quaternion.Conjugate())
  236. }
  237. // VectorToLocal converts a world vector to local body frame. TODO maybe move to Node
  238. func (b *Body) VectorToLocal(worldVector *math32.Vector3) math32.Vector3 {
  239. return *worldVector.Clone().ApplyQuaternion(b.quaternion.Conjugate())
  240. }
  241. // PointToWorld converts a local point to world frame. TODO maybe move to Node
  242. func (b *Body) PointToWorld(localPoint *math32.Vector3) math32.Vector3 {
  243. return *localPoint.Clone().ApplyQuaternion(b.quaternion).Add(b.position)
  244. }
  245. // VectorToWorld converts a local vector to world frame. TODO maybe move to Node
  246. func (b *Body) VectorToWorld(localVector *math32.Vector3) math32.Vector3 {
  247. return *localVector.Clone().ApplyQuaternion(b.quaternion)
  248. }
  249. // UpdateEffectiveMassProperties
  250. // If the body is sleeping, it should be immovable and thus have infinite mass during solve.
  251. // This is solved by having a separate "effective mass" and other "effective" properties
  252. func (b *Body) UpdateEffectiveMassProperties() {
  253. if b.sleepState == Sleeping || b.bodyType == Kinematic {
  254. b.invMassEff = 0
  255. b.invRotInertiaEff.Zero()
  256. b.invRotInertiaWorldEff.Zero()
  257. } else {
  258. b.invMassEff = b.invMass
  259. b.invRotInertiaEff.Copy(b.invRotInertia)
  260. b.invRotInertiaWorldEff.Copy(b.invRotInertiaWorld)
  261. }
  262. }
  263. // UpdateMassProperties
  264. // Should be called whenever you change the body shape or mass.
  265. func (b *Body) UpdateMassProperties() {
  266. // TODO getter of invMass ?
  267. if b.mass > 0 {
  268. b.invMass = 1.0 / b.mass
  269. } else {
  270. b.invMass = 0
  271. }
  272. if b.fixedRotation {
  273. b.rotInertia.Zero()
  274. b.invRotInertia.Zero()
  275. } else {
  276. *b.rotInertia = b.GetGeometry().RotationalInertia()
  277. b.invRotInertia.GetInverse(b.rotInertia)
  278. // Note: rotInertia is always positive definite and thus always invertible
  279. }
  280. b.UpdateInertiaWorld(true)
  281. }
  282. // Update .inertiaWorld and .invRotInertiaWorld
  283. func (b *Body) UpdateInertiaWorld(force bool) {
  284. iRI := b.invRotInertia
  285. // If rotational inertia M = s*I, where I is identity and s a scalar, then
  286. // R*M*R' = R*(s*I)*R' = s*R*I*R' = s*R*R' = s*I = M
  287. // where R is the rotation matrix.
  288. // In other words, we don't have to do the transformation if all diagonal entries are equal.
  289. if iRI[0] != iRI[4] || iRI[4] != iRI[8] || force {
  290. // iRIW = R * iRI * R'
  291. m1 := math32.NewMatrix3().MakeRotationFromQuaternion(b.quaternion)
  292. m2 := m1.Clone().Transpose()
  293. m2.Multiply(iRI)
  294. b.invRotInertiaWorld.MultiplyMatrices(m2, m1)
  295. }
  296. }
  297. // Apply force to a world point.
  298. // This could for example be a point on the Body surface.
  299. // Applying force this way will add to Body.force and Body.torque.
  300. // relativePoint: A point relative to the center of mass to apply the force on.
  301. func (b *Body) ApplyForce(force, relativePoint *math32.Vector3) {
  302. if b.bodyType != Dynamic { // Needed?
  303. return
  304. }
  305. // Add linear force
  306. b.force.Add(force) // TODO shouldn't rotational momentum be subtracted from linear momentum?
  307. // Add rotational force
  308. b.torque.Add(math32.NewVec3().CrossVectors(relativePoint, force))
  309. }
  310. // Apply force to a local point in the body.
  311. // force: The force vector to apply, defined locally in the body frame.
  312. // localPoint: A local point in the body to apply the force on.
  313. func (b *Body) ApplyLocalForce(localForce, localPoint *math32.Vector3) {
  314. if b.bodyType != Dynamic {
  315. return
  316. }
  317. // Transform the force vector to world space
  318. worldForce := b.VectorToWorld(localForce)
  319. relativePointWorld := b.VectorToWorld(localPoint)
  320. b.ApplyForce(&worldForce, &relativePointWorld)
  321. }
  322. // Apply impulse to a world point.
  323. // This could for example be a point on the Body surface.
  324. // An impulse is a force added to a body during a short period of time (impulse = force * time).
  325. // Impulses will be added to Body.velocity and Body.angularVelocity.
  326. // impulse: The amount of impulse to add.
  327. // relativePoint: A point relative to the center of mass to apply the force on.
  328. func (b *Body) ApplyImpulse(impulse, relativePoint *math32.Vector3) {
  329. if b.bodyType != Dynamic {
  330. return
  331. }
  332. // Compute point position relative to the body center
  333. r := relativePoint
  334. // Compute produced central impulse velocity
  335. velo := impulse.Clone().MultiplyScalar(b.invMass)
  336. // Add linear impulse
  337. b.velocity.Add(velo)
  338. // Compute produced rotational impulse velocity
  339. rotVelo := math32.NewVec3().CrossVectors(r, impulse)
  340. rotVelo.ApplyMatrix3(b.invRotInertiaWorld)
  341. // Add rotational Impulse
  342. b.angularVelocity.Add(rotVelo)
  343. }
  344. // Apply locally-defined impulse to a local point in the body.
  345. // force: The force vector to apply, defined locally in the body frame.
  346. // localPoint: A local point in the body to apply the force on.
  347. func (b *Body) ApplyLocalImpulse(localImpulse, localPoint *math32.Vector3) {
  348. if b.bodyType != Dynamic {
  349. return
  350. }
  351. // Transform the force vector to world space
  352. worldImpulse := b.VectorToWorld(localImpulse)
  353. relativePointWorld := b.VectorToWorld(localPoint)
  354. b.ApplyImpulse(&worldImpulse, &relativePointWorld)
  355. }
  356. // Get world velocity of a point in the body.
  357. func (b *Body) GetVelocityAtWorldPoint(worldPoint *math32.Vector3) *math32.Vector3 {
  358. r := math32.NewVec3().SubVectors(worldPoint, b.position)
  359. r.CrossVectors(b.angularVelocity, r)
  360. r.Add(b.velocity)
  361. return r
  362. }
  363. // Move the body forward in time.
  364. // dt: Time step
  365. // quatNormalize: Set to true to normalize the body quaternion
  366. // quatNormalizeFast: If the quaternion should be normalized using "fast" quaternion normalization
  367. func (b *Body) Integrate(dt float32, quatNormalize, quatNormalizeFast bool) {
  368. // Save previous position and rotation
  369. b.prevPosition.Copy(b.position)
  370. b.prevQuaternion.Copy(b.quaternion)
  371. // If static or sleeping - skip
  372. if !(b.bodyType == Dynamic || b.bodyType == Kinematic) || b.sleepState == Sleeping {
  373. return
  374. }
  375. // Integrate force over mass (acceleration) to obtain estimate for instantaneous velocities
  376. iMdt := b.invMass * dt
  377. b.velocity.X += b.force.X * iMdt * b.linearFactor.X
  378. b.velocity.Y += b.force.Y * iMdt * b.linearFactor.Y
  379. b.velocity.Z += b.force.Z * iMdt * b.linearFactor.Z
  380. // Integrate inverse angular mass times torque to obtain estimate for instantaneous angular velocities
  381. e := b.invRotInertiaWorld
  382. tx := b.torque.X * b.angularFactor.X
  383. ty := b.torque.Y * b.angularFactor.Y
  384. tz := b.torque.Z * b.angularFactor.Z
  385. b.angularVelocity.X += dt * (e[0]*tx + e[3]*ty + e[6]*tz)
  386. b.angularVelocity.Y += dt * (e[1]*tx + e[4]*ty + e[7]*tz)
  387. b.angularVelocity.Z += dt * (e[2]*tx + e[5]*ty + e[8]*tz)
  388. // Integrate velocity to obtain estimate for position
  389. b.position.X += b.velocity.X * dt
  390. b.position.Y += b.velocity.Y * dt
  391. b.position.Z += b.velocity.Z * dt
  392. // Integrate angular velocity to obtain estimate for rotation
  393. ax := b.angularVelocity.X * b.angularFactor.X
  394. ay := b.angularVelocity.Y * b.angularFactor.Y
  395. az := b.angularVelocity.Z * b.angularFactor.Z
  396. bx := b.quaternion.X
  397. by := b.quaternion.Y
  398. bz := b.quaternion.Z
  399. bw := b.quaternion.W
  400. halfDt := dt * 0.5
  401. b.quaternion.X += halfDt * (ax*bw + ay*bz - az*by)
  402. b.quaternion.Y += halfDt * (ay*bw + az*bx - ax*bz)
  403. b.quaternion.X += halfDt * (az*bw + ax*by - ay*bx)
  404. b.quaternion.W += halfDt * (-ax*bx - ay*by - az*bz)
  405. // Normalize quaternion
  406. if quatNormalize {
  407. if quatNormalizeFast {
  408. b.quaternion.NormalizeFast()
  409. } else {
  410. b.quaternion.Normalize()
  411. }
  412. }
  413. b.aabbNeedsUpdate = true
  414. // Update world inertia
  415. b.UpdateInertiaWorld(false)
  416. }