1. Hello
Apollo
Diederick Huijbers
diederick@apollomedia.nl
www.apollomedia.nl
2. This presentation is part of the openFrameworks
freakDays meetings which are given by a group of
Creative Coders and artists in Amsterdam.
During these monthly meetings we give
presentation on innovative techniques and show
projects we’re involved in.
For more information checkout www.roxlu.com or
contact us at info@roxlu.com
9. Check how the keyword A struct doesn’t need this
public makes the members public keyword. Their
green ;) and so accessible! members are public by
default! That’s nice!
class Particle { class Particle { struct Particle {
float x; public: float x;
float x; float y;
float y; float y;
float mass; float mass; float mass;
} } }
Particle Particle Particle
x x x
y y y
mass mass mass
10. When to use struct <-> class?
It doesn’t really matter;
it’s a personal thing....
15. Pointers are not that hard!
Instead of pointing to a
value hold a
a memory address!
16. Pointers are not that hard
Values Address in memory
f #1
r #2
e #3
a #4
k #5
d #6
a #7
y #8
17. char* name = “freakday”
Values Address in memory
f #1 name + 0
char * r #2 name + 1
Check the char* the star (*)
tells the compiler we want a e #3 name + 2
pointer a char. A normal char
is just one character. The 0 is a #4 name + 3
automatically added and tells
the compiler it’s the end of the k #5 name + 4
“string”
A pointer points hold an
d #6 name + 5
memory address. We can
step through the memory a #7 name + 6
addresses using this type
of variable. y #8 name + 7
0 #9 name + 8
? #10
? #11
18. Values Do not go into unauthorized
f
r
#1
#2
memory ....or else.....
e #3 “EXC_BAD_ACCESS” or
a #4
k #5 “UNDEFINED” behavior
d #6
a #7 ...which is ....
y #8
0 #9
? #10 name + 9
? #11 name + 10
20. Memory Alignment + packing
32 bit wide
}
When the CPU reads from
memory it uses a natural class Particle { enabled
alignment which must be bool enabled; // 8 bits
respected to permit the CPU float x; // 32 bits x
to read and write memory float y; // 32 bits y
effectively. A compiler will bool flying; // 8 bits
leave holes in memory when flying
members/objects aren’t }
aligned properly.
= memory needed WRONG!
= memory actually used You should align
your bytes nicely
21. Memory Alignment + packing
32 bit wide
}
class Particle {
float x; // 32 bits x
float y; // 32 bits y
bool flying; // 8 bits f e
bool enabled; // 8 bits
}
= memory needed CORRECT!
= memory actually used The members are
aligned nicely
25. Templates
Templates are a way to write more generic code: write
one special thing (algorithm) which you can use for
many kind of types.
Create one template for a particle for both 2D and 3D.
Particle<2D> and Particle<3D>
26. 2D particles....
Particle
class Particle2D {
ofVec2f position;
ofVec2f velocity;
ofVec2f forces;
void draw();
}
Particle-Group
class 2DParticlesGroup {
vector<Particle2D*> particles;
void addForce(ofVec2f f) {
for(int i = 0; i < particles.size(); ++i) {
particles.at(i)->addForce(f);
}
}
}
27. 3D particles....
Particle
class Particle3D {
ofVec3f position;
ofVec3f velocity;
ofVec3f forces;
void draw();
}
Particle-Group
class 3DParticlesGroup {
vector<Particle3D*> particles;
void addForce(ofVec3f f) {
for(int i = 0; i < particles.size(); ++i) {
particles.at(i)->addForce(f);
}
}
}
28. 4D particles....
Particle
class Particle4D {
ofVec4f position;
ofVec4f velocity;
ofVec4f forces;
void draw();
}
Particle-Group
class 4DParticlesGroup {
vector<Particle4D*> particles;
void addForce(ofVec4f f) {
for(int i = 0; i < particles.size(); ++i) {
particles.at(i)->addForce(f);
}
}
}
29. 5D, 6D, 7D ... or template
Add this before your template class:
“template<typename T>”.
The “T” is the type parameter: Particle2D, Particle3D, etc..
The name “T” can be anything you like, but T is convention.
Also correct:
template<typename SomeType>
template<class SomeType>
template<class T>
“Typename” and “class” can be used both, “typename”
is preferred.
30. Templated Particle
template<typename T>
class Particle {
public:
Particle(T oPosition, float nMass);
void addForce(T oForce);
void update();
void draw();
private:
T position;
T forces;
T velocity;
float mass;
};
33. Keyword Typename
Consider the following code:
template<typename T>
class SomeClass {
public:
typename T::SubType* ptr;
};
Makes sure that subtype is
seen as a type, not a static
member.
34. class WithStatic { class WithType {
public: public:
static int MyType; class MyType {
} }
}
Here T::MyType * ptr
WRONG: Here T::MyType * ptr would refer to the nested type
would mean a multiplication in the WithType class.
template<typename T> template<typename T>
class SomeClass { class SomeClass {
public: public:
typename T::MyType* ptr;
T::MyType * ptr; };
};
35. When to use the keyword typename
-- pseudo code --
template<typename T>
class MyContainer {
vector<T> items;
void draw() {
typename vector<T>::iterator it = items.begin();
while(it != items.end()) {
(*it)->draw();
++it;
}
}
};
-- add some particles to container
MyContainer<Particle2D*> particles;
particles.items.push_back(new Particle2D());
particles.items.push_back(new Particle2D());
particles.draw();
Here we make sure that
iterator is a type, not a static
member! Usually you use the
keyword typename with STL
iterators
37. Newtons first law
An object continues with
constant velocity unless a
force acts upon it[1]
38. Newtons first law
Note that the red arrow stays the same size. The red arrow
represents the velocity vector and showing the first law
Velocity vector(s):
ofxVec2f, ofxVec3f
time and position
1 2 3 4 5 6 7
Check XCode project
“freakday_S03E02_5_simple_motion”
39. When creating particle systems I often simulate
drag by degreasing the velocity by a small percentage.
Note how the velocity vector below get’s smaller.
// example faking drag The amount of drag, the 0.98
void Particle::update() { in this example, totally
velocity *= 0.98; depends on what you want.
It’s a case of tweaking to get
} the right behavior.
time and position
1 2 3 4 5 6 7
Check XCode project
“freakday_S03E02_6_simple_motion_with_drag”
40. Newtons second law
A force acting on a object
produces acceleration that
is proportional to the
object’s mass.
[1]
41. Newtons second law
this is the resulting force
this arrow represents the
when mass is taken into
force acting on the object
account
160-200 KG (?)
42. Newtons second law
this is the resulting force
this arrow represents the
when mass is taken into
force acting on the object
account
75-80 KG
43. Newtons second law
The math of how force,
acceleration and mass is related....
“The law” ( F = ma )
force = mass * acceleration
...to get the acceleration we do:
acceleration = 1/mass * force
this is what I use in particle systems
44. Newtons second law
This one is important!
The bigger the mass, the less the
acceleration
ration = 1/mass * force
accele
This is what we call inverse mass.
We do not need to recalculate this
for each update! We store this in a
member of the Particle class and
can be used to represent “infinite”
mass when set to zero:
0 * force = 0
45. How does this look like in code?
class Particle {
ofxVec2f position;
ofxVec2f velocity;
ofxVec2f forces;
float inverse_mass;
Particle(float fMass) {
if(mass <= 0) {
inverse_mass = 0;
}
else {
inverse_mass = 1/mass;
}
}
void addForce(ofxVec2f oForce) { D’Alembert’s Principle (simplified):
forces += oForce; We can accumulate all forces acting
} on an object.
void update() {
forces *= inverse_mass;
velocity += forces;
velocity *= 0.99;
position += velocity;
forces.set(0,0);
}
};
Check XCode project
“freakday_S03E02_7_simple_motion_inverse_mass”
46. Springs
“Springs are structural
elements that, when
connected between two
objects, apply equal and
opposite forces to each
object.”
47. Springs
Object 1 Object 2
The red arrows represent force
vectors in opposite directions: so
the two objects are pulled
towards each other
48. Springs
The rule related to springs
forces is called “Hooks” law!
f = -k∆L
-k = spring strength; in code just a
“float strength” which often gets a
value like 0.1, 0.001
∆L = difference between springs
“compressed/rest length” and current
length.
49. ∆L = (r - d)
difference between springs
“compressed/rest length” and
current length.
Two springs not
stretched/compressed
and showing their rest
length.
}
r = rest length
50. ∆L = (r - d)
Two particles connected by a spring
(r) rest length
Spring force vector Spring force vector
(d) distance
51. Spring force vector Rest length Spring force vector
(d) distance
Spring template 2d/3d/..
template<typename P, typename V>
class Spring {
public:
! Spring(P pParticleA, P pParticleB, float nStrength = 0.01)
! :a(pParticleA)
! ,b(pParticleB)
! ,k(nStrength)
! { Rest length: distance
! ! rest_length = (b->position - a->position).length(); between particles when
! } creating the spring
! void update() {
! ! V dir = b->position - a->position;
Current
! ! float dist = dir.length(); distance
! ! if(dist == 0.0) {
! ! ! dist = 0.0001; // division by zero
! ! }
! !
! ! float f = (rest_length - dist) * k; The force spring
! ! dir.normalize();
! ! a->addForce(dir * -f);
! ! b->addForce(dir * f);
! }
!
! P a,b;
Force spring multiplied by normalized direction
vector and in opposite directions
52. Springs
Example: click mouse to add particle + spring...
Check XCode project
“freakday_S03E02_8_spring_forces”
Example: right click mouse to add particle +
spring and use sliders to see the result of
different “k” and “drag” values.
Check XCode project
“freakday_S03E02_9_spring_forces_with_gui”
59. Check XCode project “freakday_S03E02_10_cloth”
re )
s ul :
or tif
a
rr u
E ea
b
60. Creating the particle grid
// lets create the grid.
for(int i = 0; i < nCols; ++i) {
! for(int j = 0; j < nRows; ++j) {
! ! ofxVec3f position(i * nSize, j * nSize);
! ! Particle3D* particle = new Particle3D(position, 1.1);
! ! particles[j * cols + i] = particle;
! ! if(j == 0) {
! ! ! particle->inverse_mass = 0;
! ! }
! }
Calculating the index in the vector. We position the
} particle just like normal image pixels are stored, by
column and row. This is handy when we need to
lookup (see getAt) a particle based on a column
and row.
61. Creating the structural springs
// create springs. For more info on
Particle3D* a; how to create the
Particle3D* b;
for(int i = 0; i < nCols; ++i) {
other springs see
! for(int j = 0; j < nRows; ++j) { the source; it’s
! ! quite similar.
! ! // structural spring - right.
! ! if(i < nCols-1) {
! ! ! a = getAt(i,j);!
! ! ! b = getAt(i+1, j);
! ! ! springs.createSpring(a,b);
! ! }
! !
! ! // structural spring - down
! ! if(j < nRows-1) {
! ! ! a = getAt(i,j);
! ! ! b = getAt(i, j+1);
! ! ! springs.createSpring(a,b);
! ! }
! }
}
Check XCode project “freakday_S03E02_11_with_gui”
62. Next time C++/...:
Initializer lists
Virtual functions
Inheritance
More templates
.....
Debugging linker errors (file, nm)
Operator overloading (=,[],*,etc.)
Const, static
63. Next time particles/3d
Integrators
(euler, verlet, runge kutta)
Fast particle systems
(buckets, sorting)
Billboarding
Matrices / 3D
Shaders