simulation.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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/physics/equation"
  7. "github.com/g3n/engine/physics/solver"
  8. "github.com/g3n/engine/physics/constraint"
  9. "github.com/g3n/engine/physics/collision"
  10. "github.com/g3n/engine/math32"
  11. "github.com/g3n/engine/physics/object"
  12. "github.com/g3n/engine/physics/material"
  13. "github.com/g3n/engine/core"
  14. )
  15. type ICollidable interface {
  16. Collided() bool
  17. Static() bool
  18. //GetCollisions() []*Collision
  19. }
  20. type CollisionGroup struct {
  21. // TODO future
  22. }
  23. // Simulation represents a physics simulation.
  24. type Simulation struct {
  25. forceFields []ForceField
  26. bodies []*object.Body
  27. nilBodies []int // Array keeps track of which indices of the 'bodies' array are nil
  28. collisionMatrix collision.Matrix // Boolean triangular matrix indicating which pairs of bodies are colliding
  29. prevCollisionMatrix collision.Matrix // CollisionMatrix from the previous step.
  30. allowSleep bool // Makes bodies go to sleep when they've been inactive
  31. contactEqs []*equation.Contact // All the current contacts (instances of ContactEquation) in the world.
  32. frictionEqs []*equation.Friction
  33. paused bool
  34. quatNormalizeSkip int // How often to normalize quaternions. Set to 0 for every step, 1 for every second etc..
  35. // A larger value increases performance.
  36. // If bodies tend to explode, set to a smaller value (zero to be sure nothing can go wrong).
  37. quatNormalizeFast bool // Set to true to use fast quaternion normalization. It is often enough accurate to use. If bodies tend to explode, set to false.
  38. time float32 // The wall-clock time since simulation start
  39. stepnumber int // Number of timesteps taken since start
  40. default_dt float32 // Default and last timestep sizes
  41. dt float32 // Currently / last used timestep. Is set to -1 if not available. This value is updated before each internal step, which means that it is "fresh" inside event callbacks.
  42. accumulator float32 // Time accumulator for interpolation. See http://gafferongames.com/game-physics/fix-your-timestep/
  43. broadphase *collision.Broadphase // The broadphase algorithm to use. Default is NaiveBroadphase
  44. narrowphase *Narrowphase // The narrowphase algorithm to use
  45. solver solver.ISolver // The solver algorithm to use. Default is GSSolver
  46. constraints []constraint.IConstraint // All constraints
  47. materials []*material.Material // All added materials
  48. cMaterials []*material.ContactMaterial
  49. //contactMaterialTable map[intPair]*ContactMaterial // Used to look up a ContactMaterial given two instances of Material.
  50. //defaultMaterial *Material
  51. defaultContactMaterial *material.ContactMaterial
  52. doProfiling bool
  53. scene *core.Node
  54. }
  55. // NewSimulation creates and returns a pointer to a new physics simulation.
  56. func NewSimulation(scene *core.Node) *Simulation {
  57. s := new(Simulation)
  58. s.time = 0
  59. s.dt = -1
  60. s.default_dt = 1/60
  61. s.scene = scene
  62. // Set up broadphase, narrowphase, and solver
  63. s.broadphase = collision.NewBroadphase()
  64. s.narrowphase = NewNarrowphase(s)
  65. s.solver = solver.NewGaussSeidel()
  66. s.collisionMatrix = collision.NewMatrix()
  67. s.prevCollisionMatrix = collision.NewMatrix()
  68. //s.contactMaterialTable = make(map[intPair]*ContactMaterial)
  69. //s.defaultMaterial = NewMaterial
  70. s.defaultContactMaterial = material.NewContactMaterial()
  71. return s
  72. }
  73. func (s *Simulation) Scene() *core.Node {
  74. return s.scene
  75. }
  76. // AddForceField adds a force field to the simulation.
  77. func (s *Simulation) AddForceField(ff ForceField) {
  78. s.forceFields = append(s.forceFields, ff)
  79. }
  80. // RemoveForceField removes the specified force field from the simulation.
  81. // Returns true if found, false otherwise.
  82. func (s *Simulation) RemoveForceField(ff ForceField) bool {
  83. for pos, current := range s.forceFields {
  84. if current == ff {
  85. copy(s.forceFields[pos:], s.forceFields[pos+1:])
  86. s.forceFields[len(s.forceFields)-1] = nil
  87. s.forceFields = s.forceFields[:len(s.forceFields)-1]
  88. return true
  89. }
  90. }
  91. return false
  92. }
  93. // AddBody adds a body to the simulation.
  94. func (s *Simulation) AddBody(body *object.Body, name string) {
  95. // Do nothing if body already present
  96. for _, existingBody := range s.bodies {
  97. if existingBody == body {
  98. return // Do nothing
  99. }
  100. }
  101. var idx int
  102. nilLen := len(s.nilBodies)
  103. if nilLen > 0 {
  104. idx = s.nilBodies[nilLen]
  105. s.nilBodies = s.nilBodies[0:nilLen-1]
  106. } else {
  107. idx = len(s.bodies)
  108. s.bodies = append(s.bodies, body)
  109. }
  110. body.SetIndex(idx)
  111. body.SetName(name)
  112. // Initialize values up to the current index (and set the colliding flag to false)
  113. s.collisionMatrix.Set(idx, idx, false)
  114. s.prevCollisionMatrix.Set(idx, idx, false)
  115. // TODO dispatch add-body event
  116. //s.Dispatch(AddBodyEvent, BodyEvent{body})
  117. }
  118. // RemoveBody removes the specified body from the simulation.
  119. // Returns true if found, false otherwise.
  120. func (s *Simulation) RemoveBody(body *object.Body) bool {
  121. for idx, current := range s.bodies {
  122. if current == body {
  123. s.bodies[idx] = nil
  124. // TODO dispatch remove-body event
  125. //s.Dispatch(AddBodyEvent, BodyEvent{body})
  126. return true
  127. }
  128. }
  129. return false
  130. }
  131. // Clean removes nil bodies from the bodies array, recalculates the body indices and updates the collision matrix.
  132. //func (s *Simulation) Clean() {
  133. //
  134. // // TODO Remove nil bodies from array
  135. // //copy(s.bodies[pos:], s.bodies[pos+1:])
  136. // //s.bodies[len(s.bodies)-1] = nil
  137. // //s.bodies = s.bodies[:len(s.bodies)-1]
  138. //
  139. // // Recompute body indices (each body has a .index int property)
  140. // for i:=0; i<len(s.bodies); i++ {
  141. // s.bodies[i].SetIndex(i)
  142. // }
  143. //
  144. // // TODO Update collision matrix
  145. //
  146. //}
  147. // Bodies returns the slice of bodies under simulation.
  148. // The slice may contain nil values!
  149. func (s *Simulation) Bodies() []*object.Body{
  150. return s.bodies
  151. }
  152. func (s *Simulation) Step(frameDelta float32) {
  153. s.StepPlus(frameDelta, 0, 10)
  154. }
  155. // Step steps the simulation.
  156. // maxSubSteps should be 10 by default
  157. func (s *Simulation) StepPlus(frameDelta float32, timeSinceLastCalled float32, maxSubSteps int) {
  158. if s.paused {
  159. return
  160. }
  161. dt := frameDelta//float32(frameDelta.Seconds())
  162. //if timeSinceLastCalled == 0 { // Fixed, simple stepping
  163. s.internalStep(dt)
  164. // Increment time
  165. //s.time += dt
  166. //} else {
  167. //
  168. // s.accumulator += timeSinceLastCalled
  169. // var substeps = 0
  170. // for s.accumulator >= dt && substeps < maxSubSteps {
  171. // // Do fixed steps to catch up
  172. // s.internalStep(dt)
  173. // s.accumulator -= dt
  174. // substeps++
  175. // }
  176. //
  177. // var t = (s.accumulator % dt) / dt
  178. // for j := 0; j < len(s.bodies); j++ {
  179. // var b = s.bodies[j]
  180. // b.previousPosition.lerp(b.position, t, b.interpolatedPosition)
  181. // b.previousQuaternion.slerp(b.quaternion, t, b.interpolatedQuaternion)
  182. // b.previousQuaternion.normalize()
  183. // }
  184. // s.time += timeSinceLastCalled
  185. //}
  186. }
  187. func (s *Simulation) SetPaused(state bool) {
  188. s.paused = state
  189. }
  190. func (s *Simulation) Paused() bool {
  191. return s.paused
  192. }
  193. // ClearForces sets all body forces in the world to zero.
  194. func (s *Simulation) ClearForces() {
  195. for i:=0; i < len(s.bodies); i++ {
  196. s.bodies[i].ClearForces()
  197. }
  198. }
  199. // Add a constraint to the simulation.
  200. func (s *Simulation) AddConstraint(c constraint.IConstraint) {
  201. s.constraints = append(s.constraints, c)
  202. }
  203. func (s *Simulation) RemoveConstraint(c constraint.IConstraint) {
  204. // TODO
  205. }
  206. func (s *Simulation) AddMaterial(mat *material.Material) {
  207. s.materials = append(s.materials, mat)
  208. }
  209. func (s *Simulation) RemoveMaterial(mat *material.Material) {
  210. // TODO
  211. }
  212. // Adds a contact material to the simulation
  213. func (s *Simulation) AddContactMaterial(cmat *material.ContactMaterial) {
  214. s.cMaterials = append(s.cMaterials, cmat)
  215. // TODO add contactMaterial materials to contactMaterialTable
  216. // s.contactMaterialTable.set(cmat.materials[0].id, cmat.materials[1].id, cmat)
  217. }
  218. // GetContactMaterial returns the contact material between the specified bodies.
  219. func (s *Simulation) GetContactMaterial(bodyA, bodyB *object.Body) *material.ContactMaterial {
  220. var cm *material.ContactMaterial
  221. // TODO
  222. //if bodyA.material != nil && bodyB.material != nil {
  223. // cm = s.contactMaterialTable.get(bodyA.material.id, bodyB.material.id)
  224. // if cm == nil {
  225. // cm = s.defaultContactMaterial
  226. // }
  227. //} else {
  228. cm = s.defaultContactMaterial
  229. //}
  230. return cm
  231. }
  232. // Events =====================
  233. type CollideEvent struct {
  234. body *object.Body
  235. contactEq *equation.Contact
  236. }
  237. // TODO AddBodyEvent, RemoveBodyEvent
  238. type ContactEvent struct {
  239. bodyA *object.Body
  240. bodyB *object.Body
  241. }
  242. const (
  243. BeginContactEvent = "physics.BeginContactEvent"
  244. EndContactEvent = "physics.EndContactEvent"
  245. CollisionEv = "physics.Collision"
  246. )
  247. // ===========================
  248. // Note - this method alters the solution arrays
  249. func (s *Simulation) ApplySolution(sol *solver.Solution) {
  250. // Add results to velocity and angular velocity of bodies
  251. for i := 0; i < len(s.bodies); i++ {
  252. s.bodies[i].ApplyVelocityDeltas(&sol.VelocityDeltas[i], &sol.AngularVelocityDeltas[i])
  253. }
  254. }
  255. // Store old collision state info
  256. func (s *Simulation) collisionMatrixTick() {
  257. s.prevCollisionMatrix = s.collisionMatrix
  258. s.collisionMatrix = collision.NewMatrix()
  259. lb := len(s.bodies)
  260. s.collisionMatrix.Set(lb, lb, false)
  261. // TODO verify that the matrices are indeed different
  262. //if s.prevCollisionMatrix == s.collisionMatrix {
  263. // log.Error("SAME")
  264. //}
  265. // TODO
  266. //s.bodyOverlapKeeper.tick()
  267. //s.shapeOverlapKeeper.tick()
  268. }
  269. // TODO read https://gafferongames.com/post/fix_your_timestep/
  270. func (s *Simulation) internalStep(dt float32) {
  271. s.dt = dt
  272. // Apply force fields and compute world normals/edges
  273. for _, b := range s.bodies {
  274. // Only apply to dynamic bodies
  275. if b.BodyType() == object.Dynamic {
  276. for _, ff := range s.forceFields {
  277. pos := b.Position()
  278. force := ff.ForceAt(&pos)
  279. b.ApplyForceField(&force)
  280. }
  281. }
  282. // Compute for the new rotation
  283. // TODO optimization: only need to compute the below for objects that will go through narrowphase
  284. b.ComputeWorldFaceNormalsAndUniqueEdges()
  285. }
  286. // TODO update subsystems ?
  287. // Find pairs of bodies that are potentially colliding
  288. pairs := s.broadphase.FindCollisionPairs(s.bodies)
  289. // Remove some pairs before proceeding to narrophase based on constraints' colConn property
  290. // which specified if constrained bodies should collide with one another
  291. s.prunePairs(pairs) // TODO review
  292. //
  293. s.collisionMatrixTick()
  294. // Generate contacts
  295. s.generateContacts(pairs)
  296. s.emitContactEvents()
  297. // Wake up bodies
  298. // TODO why not wake bodies up inside s.generateContacs when setting the WakeUpAfterNarrowphase flag?
  299. // Maybe there we are only looking at bodies that belong to current contact equations...
  300. // and need to wake up all marked bodies
  301. for i := 0; i < len(s.bodies); i++ {
  302. bi := s.bodies[i]
  303. if bi != nil && bi.WakeUpAfterNarrowphase() {
  304. bi.WakeUp()
  305. bi.SetWakeUpAfterNarrowphase(false)
  306. }
  307. }
  308. // Add user-added constraints
  309. userAddedEquations := 0
  310. for i := 0; i < len(s.constraints); i++ {
  311. c := s.constraints[i]
  312. c.Update()
  313. eqs := c.Equations()
  314. for j := 0; j < len(eqs); j++ {
  315. userAddedEquations++
  316. s.solver.AddEquation(eqs[j])
  317. }
  318. }
  319. // Update solve mass for all bodies
  320. // NOTE: This was originally inside the beginning of solver.Solve()
  321. if len(s.frictionEqs) + len(s.contactEqs) + userAddedEquations > 0 {
  322. for i := 0; i < len(s.bodies); i++ {
  323. s.bodies[i].UpdateEffectiveMassProperties()
  324. }
  325. }
  326. // Solve the constrained system
  327. solution := s.solver.Solve(dt, len(s.bodies))
  328. s.ApplySolution(solution) // Applies velocity deltas
  329. s.solver.ClearEquations()
  330. // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details
  331. for i := 0; i < len(s.bodies); i++ {
  332. bi := s.bodies[i]
  333. if bi != nil && bi.BodyType() == object.Dynamic { // Only apply damping to dynamic bodies
  334. bi.ApplyDamping(dt)
  335. }
  336. }
  337. // TODO s.Dispatch(World_step_preStepEvent)
  338. // Integrate the forces into velocities into position deltas
  339. quatNormalize := true// s.stepnumber % (s.quatNormalizeSkip + 1) == 0
  340. for i := 0; i < len(s.bodies); i++ {
  341. s.bodies[i].Integrate(dt, quatNormalize, s.quatNormalizeFast)
  342. }
  343. s.ClearForces()
  344. // TODO s.broadphase.dirty = true ?
  345. // Update world time
  346. s.time += dt
  347. s.stepnumber += 1
  348. // TODO s.Dispatch(World_step_postStepEvent)
  349. // Sleeping update
  350. if s.allowSleep {
  351. for i := 0; i < len(s.bodies); i++ {
  352. s.bodies[i].SleepTick(s.time)
  353. }
  354. }
  355. }
  356. // TODO - REVIEW THIS
  357. func (s *Simulation) prunePairs(pairs []collision.Pair) []collision.Pair {
  358. // TODO There is probably a bug here when the same body can have multiple constraints and appear in multiple pairs
  359. //// Remove constrained pairs with collideConnected == false
  360. //pairIdxsToRemove := []int
  361. //for i := 0; i < len(s.constraints); i++ {
  362. // c := s.constraints[i]
  363. // cBodyA := s.bodies[c.BodyA().Index()]
  364. // cBodyB := s.bodies[c.BodyB().Index()]
  365. // if !c.CollideConnected() {
  366. // for i := range pairs {
  367. // if (pairs[i].BodyA == cBodyA && pairs[i].BodyB == cBodyB) ||
  368. // (pairs[i].BodyA == cBodyB && pairs[i].BodyB == cBodyA) {
  369. // pairIdxsToRemove = append(pairIdxsToRemove, i)
  370. //
  371. // }
  372. // }
  373. // }
  374. //}
  375. //
  376. //// Remove pairs
  377. ////var prunedPairs []Pair
  378. //for i := range pairs {
  379. // for _, idx := range pairIdxsToRemove {
  380. // copy(pairs[i:], pairs[i+1:])
  381. // //pairs[len(pairs)-1] = nil
  382. // pairs = pairs[:len(pairs)-1]
  383. // }
  384. //}
  385. return pairs
  386. }
  387. // generateContacts
  388. func (s *Simulation) generateContacts(pairs []collision.Pair) {
  389. // Find all contacts and generate contact and friction equations (narrowphase)
  390. s.contactEqs, s.frictionEqs = s.narrowphase.GetContacts(pairs)
  391. // Add all friction equations to solver
  392. for i := 0; i < len(s.frictionEqs); i++ {
  393. s.solver.AddEquation(s.frictionEqs[i])
  394. }
  395. for k := 0; k < len(s.contactEqs); k++ {
  396. // Current contact
  397. contactEq := s.contactEqs[k]
  398. // Get current collision indices
  399. bodyA := s.bodies[contactEq.BodyA().Index()]
  400. bodyB := s.bodies[contactEq.BodyB().Index()]
  401. // TODO future: update equations with physical material properties
  402. s.solver.AddEquation(contactEq)
  403. if bodyA.AllowSleep() && bodyA.BodyType() == object.Dynamic && bodyA.SleepState() == object.Sleeping && bodyB.SleepState() == object.Awake && bodyB.BodyType() != object.Static {
  404. velocityB := bodyB.Velocity()
  405. angularVelocityB := bodyB.AngularVelocity()
  406. speedSquaredB := velocityB.LengthSq() + angularVelocityB.LengthSq()
  407. speedLimitSquaredB := math32.Pow(bodyB.SleepSpeedLimit(), 2)
  408. if speedSquaredB >= speedLimitSquaredB*2 {
  409. bodyA.SetWakeUpAfterNarrowphase(true)
  410. }
  411. }
  412. if bodyB.AllowSleep() && bodyB.BodyType() == object.Dynamic && bodyB.SleepState() == object.Sleeping && bodyA.SleepState() == object.Awake && bodyA.BodyType() != object.Static {
  413. velocityA := bodyA.Velocity()
  414. angularVelocityA := bodyA.AngularVelocity()
  415. speedSquaredA := velocityA.LengthSq() + angularVelocityA.LengthSq()
  416. speedLimitSquaredA := math32.Pow(bodyA.SleepSpeedLimit(), 2)
  417. if speedSquaredA >= speedLimitSquaredA*2 {
  418. bodyB.SetWakeUpAfterNarrowphase(true)
  419. }
  420. }
  421. // Now we know that i and j are in contact. Set collision matrix state
  422. s.collisionMatrix.Set(bodyA.Index(), bodyB.Index(), true)
  423. if s.prevCollisionMatrix.Get(bodyA.Index(), bodyB.Index()) == false {
  424. // First contact!
  425. bodyA.Dispatch(CollisionEv, &CollideEvent{bodyB, contactEq})
  426. bodyB.Dispatch(CollisionEv, &CollideEvent{bodyA, contactEq})
  427. }
  428. // TODO this is only for events
  429. //s.bodyOverlapKeeper.set(bodyA.id, bodyB.id)
  430. //s.shapeOverlapKeeper.set(si.id, sj.id)
  431. }
  432. }
  433. func (s *Simulation) emitContactEvents() {
  434. //TODO
  435. }