-
Notifications
You must be signed in to change notification settings - Fork 0
/
Physics2.h
215 lines (160 loc) · 10.1 KB
/
Physics2.h
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**************************************************************************
File: Physics2.h
Prepared by Erkin Tunca for nehe.gamedev.net
**************************************************************************/
#include "Physics1.h" //Physics1.h is a must for Physics2.h simulations
//An object to represent a spring with inner friction binding
//two masses. The spring has a normal length (the length that the
// spring does not exert any force)
class Spring{
public:
Mass* mass1; //The first mass at one tip of the spring
Mass* mass2; //The second mass at the other tip of the spring
float springConstant; //A constant to represent the stiffness of the spring
float springLength; //The length that the spring does not exert any force
float frictionConstant; //A constant to be used for the inner friction of the spring
Spring(Mass* mass1, Mass* mass2,
float springConstant, float springLength, float frictionConstant){ //Constructor
this->springConstant = springConstant; //set the springConstant
this->springLength = springLength; //set the springLength
this->frictionConstant = frictionConstant; //set the frictionConstant
this->mass1 = mass1; //set mass1
this->mass2 = mass2; //set mass2
}
void solve() //solve() method: the method where forces can be applied
{
Vector3D springVector = mass1->pos - mass2->pos; //vector between the two masses
float r = springVector.length(); //distance between the two masses
Vector3D force; //force initially has a zero value
if (r != 0) //to avoid a division by zero check if r is zero
force += (springVector / r) * (r - springLength) * (-springConstant); //the spring force is added to the force
force += -(mass1->vel - mass2->vel) * frictionConstant; //the friction force is added to the force
//with this addition we obtain the net force of the spring
mass1->applyForce(force); //force is applied to mass1
mass2->applyForce(-force); //the opposite of force is applied to mass2
}
};
/*
class RopeSimulation is derived from class Simulation (see Physics1.h). It simulates a rope with
point-like particles binded with springs. The springs have inner friction and normal length. One tip of
the rope is stabilized at a point in space called "Vector3D ropeConnectionPos". This point can be
moved externally by a method "void setRopeConnectionVel(Vector3D ropeConnectionVel)". RopeSimulation
creates air friction and a planer surface (or ground) with a normal in +y direction. RopeSimulation
implements the force applied by this surface. In the code, the surface is refered as "ground".
*/
class RopeSimulation : public Simulation //An object to simulate a rope interacting with a planer surface and air
{
public:
Vector3D** massesPositions; // Masses possitins on the solid geometry
Spring** springs; //Springs binding the masses (there shall be [numOfMasses - 1] of them)
Vector3D gravitation; //gravitational acceleration (gravity will be applied to all masses)
Vector3D ropeConnectionPos; //A point in space that is used to set the position of the
//first mass in the system (mass with index 0)
Vector3D ropeConnectionVel; //a variable to move the ropeConnectionPos (by this, we can swing the rope)
float groundRepulsionConstant; //a constant to represent how much the ground shall repel the masses
float groundFrictionConstant; //a constant of friction applied to masses by the ground
//(used for the sliding of rope on the ground)
float groundAbsorptionConstant; //a constant of absorption friction applied to masses by the ground
//(used for vertical collisions of the rope with the ground)
float groundHeight; //a value to represent the y position value of the ground
//(the ground is a planer surface facing +y direction)
float airFrictionConstant; //a constant of air friction applied to masses
RopeSimulation( //a long long constructor with 11 parameters starts here
int numOfMasses, //1. the number of masses
float m, //2. weight of each mass
float springConstant, //3. how stiff the springs are
float springLength, //4. the length that a spring does not exert any force
float springFrictionConstant, //5. inner friction constant of spring
Vector3D gravitation, //6. gravitational acceleration
float airFrictionConstant, //7. air friction constant
float groundRepulsionConstant, //8. ground repulsion constant
float groundFrictionConstant, //9. ground friction constant
float groundAbsorptionConstant, //10. ground absorption constant
float groundHeight //11. height of the ground (y position)
) : Simulation(numOfMasses, m) //The super class creates masses with weights m of each
{
this->gravitation = gravitation;
this->airFrictionConstant = airFrictionConstant;
this->groundFrictionConstant = groundFrictionConstant;
this->groundRepulsionConstant = groundRepulsionConstant;
this->groundAbsorptionConstant = groundAbsorptionConstant;
this->groundHeight = groundHeight;
for (int index = 0; index < numOfMasses; ++index) //To set the initial positions of masses loop with for(;;)
{
masses[index]->pos.x = index * springLength; //Set x position of masses[a] with springLength distance to its neighbor
masses[index]->pos.y = 0; //Set y position as 0 so that it stand horizontal with respect to the ground
masses[index]->pos.z = 0; //Set z position as 0 so that it looks simple
}
springs = new Spring*[numOfMasses - 1]; //create [numOfMasses - 1] pointers for springs
//([numOfMasses - 1] springs are necessary for numOfMasses)
for (int index = 0; index < numOfMasses - 1; ++index) //to create each spring, start a loop
{
//Create the spring with index "a" by the mass with index "a" and another mass with index "a + 1".
springs[index] = new Spring(masses[index], masses[index + 1],
springConstant, springLength, springFrictionConstant);
}
}
void release() //release() is overriden because we have springs to delete
{
Simulation::release(); //Have the super class release itself
for (int index = 0; index < numOfMasses - 1; ++index) //to delete all springs, start a loop
{
delete(springs[index]);
springs[index] = NULL;
}
delete(springs);
springs = NULL;
}
void solve() //solve() is overriden because we have forces to be applied
{
for (int index = 0; index < numOfMasses - 1; ++index) //apply force of all springs
{
springs[index]->solve(); //Spring with index "a" should apply its force
}
for (int index = 0; index < numOfMasses; ++index) //Start a loop to apply forces which are common for all masses
{
masses[index]->applyForce(gravitation * masses[index]->m); //The gravitational force
masses[index]->applyForce(-masses[index]->vel * airFrictionConstant); //The air friction
if (masses[index]->pos.y < groundHeight) //Forces from the ground are applied if a mass collides with the ground
{
Vector3D v; //A temporary Vector3D
v = masses[index]->vel; //get the velocity
v.y = 0; //omit the velocity component in y direction
//The velocity in y direction is omited because we will apply a friction force to create
//a sliding effect. Sliding is parallel to the ground. Velocity in y direction will be used
//in the absorption effect.
masses[index]->applyForce(-v * groundFrictionConstant); //ground friction force is applied
v = masses[index]->vel; //get the velocity
v.x = 0; //omit the x and z components of the velocity
v.z = 0; //we will use v in the absorption effect
//above, we obtained a velocity which is vertical to the ground and it will be used in
//the absorption force
if (v.y < 0) //let's absorb energy only when a mass collides towards the ground
masses[index]->applyForce(-v * groundAbsorptionConstant); //the absorption force is applied
//The ground shall repel a mass like a spring.
//By "Vector3D(0, groundRepulsionConstant, 0)" we create a vector in the plane normal direction
//with a magnitude of groundRepulsionConstant.
//By (groundHeight - masses[a]->pos.y) we repel a mass as much as it crashes into the ground.
Vector3D force = Vector3D(0, groundRepulsionConstant, 0) *
(groundHeight - masses[index]->pos.y);
masses[index]->applyForce(force); //The ground repulsion force is applied
}
}
}
void simulate(float dt) //simulate(float dt) is overriden because we want to simulate
//the motion of the ropeConnectionPos
{
Simulation::simulate(dt); //the super class shall simulate the masses
ropeConnectionPos += ropeConnectionVel * dt; //iterate the positon of ropeConnectionPos
if (ropeConnectionPos.y < groundHeight) //ropeConnectionPos shall not go under the ground
{
ropeConnectionPos.y = groundHeight;
}
masses[0]->pos = ropeConnectionPos; //mass with index "0" shall position at ropeConnectionPos
masses[0]->vel = ropeConnectionVel; //the mass's velocity is set to be equal to ropeConnectionVel
}
void setRopeConnectionVel(Vector3D ropeConnectionVel) //the method to set ropeConnectionVel
{
this->ropeConnectionVel = ropeConnectionVel;
}
};