openFrameworks freakDay S03E02 Diederick Huijbers - C++/Physics/Cloth Animation/Templates

Post on 28-Nov-2014

4871 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Presentation given at the monthly "freakDays" meetings in Amsterdam on Creative Coding.

Transcript

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

c++ templates Physics

Cloth

Basic C++structsclassespointers

templates<>

struct Particle { float x; float y; float mass;}

Particle

xy

mass

... use the keyword “struct”

.. green means “members are accessible”..

class Particle { float x; float y; float mass;}

Particle

xy

mass

... use the keyword “class”

.. red means “members are NOT accessible”..

Differences:Struct members are

public by default those of a class not.

class Particle { float x; float y; float mass;}

Particle

xy

mass

Particle

xy

mass

Particle

xy

mass

A struct doesn’t need thispublic keyword. Their members are public by default! That’s nice!

class Particle {public: float x; float y; float mass;}

struct Particle { float x; float y; float mass;}

Check how the keyword public makes the members green ;) and so accessible!

When to use struct <-> class?It doesn’t really matter; it’s a personal thing....

...though, typically structsare used for simple datacontainers and classes

for more advanced things.

class Particle {public: Particle(); void setPosition(float x, float y); void update(); void draw(); void applyRepulsiveForce(); void addForce(float x, float y);

private: float x; float y; float mass;}

Classes for more advanced stuff

struct User { string name; string password; string homepage; int age; float weight;};

struct Tweet { uint16 userid; string homepage; string avatar_url; int timestamp; bool has_gps;};

Structs for simple data containers

Pointers !!!

Pointers are not that hard!Instead of pointing to a

value hold a a memory address!

Pointers are not that hardValues Address in memory

f #1

r #2

e #3

a #4

k #5

d #6

a #7

y #8

Values Address in memory

f #1

r #2

e #3

a #4

k #5

d #6

a #7

y #8

\0 #9

? #10

? #11

char* name = “freakday”

name + 0

name + 1

name + 2

name + 3

name + 4

name + 5

name + 6

name + 7

name + 8

char *Check the char* the star (*) tells the compiler we want a pointer a char. A normal char is just one character. The \0 is automatically added and tells the compiler it’s the end of the “string”

A pointer points hold an memory address. We can step through the memory addresses using this type of variable.

Values

f #1

r #2

e #3

a #4

k #5

d #6

a #7

y #8

\0 #9

? #10

? #11

name + 9

name + 10

Do not go into unauthorized memory ....or else.....

“EXC_BAD_ACCESS” or“UNDEFINED” behavior

...which is ....

Check XCode project “freakday_S03E02_pointers”

Memory Alignment + packing

class Particle { bool enabled; // 8 bits float x; // 32 bits float y; // 32 bits bool flying; // 8 bits}

enabled

xy

flying

= memory needed

= memory actually used

}32 bit wide

WRONG!You should align your bytes nicely

When the CPU reads from memory it uses a natural alignment which must be respected to permit the CPU to read and write memory effectively. A compiler will leave holes in memory when members/objects aren’t aligned properly.

}

Memory Alignment + packing

class Particle { float x; // 32 bits float y; // 32 bits bool flying; // 8 bits bool enabled; // 8 bits}

xy

f

= memory needed

= memory actually used

32 bit wide

CORRECT!The members are aligned nicely

e

Memory Alignment + packing

Check XCode project “freakday_S03E02_packing”

[TYPE_ADDRESS]: some value[ADDRESS_ENTRY]: some value

[TYPE_PHONE]: some value

Templates

Office address: some valueBilling address: some valueMobile phone: some valueWork phone: some value

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>

Templates

class Particle2D { ofVec2f position; ofVec2f velocity; ofVec2f forces; void draw();}

class 2DParticlesGroup { vector<Particle2D*> particles; void addForce(ofVec2f f) { for(int i = 0; i < particles.size(); ++i) { particles.at(i)->addForce(f); } }}

2D particles....

Particle-Group

Particle

class Particle3D { ofVec3f position; ofVec3f velocity; ofVec3f forces; void draw();}

class 3DParticlesGroup { vector<Particle3D*> particles; void addForce(ofVec3f f) { for(int i = 0; i < particles.size(); ++i) { particles.at(i)->addForce(f); } }}

3D particles....

Particle-Group

Particle

class Particle4D { ofVec4f position; ofVec4f velocity; ofVec4f forces; void draw();}

class 4DParticlesGroup { vector<Particle4D*> particles; void addForce(ofVec4f f) { for(int i = 0; i < particles.size(); ++i) { particles.at(i)->addForce(f); } }}

4D particles....

Particle-Group

Particle

5D, 6D, 7D ... or templateAdd 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.

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;};

Templated Particle

template<typename P, typename V>class ParticleGroup {public: ParticleGroup(); void addParticle(P oParticle); void addForce(V oForce); void update(); void draw();

private: vector<P> particles};

Templated Particle-Group

template<typename P, typename V>class ParticleGroup {public: ParticleGroup(); void addParticle(P oParticle); void addForce(V oForce); void update(); void draw();

private: vector<P> particles};

Example of templated particles

