-
Notifications
You must be signed in to change notification settings - Fork 2
/
PAction.cpp
150 lines (124 loc) · 4.12 KB
/
PAction.cpp
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
#include "PAction.h"
#include <iostream>
#include "utils.h"
#include <cstdio>
#include "PEmitter.h"
ConstForceF::ConstForceF(float g, const glm::vec3 &dir) :
g_(g), dir_(glm::normalize(dir))
{ }
void ConstForceF::operator() (Particle *part, float dt)
{
part->vel += dir_ * g_ * dt;
}
/*
PERandomF::PERandomF(float howRandom) : sigma_(howRandom) { }
void PERandomF::operator() (Emitter* em, float dt)
{
glm::vec3 dir(randomFloat(-1, 1), randomFloat(-1, 1), randomFloat(-1, 1));
dir = glm::normalize(dir);
em->loc_ += dir * dt * sigma_;
}
void DefaultActionF::operator()(std::vector<Particle*>&, float dt)
{
return;
}
CentripetalForceF::CentripetalForceF(const glm::vec3 ¢er, const glm::vec3 &up,
float radius) :
center_(center),
up_(glm::normalize(up)),
radius_(radius)
{ }
void CentripetalForceF::operator() (std::vector<Particle*> &parts, float dt)
{
for (size_t i = 0; i < parts.size(); i++)
{
Particle *p = parts[i];
// First we need to get the direction from the center to the point,
// use project for this
glm::vec3 pdir = p->loc - center_;
// up is unit vector, no need for divison by ||up||
glm::vec3 projection = glm::dot(pdir, up_) * up_;
// Outward vector is pdir - projection
glm::vec3 outvec = pdir - projection;
// Get the velocity not in the upwards direction
glm::vec3 upVel = glm::dot(p->vel, up_) * up_;
glm::vec3 sideVel = p->vel - upVel;
// Speed of the circle component
float speed = glm::length(sideVel);
glm::vec3 outdir = glm::normalize(outvec);
// Apply inward force
// inward force, centripetal force see:
// http://en.wikipedia.org/wiki/Centripetal_force
p->vel += -outdir * speed * speed / radius_ * dt;
}
}
void CentripetalForceF::setCenter(const glm::vec3 ¢er)
{
center_ = center;
}
PPointAttractorF::PPointAttractorF(const glm::vec3 &pos, float magnitude) :
pos_(pos), g_(magnitude)
{ }
void PPointAttractorF::operator() (std::vector<Particle*> &parts, float dt)
{
for (size_t i = 0; i < parts.size(); i++)
{
Particle *part = parts[i];
float r = glm::length(part->loc - pos_);
glm::vec3 rhat = glm::normalize(part->loc - pos_);
glm::vec3 theforce = rhat * glm::vec3(g_ / (pow(r, 2.0f)));
part->vel -= theforce * dt;
}
}
PPointSinkF::PPointSinkF(const glm::vec3 &location, float tolerance) :
pos_(location), tol_(tolerance)
{ }
void PPointSinkF::operator() (std::vector<Particle*> &parts, float dt)
{
for (size_t i = 0; i < parts.size(); i++)
{
Particle *part = parts[i];
if (glm::length(part->loc - pos_) < tol_)
{
part->t = -HUGE_VAL;
}
}
}
PPlaneSinkF::PPlaneSinkF(const glm::vec3 &pt, const glm::vec3 &normal) : pt_(pt), normal_(normal) { }
void PPlaneSinkF::operator() (std::vector<Particle*> &parts, float dt)
{
for (size_t i = 0; i < parts.size(); i++)
{
Particle *p = parts[i];
// check to see if it's on the same side as the plane
if (glm::dot(normal_, p->loc - pt_) < 0.f)
p->t = -HUGE_VAL;
}
}
PPlaneBounceF::PPlaneBounceF(const glm::vec3 & pt,
const glm::vec3 &normal_vec,
float elast) :
point_(pt), normal_(normal_vec), elasticity_(elast) { }
void PPlaneBounceF::operator() (std::vector<Particle*> &parts, float dt)
{
// for each particle, check if it's over our plane
for (size_t i = 0; i < parts.size(); i++)
{
Particle *p = parts[i];
if (glm::dot(p->loc - point_, normal_) < 0.0f)
{
// particle in question is 'behind' the normal one
reflectParticleVelocity(p);
}
}
}
void PPlaneBounceF::reflectParticleVelocity(Particle *p)
{
float magnitude = glm::length(p->vel);
//glm::vec3 dn = normal_ - glm::normalize(p.vel);
//glm::vec3 oldvel = p.vel;
// reflected vector
p->vel = magnitude * glm::normalize((normal_ - glm::normalize(p->vel)));
p->vel = elasticity_ * magnitude * glm::reflect(-glm::normalize(p->vel), normal_);
}
*/