body.go 17 KB

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