forcefield.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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 "github.com/g3n/engine/math32"
  6. // ForceField represents a force field. A force is defined for every point.
  7. type ForceField interface {
  8. ForceAt(pos *math32.Vector3) math32.Vector3
  9. }
  10. //
  11. // ConstantForceField is a constant force field.
  12. // It can be used to simulate surface gravity.
  13. //
  14. type ConstantForceField struct {
  15. force math32.Vector3
  16. }
  17. // NewConstantForceField creates and returns a pointer to a new ConstantForceField.
  18. func NewConstantForceField(force *math32.Vector3) *ConstantForceField {
  19. g := new(ConstantForceField)
  20. g.force = *force
  21. return g
  22. }
  23. // SetForce sets the force of the force field.
  24. func (g *ConstantForceField) SetForce(newDirection *math32.Vector3) {
  25. g.force = *newDirection
  26. }
  27. // Force returns the force of the force field.
  28. func (g *ConstantForceField) Force() *math32.Vector3 {
  29. return &g.force
  30. }
  31. // ForceAt satisfies the ForceField interface and returns the force at the specified position.
  32. func (g *ConstantForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
  33. return g.force
  34. }
  35. //
  36. // AttractorForceField is a force field where all forces point to a single point.
  37. // The force strength changes with the inverse distance squared.
  38. // This can be used to model planetary attractions.
  39. //
  40. type AttractorForceField struct {
  41. position math32.Vector3
  42. mass float32
  43. }
  44. // NewAttractorForceField creates and returns a pointer to a new AttractorForceField.
  45. func NewAttractorForceField(position *math32.Vector3, mass float32) *AttractorForceField {
  46. pa := new(AttractorForceField)
  47. pa.position = *position
  48. pa.mass = mass
  49. return pa
  50. }
  51. // SetPosition sets the position of the AttractorForceField.
  52. func (pa *AttractorForceField) SetPosition(newPosition *math32.Vector3) {
  53. pa.position = *newPosition
  54. }
  55. // Position returns the position of the AttractorForceField.
  56. func (pa *AttractorForceField) Position() *math32.Vector3 {
  57. return &pa.position
  58. }
  59. // SetMass sets the mass of the AttractorForceField.
  60. func (pa *AttractorForceField) SetMass(newMass float32) {
  61. pa.mass = newMass
  62. }
  63. // Mass returns the mass of the AttractorForceField.
  64. func (pa *AttractorForceField) Mass() float32 {
  65. return pa.mass
  66. }
  67. // ForceAt satisfies the ForceField interface and returns the force at the specified position.
  68. func (pa *AttractorForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
  69. dir := pos
  70. dir.Negate()
  71. dir.Add(&pa.position)
  72. dist := dir.Length()
  73. dir.Normalize()
  74. var val float32
  75. //log.Error("dist %v", dist)
  76. if dist > 0 {
  77. val = pa.mass / (dist * dist)
  78. } else {
  79. val = 0
  80. }
  81. val = math32.Min(val, 100) // TODO deal with instability
  82. //log.Error("%v", val)
  83. dir.MultiplyScalar(val) // TODO multiply by gravitational constant: 6.673×10−11 (N–m2)/kg2
  84. return *dir
  85. }
  86. //
  87. // RepellerForceField is a force field where all forces point away from a single point.
  88. // The force strength changes with the inverse distance squared.
  89. //
  90. type RepellerForceField struct {
  91. position math32.Vector3
  92. mass float32
  93. }
  94. // NewRepellerForceField creates and returns a pointer to a new RepellerForceField.
  95. func NewRepellerForceField(position *math32.Vector3, mass float32) *RepellerForceField {
  96. pr := new(RepellerForceField)
  97. pr.position = *position
  98. pr.mass = mass
  99. return pr
  100. }
  101. // SetPosition sets the position of the RepellerForceField.
  102. func (pr *RepellerForceField) SetPosition(newPosition *math32.Vector3) {
  103. pr.position = *newPosition
  104. }
  105. // Position returns the position of the RepellerForceField.
  106. func (pr *RepellerForceField) Position() *math32.Vector3 {
  107. return &pr.position
  108. }
  109. // SetMass sets the mass of the RepellerForceField.
  110. func (pr *RepellerForceField) SetMass(newMass float32) {
  111. pr.mass = newMass
  112. }
  113. // Mass returns the mass of the RepellerForceField.
  114. func (pr *RepellerForceField) Mass() float32 {
  115. return pr.mass
  116. }
  117. // ForceAt satisfies the ForceField interface and returns the force at the specified position.
  118. func (pr *RepellerForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
  119. dir := pr.position
  120. dir.Negate()
  121. dir.Add(pos)
  122. dist := dir.Length()
  123. dir.Normalize()
  124. dir.MultiplyScalar(pr.mass / (dist * dist)) // TODO multiply by gravitational constant: 6.673×10−11 (N–m2)/kg2
  125. return dir
  126. }