body.go 18 KB

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