simulation.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. "time"
  7. "github.com/g3n/engine/physics/equation"
  8. "github.com/g3n/engine/physics/solver"
  9. "github.com/g3n/engine/physics/constraint"
  10. )
  11. type ICollidable interface {
  12. Collided() bool
  13. Static() bool
  14. //GetCollisions() []*Collision
  15. }
  16. type CollisionGroup struct {
  17. // TODO future
  18. }
  19. // Simulation represents a physics simulation.
  20. type Simulation struct {
  21. forceFields []ForceField
  22. bodies []*Body
  23. particles []*Particle
  24. //dynamical []int // non collidable but still affected by force fields
  25. //collidables []ICollidable
  26. allowSleep bool // Makes bodies go to sleep when they've been inactive
  27. contactEqs []*equation.Contact // All the current contacts (instances of ContactEquation) in the world.
  28. frictionEqs []*equation.Friction
  29. quatNormalizeSkip int // How often to normalize quaternions. Set to 0 for every step, 1 for every second etc..
  30. // A larger value increases performance.
  31. // If bodies tend to explode, set to a smaller value (zero to be sure nothing can go wrong).
  32. 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.
  33. time float32 // The wall-clock time since simulation start
  34. stepnumber int // Number of timesteps taken since start
  35. default_dt float32 // Default and last timestep sizes
  36. accumulator float32 // Time accumulator for interpolation. See http://gafferongames.com/game-physics/fix-your-timestep/
  37. //broadphase IBroadphase // The broadphase algorithm to use. Default is NaiveBroadphase
  38. //narrowphase INarrowphase // The narrowphase algorithm to use
  39. solver solver.ISolver // The solver algorithm to use. Default is GSSolver
  40. constraints []*constraint.Constraint // All constraints
  41. materials []*Material // All added materials
  42. cMaterials []*ContactMaterial
  43. doProfiling bool
  44. }
  45. // NewSimulation creates and returns a pointer to a new physics simulation.
  46. func NewSimulation() *Simulation {
  47. s := new(Simulation)
  48. s.time = 0
  49. s.default_dt = 1/60
  50. //s.broadphase = NewNaiveBroadphase()
  51. //s.narrowphase = NewNarrowphase()
  52. s.solver = solver.NewGaussSeidel()
  53. return s
  54. }
  55. // AddForceField adds a force field to the simulation.
  56. func (s *Simulation) AddForceField(ff ForceField) {
  57. s.forceFields = append(s.forceFields, ff)
  58. }
  59. // RemoveForceField removes the specified force field from the simulation.
  60. // Returns true if found, false otherwise.
  61. func (s *Simulation) RemoveForceField(ff ForceField) bool {
  62. for pos, current := range s.forceFields {
  63. if current == ff {
  64. copy(s.forceFields[pos:], s.forceFields[pos+1:])
  65. s.forceFields[len(s.forceFields)-1] = nil
  66. s.forceFields = s.forceFields[:len(s.forceFields)-1]
  67. return true
  68. }
  69. }
  70. return false
  71. }
  72. // AddBody adds a body to the simulation.
  73. // @todo If the simulation has not yet started, why recrete and copy arrays for each body? Accumulate in dynamic arrays in this case.
  74. // @todo Adding an array of bodies should be possible. This would save some loops too
  75. func (s *Simulation) AddBody(body *Body) {
  76. // TODO only add if not already present
  77. s.bodies = append(s.bodies, body)
  78. //body.index = this.bodies.length
  79. //s.bodies.push(body)
  80. //body.simulation = s // TODO
  81. //body.initPosition.Copy(body.position)
  82. //body.initVelocity.Copy(body.velocity)
  83. //body.timeLastSleepy = s.time
  84. //if body instanceof Body { // TODO
  85. // body.initAngularVelocity.Copy(body.angularVelocity)
  86. // body.initQuaternion.Copy(body.quaternion)
  87. //}
  88. //
  89. //// TODO
  90. //s.collisionMatrix.setNumObjects(len(s.bodies))
  91. //s.addBodyEvent.body = body
  92. //s.idToBodyMap[body.id] = body
  93. //s.dispatchEvent(s.addBodyEvent)
  94. }
  95. // RemoveBody removes the specified body from the simulation.
  96. // Returns true if found, false otherwise.
  97. func (s *Simulation) RemoveBody(body *Body) bool {
  98. for pos, current := range s.bodies {
  99. if current == body {
  100. copy(s.bodies[pos:], s.bodies[pos+1:])
  101. s.bodies[len(s.bodies)-1] = nil
  102. s.bodies = s.bodies[:len(s.bodies)-1]
  103. body.simulation = nil
  104. // Recompute body indices (each body has a .index int property)
  105. for i:=0; i<len(s.bodies); i++ {
  106. s.bodies[i].index = i
  107. }
  108. // TODO
  109. //s.collisionMatrix.setNumObjects(len(s.bodies) - 1)
  110. //s.removeBodyEvent.body = body
  111. //delete s.idToBodyMap[body.id]
  112. //s.dispatchEvent(s.removeBodyEvent)
  113. return true
  114. }
  115. }
  116. return false
  117. }
  118. // Bodies returns the bodies under simulation.
  119. func (s *Simulation) Bodies() []*Body{
  120. return s.bodies
  121. }
  122. // AddParticle adds a particle to the simulation.
  123. func (s *Simulation) AddParticle(rb *Particle) {
  124. s.particles = append(s.particles, rb)
  125. }
  126. // RemoveParticle removes the specified particle from the simulation.
  127. // Returns true if found, false otherwise.
  128. func (s *Simulation) RemoveParticle(rb *Particle) bool {
  129. for pos, current := range s.particles {
  130. if current == rb {
  131. copy(s.particles[pos:], s.particles[pos+1:])
  132. s.particles[len(s.particles)-1] = nil
  133. s.particles = s.particles[:len(s.particles)-1]
  134. return true
  135. }
  136. }
  137. return false
  138. }
  139. func (s *Simulation) applyForceFields(frameDelta time.Duration) {
  140. for _, ff := range s.forceFields {
  141. for _, rb := range s.bodies {
  142. pos := rb.GetNode().Position()
  143. force := ff.ForceAt(&pos)
  144. //log.Error("force: %v", force)
  145. //log.Error("mass: %v", rb.mass)
  146. //log.Error("frameDelta: %v", frameDelta.Seconds())
  147. vdiff := force.MultiplyScalar(float32(frameDelta.Seconds())/rb.mass)
  148. //log.Error("vdiff: %v", vdiff)
  149. rb.velocity.Add(vdiff)
  150. }
  151. }
  152. for _, ff := range s.forceFields {
  153. for _, rb := range s.particles {
  154. pos := rb.GetNode().Position()
  155. force := ff.ForceAt(&pos)
  156. //log.Error("force: %v", force)
  157. //log.Error("mass: %v", rb.mass)
  158. //log.Error("frameDelta: %v", frameDelta.Seconds())
  159. vdiff := force.MultiplyScalar(float32(frameDelta.Seconds())/rb.mass)
  160. //log.Error("vdiff: %v", vdiff)
  161. rb.velocity.Add(vdiff)
  162. }
  163. }
  164. }
  165. // updatePositions integrates the velocity of the objects to obtain the position in the next frame.
  166. func (s *Simulation) updatePositions(frameDelta time.Duration) {
  167. for _, rb := range s.bodies {
  168. pos := rb.GetNode().Position()
  169. posDelta := rb.velocity.Clone()
  170. posDelta.MultiplyScalar(float32(frameDelta.Seconds()))
  171. pos.Add(posDelta)
  172. rb.GetNode().SetPositionVec(&pos)
  173. }
  174. for _, rb := range s.particles {
  175. pos := rb.GetNode().Position()
  176. posDelta := rb.velocity.Clone()
  177. posDelta.MultiplyScalar(float32(frameDelta.Seconds()))
  178. pos.Add(posDelta)
  179. rb.GetNode().SetPositionVec(&pos)
  180. }
  181. }
  182. //func (s *Simulation) CheckCollisions() []*Collision{//collidables []ICollidable) {
  183. //
  184. // return
  185. //}
  186. func (s *Simulation) Backtrack() {
  187. }
  188. // Step steps the simulation.
  189. func (s *Simulation) Step(frameDelta time.Duration) {
  190. // Check for collisions
  191. //collisions := s.CheckCollisions()
  192. //if len(collisions) > 0 {
  193. // // Backtrack to 0 penetration
  194. // s.Backtrack()
  195. //}
  196. // Apply static forces/inertia/impulses (only to objects that did not collide)
  197. s.applyForceFields(frameDelta)
  198. // s.applyDrag(frameDelta) // TODO
  199. // Apply impact forces/inertia/impulses to objects that collided
  200. //s.applyImpactForces(frameDelta)
  201. // Update object positions based on calculated final speeds
  202. s.updatePositions(frameDelta)
  203. }
  204. // ClearForces sets all body forces in the world to zero.
  205. func (s *Simulation) ClearForces() {
  206. for i:=0; i < len(s.bodies); i++ {
  207. s.bodies[i].force.Set(0,0,0)
  208. s.bodies[i].torque.Set(0,0,0)
  209. }
  210. }
  211. // Add a constraint to the simulation.
  212. func (s *Simulation) AddConstraint(c *constraint.Constraint) {
  213. s.constraints = append(s.constraints, c)
  214. }
  215. func (s *Simulation) RemoveConstraint(c *constraint.Constraint) {
  216. // TODO
  217. }
  218. func (s *Simulation) AddMaterial(mat *Material) {
  219. s.materials = append(s.materials, mat)
  220. }
  221. func (s *Simulation) RemoveMaterial(mat *Material) {
  222. // TODO
  223. }
  224. func (s *Simulation) AddContactMaterial(cmat *ContactMaterial) {
  225. s.cMaterials = append(s.cMaterials, cmat)
  226. // TODO add contactMaterial materials to contactMaterialTable
  227. }
  228. type ContactEvent struct {
  229. bodyA *Body
  230. bodyB *Body
  231. // shapeA
  232. // shapeB
  233. }
  234. const (
  235. BeginContactEvent = "physics.BeginContactEvent"
  236. EndContactEvent = "physics.EndContactEvent"
  237. )
  238. func (s *Simulation) EmitContactEvents() {
  239. //TODO
  240. }
  241. func (s *Simulation) Solve() {
  242. //// Update solve mass for all bodies
  243. //if Neq > 0 {
  244. // for i := 0; i < Nbodies; i++ {
  245. // bodies[i].UpdateSolveMassProperties()
  246. // }
  247. //}
  248. //
  249. //s.solver.Solve(frameDelta, len(bodies))
  250. }
  251. // Note - this method alters the solution arrays
  252. func (s *Simulation) ApplySolution(solution *solver.Solution) {
  253. // Add results to velocity and angular velocity of bodies
  254. for i := 0; i < len(s.bodies); i++ {
  255. b := s.bodies[i]
  256. vDelta := solution.VelocityDeltas[i].Multiply(b.LinearFactor())
  257. b.AddToVelocity(vDelta)
  258. wDelta := solution.AngularVelocityDeltas[i].Multiply(b.AngularFactor())
  259. b.AddToAngularVelocity(wDelta)
  260. }
  261. }