/
forcefield.go
164 lines (126 loc) · 4.26 KB
/
forcefield.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2016 The G3N Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package physics
import "github.com/lquesada/cavernal/lib/g3n/engine/math32"
// ForceField represents a force field. A force is defined for every point.
type ForceField interface {
ForceAt(pos *math32.Vector3) math32.Vector3
}
//
// ConstantForceField is a constant force field.
// It can be used to simulate surface gravity.
//
type ConstantForceField struct {
force math32.Vector3
}
// NewConstantForceField creates and returns a pointer to a new ConstantForceField.
func NewConstantForceField(force *math32.Vector3) *ConstantForceField {
g := new(ConstantForceField)
g.force = *force
return g
}
// SetForce sets the force of the force field.
func (g *ConstantForceField) SetForce(newDirection *math32.Vector3) {
g.force = *newDirection
}
// Force returns the force of the force field.
func (g *ConstantForceField) Force() *math32.Vector3 {
return &g.force
}
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
func (g *ConstantForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
return g.force
}
//
// AttractorForceField is a force field where all forces point to a single point.
// The force strength changes with the inverse distance squared.
// This can be used to model planetary attractions.
//
type AttractorForceField struct {
position math32.Vector3
mass float32
}
// NewAttractorForceField creates and returns a pointer to a new AttractorForceField.
func NewAttractorForceField(position *math32.Vector3, mass float32) *AttractorForceField {
pa := new(AttractorForceField)
pa.position = *position
pa.mass = mass
return pa
}
// SetPosition sets the position of the AttractorForceField.
func (pa *AttractorForceField) SetPosition(newPosition *math32.Vector3) {
pa.position = *newPosition
}
// Position returns the position of the AttractorForceField.
func (pa *AttractorForceField) Position() *math32.Vector3 {
return &pa.position
}
// SetMass sets the mass of the AttractorForceField.
func (pa *AttractorForceField) SetMass(newMass float32) {
pa.mass = newMass
}
// Mass returns the mass of the AttractorForceField.
func (pa *AttractorForceField) Mass() float32 {
return pa.mass
}
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
func (pa *AttractorForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
dir := pos
dir.Negate()
dir.Add(&pa.position)
dist := dir.Length()
dir.Normalize()
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
}
//
// RepellerForceField is a force field where all forces point away from a single point.
// The force strength changes with the inverse distance squared.
//
type RepellerForceField struct {
position math32.Vector3
mass float32
}
// NewRepellerForceField creates and returns a pointer to a new RepellerForceField.
func NewRepellerForceField(position *math32.Vector3, mass float32) *RepellerForceField {
pr := new(RepellerForceField)
pr.position = *position
pr.mass = mass
return pr
}
// SetPosition sets the position of the RepellerForceField.
func (pr *RepellerForceField) SetPosition(newPosition *math32.Vector3) {
pr.position = *newPosition
}
// Position returns the position of the RepellerForceField.
func (pr *RepellerForceField) Position() *math32.Vector3 {
return &pr.position
}
// SetMass sets the mass of the RepellerForceField.
func (pr *RepellerForceField) SetMass(newMass float32) {
pr.mass = newMass
}
// Mass returns the mass of the RepellerForceField.
func (pr *RepellerForceField) Mass() float32 {
return pr.mass
}
// ForceAt satisfies the ForceField interface and returns the force at the specified position.
func (pr *RepellerForceField) ForceAt(pos *math32.Vector3) math32.Vector3 {
dir := pr.position
dir.Negate()
dir.Add(pos)
dist := dir.Length()
dir.Normalize()
dir.MultiplyScalar(pr.mass/(dist*dist)) // TODO multiply by gravitational constant: 6.673×10−11 (N–m2)/kg2
return dir
}