|
@@ -8,148 +8,157 @@ import "github.com/g3n/engine/math32"
|
|
|
|
|
|
|
|
// ForceField represents a force field. A force is defined for every point.
|
|
// ForceField represents a force field. A force is defined for every point.
|
|
|
type ForceField interface {
|
|
type ForceField interface {
|
|
|
- ForceAt(pos *math32.Vector3) *math32.Vector3
|
|
|
|
|
|
|
+ ForceAt(pos *math32.Vector3) math32.Vector3
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
-// Constant is a constant force field.
|
|
|
|
|
|
|
+// ConstantForceField is a constant force field.
|
|
|
// It can be used to simulate surface gravity.
|
|
// It can be used to simulate surface gravity.
|
|
|
//
|
|
//
|
|
|
-type Constant struct {
|
|
|
|
|
|
|
+type ConstantForceField struct {
|
|
|
force math32.Vector3
|
|
force math32.Vector3
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// NewConstant creates and returns a pointer to a new Constant force field.
|
|
|
|
|
-func NewConstant(acceleration float32) *Constant {
|
|
|
|
|
|
|
+// NewConstantForceField creates and returns a pointer to a new ConstantForceField.
|
|
|
|
|
+func NewConstantForceField(force *math32.Vector3) *ConstantForceField {
|
|
|
|
|
|
|
|
- g := new(Constant)
|
|
|
|
|
- g.force = math32.Vector3{0,0,-acceleration}
|
|
|
|
|
|
|
+ g := new(ConstantForceField)
|
|
|
|
|
+ g.force = *force
|
|
|
return g
|
|
return g
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// SetForce sets the force of the force field.
|
|
// SetForce sets the force of the force field.
|
|
|
-func (g *Constant) SetForce(newDirection *math32.Vector3) {
|
|
|
|
|
|
|
+func (g *ConstantForceField) SetForce(newDirection *math32.Vector3) {
|
|
|
|
|
|
|
|
g.force = *newDirection
|
|
g.force = *newDirection
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Force returns the force of the force field.
|
|
// Force returns the force of the force field.
|
|
|
-func (g *Constant) Force() *math32.Vector3 {
|
|
|
|
|
|
|
+func (g *ConstantForceField) Force() *math32.Vector3 {
|
|
|
|
|
|
|
|
return &g.force
|
|
return &g.force
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
|
-func (g *Constant) ForceAt(pos *math32.Vector3) *math32.Vector3 {
|
|
|
|
|
|
|
+func (g *ConstantForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
|
|
|
|
|
|
|
|
- return &g.force
|
|
|
|
|
|
|
+ return g.force
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
-// PointAttractor is a force field where all forces point to a single point.
|
|
|
|
|
|
|
+// AttractorForceField is a force field where all forces point to a single point.
|
|
|
// The force strength changes with the inverse distance squared.
|
|
// The force strength changes with the inverse distance squared.
|
|
|
// This can be used to model planetary attractions.
|
|
// This can be used to model planetary attractions.
|
|
|
//
|
|
//
|
|
|
-type PointAttractor struct {
|
|
|
|
|
|
|
+type AttractorForceField struct {
|
|
|
position math32.Vector3
|
|
position math32.Vector3
|
|
|
mass float32
|
|
mass float32
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// NewPointAttractor creates and returns a pointer to a new PointAttractor force field.
|
|
|
|
|
-func NewPointAttractor(position *math32.Vector3, mass float32) *PointAttractor {
|
|
|
|
|
|
|
+// NewAttractorForceField creates and returns a pointer to a new AttractorForceField.
|
|
|
|
|
+func NewAttractorForceField(position *math32.Vector3, mass float32) *AttractorForceField {
|
|
|
|
|
|
|
|
- pa := new(PointAttractor)
|
|
|
|
|
|
|
+ pa := new(AttractorForceField)
|
|
|
pa.position = *position
|
|
pa.position = *position
|
|
|
pa.mass = mass
|
|
pa.mass = mass
|
|
|
return pa
|
|
return pa
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetPosition sets the position of the PointAttractor.
|
|
|
|
|
-func (pa *PointAttractor) SetPosition(newPosition *math32.Vector3) {
|
|
|
|
|
|
|
+// SetPosition sets the position of the AttractorForceField.
|
|
|
|
|
+func (pa *AttractorForceField) SetPosition(newPosition *math32.Vector3) {
|
|
|
|
|
|
|
|
pa.position = *newPosition
|
|
pa.position = *newPosition
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Position returns the position of the PointAttractor.
|
|
|
|
|
-func (pa *PointAttractor) Position() *math32.Vector3 {
|
|
|
|
|
|
|
+// Position returns the position of the AttractorForceField.
|
|
|
|
|
+func (pa *AttractorForceField) Position() *math32.Vector3 {
|
|
|
|
|
|
|
|
return &pa.position
|
|
return &pa.position
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetMass sets the mass of the PointAttractor.
|
|
|
|
|
-func (pa *PointAttractor) SetMass(newMass float32) {
|
|
|
|
|
|
|
+// SetMass sets the mass of the AttractorForceField.
|
|
|
|
|
+func (pa *AttractorForceField) SetMass(newMass float32) {
|
|
|
|
|
|
|
|
pa.mass = newMass
|
|
pa.mass = newMass
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Mass returns the mass of the PointAttractor.
|
|
|
|
|
-func (pa *PointAttractor) Mass() float32 {
|
|
|
|
|
|
|
+// Mass returns the mass of the AttractorForceField.
|
|
|
|
|
+func (pa *AttractorForceField) Mass() float32 {
|
|
|
|
|
|
|
|
return pa.mass
|
|
return pa.mass
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
|
-func (pa *PointAttractor) ForceAt(pos *math32.Vector3) *math32.Vector3 {
|
|
|
|
|
|
|
+func (pa *AttractorForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
|
|
|
|
|
|
|
|
dir := pos
|
|
dir := pos
|
|
|
dir.Negate()
|
|
dir.Negate()
|
|
|
dir.Add(&pa.position)
|
|
dir.Add(&pa.position)
|
|
|
dist := dir.Length()
|
|
dist := dir.Length()
|
|
|
dir.Normalize()
|
|
dir.Normalize()
|
|
|
- dir.MultiplyScalar(pa.mass/(dist*dist))
|
|
|
|
|
- return dir
|
|
|
|
|
|
|
+ var val float32
|
|
|
|
|
+ log.Error("dist %v", dist)
|
|
|
|
|
+ if dist > 0 {
|
|
|
|
|
+ val = pa.mass/(dist*dist)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ val = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ val = math32.Min(val, 100) // TODO deal with instability
|
|
|
|
|
+ log.Error("%v", val)
|
|
|
|
|
+ dir.MultiplyScalar(val) // TODO multiply by gravitational constant: 6.673×10−11 (N–m2)/kg2
|
|
|
|
|
+ return *dir
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
-// PointRepeller is a force field where all forces point away from a single point.
|
|
|
|
|
|
|
+// RepellerForceField is a force field where all forces point away from a single point.
|
|
|
// The force strength changes with the inverse distance squared.
|
|
// The force strength changes with the inverse distance squared.
|
|
|
//
|
|
//
|
|
|
-type PointRepeller struct {
|
|
|
|
|
|
|
+type RepellerForceField struct {
|
|
|
position math32.Vector3
|
|
position math32.Vector3
|
|
|
mass float32
|
|
mass float32
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// NewPointRepeller creates and returns a pointer to a new PointRepeller force field.
|
|
|
|
|
-func NewPointRepeller(position *math32.Vector3, mass float32) *PointRepeller {
|
|
|
|
|
|
|
+// NewRepellerForceField creates and returns a pointer to a new RepellerForceField.
|
|
|
|
|
+func NewRepellerForceField(position *math32.Vector3, mass float32) *RepellerForceField {
|
|
|
|
|
|
|
|
- pr := new(PointRepeller)
|
|
|
|
|
|
|
+ pr := new(RepellerForceField)
|
|
|
pr.position = *position
|
|
pr.position = *position
|
|
|
pr.mass = mass
|
|
pr.mass = mass
|
|
|
return pr
|
|
return pr
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetPosition sets the position of the PointRepeller.
|
|
|
|
|
-func (pr *PointRepeller) SetPosition(newPosition *math32.Vector3) {
|
|
|
|
|
|
|
+// SetPosition sets the position of the RepellerForceField.
|
|
|
|
|
+func (pr *RepellerForceField) SetPosition(newPosition *math32.Vector3) {
|
|
|
|
|
|
|
|
pr.position = *newPosition
|
|
pr.position = *newPosition
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Position returns the position of the PointRepeller.
|
|
|
|
|
-func (pr *PointRepeller) Position() *math32.Vector3 {
|
|
|
|
|
|
|
+// Position returns the position of the RepellerForceField.
|
|
|
|
|
+func (pr *RepellerForceField) Position() *math32.Vector3 {
|
|
|
|
|
|
|
|
return &pr.position
|
|
return &pr.position
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetMass sets the mass of the PointRepeller.
|
|
|
|
|
-func (pr *PointRepeller) SetMass(newMass float32) {
|
|
|
|
|
|
|
+// SetMass sets the mass of the RepellerForceField.
|
|
|
|
|
+func (pr *RepellerForceField) SetMass(newMass float32) {
|
|
|
|
|
|
|
|
pr.mass = newMass
|
|
pr.mass = newMass
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Mass returns the mass of the PointRepeller.
|
|
|
|
|
-func (pr *PointRepeller) Mass() float32 {
|
|
|
|
|
|
|
+// Mass returns the mass of the RepellerForceField.
|
|
|
|
|
+func (pr *RepellerForceField) Mass() float32 {
|
|
|
|
|
|
|
|
return pr.mass
|
|
return pr.mass
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
|
|
|
-func (pr *PointRepeller) ForceAt(pos *math32.Vector3) *math32.Vector3 {
|
|
|
|
|
|
|
+func (pr *RepellerForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
|
|
|
|
|
|
|
|
dir := pr.position
|
|
dir := pr.position
|
|
|
dir.Negate()
|
|
dir.Negate()
|
|
|
dir.Add(pos)
|
|
dir.Add(pos)
|
|
|
dist := dir.Length()
|
|
dist := dir.Length()
|
|
|
dir.Normalize()
|
|
dir.Normalize()
|
|
|
- dir.MultiplyScalar(pr.mass/(dist*dist))
|
|
|
|
|
- return &dir
|
|
|
|
|
|
|
+ dir.MultiplyScalar(pr.mass/(dist*dist)) // TODO multiply by gravitational constant: 6.673×10−11 (N–m2)/kg2
|
|
|
|
|
+ return dir
|
|
|
}
|
|
}
|