Check XCode project “freakday_S03E02_templates”

Keyword TypenameConsider 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.

template<typename T>class SomeClass {public: typename T::MyType* ptr;};

template<typename T>class SomeClass {public:

T::MyType* ptr;};

WRONG: Here T::MyType * ptr would mean a multiplication

class WithStatic {public: static int MyType;}

Here T::MyType * ptr would refer to the nested type in the WithType class.

class WithType {public: class MyType { }}

-- 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 containerMyContainer<Particle2D*> particles;particles.items.push_back(new Particle2D()); particles.items.push_back(new Particle2D());particles.draw();

When to use the keyword typename

Here we make sure that iterator is a type, not a static member! Usually you use the keyword typename with STL iterators

Physics

An object continues with constant velocity unless a

force acts upon it [1]

Newtons first law

Newtons first law

1 2 3 4 5 6 7time and position

Velocity vector(s):ofxVec2f, ofxVec3f

Note that the red arrow stays the same size. The red arrow represents the velocity vector and showing the first law

Check XCode project “freakday_S03E02_5_simple_motion”

1 2 3 4 5 6 7time and position

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.

Check XCode project “freakday_S03E02_6_simple_motion_with_drag”

// example faking dragvoid Particle::update() { velocity *= 0.98;}

The amount of drag, the 0.98 in this example, totally depends on what you want. It’s a case of tweaking to get the right behavior.

A force acting on a object produces acceleration that

is proportional to the object’s mass. [1]

Newtons second law

Newtons second law

this arrow represents the force acting on the object

this is the resulting forcewhen mass is taken intoaccount

160-200 KG (?)

Newtons second law

this arrow represents the force acting on the object

this is the resulting forcewhen mass is taken intoaccount

75-80 KG

Newtons second law

force = mass * acceleration

The math of how force, acceleration and mass is related....

...to get the acceleration we do:

“The law” ( F = ma )

this is what I use in particle systems

acceleration = 1/mass * force

Newtons second law

acceleration = 1/mass * force

This one is important! The bigger the mass, the less the

acceleration

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

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) { forces += oForce; } void update() { forces *= inverse_mass; velocity += forces; velocity *= 0.99; position += velocity; forces.set(0,0); }};

How does this look like in code?

Check XCode project “freakday_S03E02_7_simple_motion_inverse_mass”

D’Alembert’s Principle (simplified):We can accumulate all forces acting on an object.

“Springs are structural elements that, when

connected between two objects, apply equal and opposite forces to each

object.”

Springs

Springs

Object 2Object 1

The red arrows represent force vectors in opposite directions: so the two objects are pulled towards each other

Springs

-k = spring strength; in code just a “float strength” which often gets a value like 0.1, 0.001

The rule related to springsforces is called “Hooks” law!

f = -k∆L

∆L = difference between springs “compressed/rest length” and current length.

∆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

∆L = (r - d)

(r) rest length

Two particles connected by a spring

(d) distance

Spring force vector Spring force vector

(d) distance

Spring force vector Spring force vector

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 = (b->position - a->position).length();! }

! void update() {! ! V dir = b->position - a->position;! ! float dist = dir.length();! ! if(dist == 0.0) {! ! ! dist = 0.0001; // division by zero! ! } ! !! ! float f = (rest_length - dist) * k; ! ! dir.normalize();! ! a->addForce(dir * -f);! ! b->addForce(dir * f);! }!! P a,b;

Spring template 2d/3d/..

Rest length

Rest length: distance between particles when

creating the spring

Current distance

The force spring

Force spring multiplied by normalized direction vector and in opposite directions

Springs

Check XCode project “freakday_S03E02_8_spring_forces”

Check XCode project “freakday_S03E02_9_spring_forces_with_gui”

Example: click mouse to add particle + spring...

Example: right click mouse to add particle + spring and use sliders to see the result of

different “k” and “drag” values.

Cloth Physics

Cloth PhysicsSimple cloth physics used multiple springs connected

to particles in a grid.

Cloth Physics

Particles are positioned on a grid and then connected by 3 kind of springs:

- structural springs- shear springs- bending springs

Cloth PhysicsStructural springs

Cloth PhysicsShear springs

Cloth Physics

Bending springs

Errors

are

beauti

ful :)

Check XC

ode project “freakday_S03E02_10_cloth”

// 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;! ! }! }}

Creating the particle grid

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.

// create springs.Particle3D* a;Particle3D* b;for(int i = 0; i < nCols; ++i) {! for(int j = 0; j < nRows; ++j) {! !! ! // 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);! ! }! }}

For more info on how to create the other springs see the source; it’s quite similar.

Creating the structural springs

Check XCode project “freakday_S03E02_11_with_gui”

Next time C++/...:

Initializer listsVirtual functionsInheritance More templates.....Debugging linker errors (file, nm)Operator overloading (=,[],*,etc.)Const, static

Integrators (euler, verlet, runge kutta)

Fast particle systems (buckets, sorting)

BillboardingMatrices / 3DShaders

Next time particles/3d

....

Other suggestions...

References1. Ian Millington, Game Physics Engine Development, 2007

top related