OGDC 2014_Build your own Particle System_Mr. Nguyen Dang Quang

Preview:

Citation preview

1

ENABLE YOU TO MAKE A

PARTICLE SYSTEM SIMPLE & CUSTOMIZABLE THAT IS

2

1. BREAK IT DOWN

2. BUILD IT UP

1. BREAK IT DOWN

3

EMITTER

PARTICLE

WORLD

4

POSITION

POSITION OVER LIFE

POSITION AT BIRTH

SCALE

SCALE OVER LIFE

SCALE AT BIRTH

ROTATION

ROTATION OVER LIFE

ROTATION AT BIRTH

OPACITY

OPACITY OVER LIFE

OPACITY AT BIRTH

ANCHOR

ANCHOR OVER LIFE

ANCHOR AT BIRTH

5

POSITION

POSITION OVER LIFE

POSITION AT BIRTH

SCALE

SCALE OVER LIFE

SCALE AT BIRTH

ROTATION

ROTATION OVER LIFE

ROTATION AT BIRTH

OPACITY

OPACITY OVER LIFE

OPACITY AT BIRTH

ANCHOR

ANCHOR OVER LIFE

ANCHOR AT BIRTH POSITION

POSITION OVER LIFE

POSITION AT BIRTH

SCALE

SCALE OVER LIFE

SCALE AT BIRTH

ROTATION

ROTATION OVER LIFE

ROTATION AT BIRTH

OPACITY

OPACITY OVER LIFE

OPACITY AT BIRTH

ANCHOR

ANCHOR OVER LIFE

ANCHOR AT BIRTH

POSITION

POSITION OVER LIFE

POSITION AT BIRTH

SCALE

SCALE OVER LIFE

SCALE AT BIRTH

ROTATION

ROTATION OVER LIFE

ROTATION AT BIRTH

OPACITY

OPACITY OVER LIFE

OPACITY AT BIRTH

ANCHOR

ANCHOR OVER LIFE

ANCHOR AT BIRTH

POSITION

POSITION OVER LIFE

POSITION AT BIRTH

SCALE

SCALE OVER LIFE

SCALE AT BIRTH

ROTATION

ROTATION OVER LIFE

ROTATION AT BIRTH

OPACITY

OPACITY OVER LIFE

OPACITY AT BIRTH

ANCHOR

ANCHOR OVER LIFE

ANCHOR AT BIRTH

6

P POSITION

P POSITION OVER LIFE

P POSITION AT BIRTH

RANDOM

RANDOM

P SCALE

P SCALE OVER LIFE

P SCALE AT BIRTH

RANDOM

RANDOM

P ROTATION

P ROTATION OVER LIFE

P ROTATION AT BIRTH

RANDOM

RANDOM

P OPACITY

P OPACITY OVER LIFE

P OPACITY AT BIRTH

RANDOM

RANDOM

P ANCHOR

P ANCHOR OVER LIFE

P ANCHOR AT BIRTH

RANDOM

RANDOM

7

OPACITY

ROTATION

SCALE

POSITION

ANCHOR

NOISE

DISTRIBUTION

SHAPE SIZE

SHAPE

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

PARTICLE INSTANCES

35

PARTICLE INSTANCES

PARTICLE GROUPS

36

1. BREAK IT DOWN

2. BUILD IT UP 2. BUILD IT UP

37

OUTPUT

INPUT

INPUT

WIND DRAG GRAVITY BOUNCE TIME STRETCH TIME LOOP

DENSITY QUANTITY

SPREAD SPEED LIFE

ANCHOR

RANDOM SEED

POSITION SCALE ROTATION

LOOK

OPACITY

BIRTH

AGE

INDEX

LIFE

ANCHOR POSITION

SCALE ROTATION

OPACITY

START TIME

OPACITY ROTATION

SCALE POSITION ANCHOR

NOISE DISTRIBUTION

SHAPE SIZE SHAPE

38

1. EMITTER OBJECT contains all centralized inputs for controlling all of its child particle groups

int shape

float[3] shapeSize

int distribution

float[3] noise

float[3] anchor, position, scale, rotation

float opacity

39

2. PARTICLE GROUP OBJECT contains all centralized inputs for controlling all of its child particle groups

Image look

int randomSeed

float startTime

float quantity

float density

float life, lifeRandom

float speed, speedRandom

boolean speedOverdriveFromEmitterMotion

40

contains all centralized inputs for controlling all of its child particle groups

float[3] spreadAngle, spreadRange, spreadRandom

boolean spreadFollowEmitterMotion

float[3] anchorOffset, anchorOffsetRandom,

anchorWiggleFrequency, anchorWiggleAmplitude

float[3] positionWiggleFrequency,

positionWiggleAmplitude

2. PARTICLE GROUP OBJECT

41

contains all centralized inputs for controlling all of its child particle groups

float[2] scale, scaleRandom,

scaleWiggleFrequency, scaleWiggleAmplitude

float[3] rotationAtBirth, rotationAtBirthRandom,

rotationSpeed, rotationSpeedRandom,

rotationWiggleFrequency,

rotationWiggleAmplitude

boolean[3] rotationInBothDirection

float opacity, opacityRandom,

opacityWiggleFrequency, opacityWiggleAmplitude

2. PARTICLE GROUP OBJECT

42

2. PARTICLE GROUP OBJECT contains all centralized inputs for controlling all of its child particle groups

float[3] wind

float[3] gravity

boolean bounce

float bounceFloorDistance,

bounceElasticity, bounceFriction

float drag

float timeStretch

float timeLoop

43

contains generated properties to draw on screen

int index

float birth, life, age

float[3] anchor

float[3] position

float[2] scale

float[3] rotation

float opacity

3. PARTICLE INSTANCE OBJECT

44

SCALE

45

Particle Life is the longevity of the particle. It tells when the particle dies: life = pg.life + random(-pg.lifeRandom, pg.lifeRandom);

If we have PG Life Random, Particle Life will differ from PG Life.

Particle Birth is the moment the particle gets born: birth = pg.startTime + index/pg.density;

PG Start Time is the time this Particle Group starts showing up. Particle Index is the order of the particle, starting from 0. PG Density is how many particles get born in a second.

Particle Age is how old the particle is at a certain time: age = time – birth;

Time is the global value. It keeps increasing over time.

1. PARTICLE BIRTH + LIFE + AGE

46

SCALE

47

Every particle has its anchor at the center of it. If we need PG Anchor Offset feature, we need to implement it like this: anchor = pg.anchorOffset +

random(-pg.anchorOffsetRandom,

pg.anchorOffsetRandom);

Anchor alters the result when rotating or scaling an object:

2. PARTICLE ANCHOR

48

SCALE

49

Particle follows Emitting Direction. When Emitting Direction changes, Particle Direction changes, affecting Particle Position.

3. PARTICLE POSITION

50

Step 2: Calculate Particle Direction affected by Emitter Rotation and PG Spread: direction =

emitter.rotation +

pg.spreadAngle +

random(-pg.spreadRandom,

pg.spreadRandom);

Step 1: Define vector Particle Velocity pointing straight up (-Y): velocity = [0, -pg.speed, 0];

PG Speed defines how fast particles travel when they are born.

3. PARTICLE POSITION

51

3D Rotation reference: http://www.cs.helsinki.fi/group/goa/mallinnus/3dtransf/3drot.html

Step 3: Transform vector Particle Velocity according to Particle Direction: v = velocity; d = direction;

• X-Axis Rotation: vNew[0] = v[0]; vNew[1] = v[1] * cos(d[0]) - v[2] * sin(d[0]);

vNew[2] = v[1] * sin(d[0]) + v[2] * cos(d[0]);

• Y-Axis Rotation: vNew[0] = v[2] * sin(d[1]) + v[0] * cos(d[1]);

vNew[1] = v[1];

vNew[2] = v[2] * cos(d[1]) - v[0] * sin(d[1]);

• Z-Axis Rotation (2D Rotation): vNew[0] = v[0] * cos(d[2]) – v[1] * sin(d[2]);

vNew[1] = v[0] * sin(d[2]) + v[1] * cos(d[2]);

vNew[2] = v[2];

3. PARTICLE POSITION

52

particlePositionAtBirth emitterPosition

vNew * age

Step 4: We now have new vector Particle Velocity. Multiply it with Particle Age to get its local Particle Position over time: position = vNew * age;

Finally we get global Particle Position: position += emitter.Position;

3. PARTICLE POSITION

53

Emitter Size

Random point picking reference for other shapes: http://mathworld.wolfram.

com/topics/

RandomPointPicking.html

If Emitter Shape Size is not zero. Position At Birth is a random point within Emitter Shape. So it is affected by Emitter Shape and Emitter Shape Size: positionAtBirth =

random(-emitter.shapeSize/2,

emitter.shapeSize/2);

particlePositionAtBirth

emitterPosition

vNew * time

3. PARTICLE POSITION

So we have to count in Particle Position At Birth: position += positionAtBirth;

54

SCALE

55

Particle Scale defines the size of the particle. And it is affected by PG Scale and PG Scale Random: scale = pg.scale +

random(-pg.scaleRandom, pg.scaleRandom);

In order to change Particle Scale Over Life we need to enable key frames for PG Scale so its value varies from time to time, and then get its value at its proper age, we call it PG Age: pgAge = age * pg.life/life;

So we use this code instead of the one above: scale = pg.scale.valueAtTime(pgAge) +

random(-pg.scaleRandom, pg.scaleRandom);

4. PARTICLE SCALE

56

SCALE

57

Particle Rotation is a little more complicated. We need to apply both PG Particle Rotation At Birth and PG Rotation Speed: rotation = pg.rotationAtBirth +

random(-pg.rotationAtBirthRandom,

pg.rotationAtBirthRandom) +

age *

(pg.rotationSpeed.valueAtTime(age * pg.life/life) +

random(-pg.rotationSpeedRandom,

pg.rotationSpeedRandom));

5. PARTICLE ROTATION

58

SCALE

59

Also like Particle Scale, Particle Opacity is simple, supporting Particle Opacity Over Life: opacity = pg.opacity.valueAtTime(pgAge) +

random(-pg.opacityRandom, pg.opacityRandom);

6. PARTICLE OPACITY

60

To achieve uniform spread, we need to add to the Particle Direction code that we made before: direction = emitter.rotation + pg.spreadAngle +

random(-pg.spreadRandom, pg.spreadRandom);

…with this: direction += pg.spreadAngle – pg.spreadRange/2 +

pg.spreadRange/pg.quantity * index;

Quantity is the total number of particles of this Particle Group.

PARTICLE UNIFORM SPREAD

61

To implement Wiggle Effect for Position, Scale, Opacity and even Rotation, we need to replicate the wiggle expression in After Effects. Here is an example expression of Particle Scale Wiggle in After Effects: scale = pg.scale +

wiggle(pg.scaleWiggleFrequency,

pg.scaleWiggleAmplitude);

PG Scale Wiggle Frequency is how many times a second the value changes. PG Scale Wiggle Amplitude is how large the value changes each time.

Go to this link for reference: http://codepen.io/jamiejefferson/pen/hHegc

WIGGLE

62

PG Wind is a vector that helps push particles at a constant speed: position += age * pg.wind;

PG Gravity makes particles fall down or float up at an accelerated speed. We can use this equation: position[1] = 0.5 * pg.gravity * age * age +

vNew[1] * age;

PG Drag makes particles slow down over time to zero speed: if (age == 0) age = 0.000001;

dragModifier = (1 – exp(-pg.drag * age)) /

(pg.drag * age);

position *= age * dragModifier;

WIND + GRAVITY + DRAG

63

PG Bounce is another story. We need to pass launch velocity, gravity, bounce floor height, elasticity and friction to get the vertical height of the particle.

Step 1: We have velocity and gravity, we can find the max height:

𝒉 =𝒗𝟐

𝟐𝒈=

𝒈𝟐𝒕𝟐

𝟐𝒈=

𝒈𝒕𝟐

𝟐 (𝒗 = 𝒈𝒕)

maxHeight = pg.bounceFloorDistance +

(vNew[1] * vNew[1]) / (2 * pg.gravity);

Step 2: Find the time the particle reaches the floor. It consists of the time the particle travels from its position at birth to the max height and the time from the max height to the floor. Time at bounce:

𝒕 = 𝒕𝟏 + 𝒕𝟐

BOUNCE

64

At max height velocity reaches zero, so we have the time from position at birth to the max height:

𝒗 = 𝒗𝟎 − 𝒈𝒕𝟏 ⇒ 𝟎 = 𝒗𝟎 − 𝒈𝒕𝟏 ⇒ 𝒕𝟏 =𝒗𝟎

𝒈

We have the max height and the gravity, we can find the time from the max height to the floor:

𝒕𝟐 =𝟐𝒉

𝒈 (𝒉 =

𝒈𝒕𝟐𝟐

𝟐 )

Finally we have: timeAtBounce = vNew[1]/pg.gravity +

sqrt(2 * maxHeight/pg.gravity);

BOUNCE

65

Step 3: If the particle has not reached the floor (Particle Age is less than Particle Time At Floor), it just moves under the effect of the gravity:

𝒉 = 𝒗𝒕 −𝒈𝒕𝟐

𝟐

position[1] = pg.bounceFloorDistance +

vNew[1] * age –

(pg.gravity * age * age)/2;

If the particle has reached the floor (Particle Age is equal or more than Particle Time At Floor), it’s time to calculate the bounce. First we invert the velocity at bounce:

𝒗 = 𝒗𝟎 − 𝒈𝒕

v[1] = -(vNew[1] – pg.gravity * timeAtBounce);

BOUNCE

66

When the particle bounces on the floor, it will loose some velocity basing on PG Bounce Elasticity: v[1] *= pg.bounceElasticity;

If PG Bounce Elasticity is less than 1: the particles will lose some vertical velocity after each bounce; is more than 1: they gain more vertical velocity.

The same for PG Bounce Friction but applied for horizontal velocity instead.

Then we add the time to the next bounce. It is twice the time to reach the max height (if we consider there is no drag):

𝒕 = 𝟐 ×𝒗

𝒈

timeAtBounce += 2 * v[1]/pg.gravity;

Step 4: We repreat it again and againfrom bounce to bounce until the time between any two bounces is less than one frame duration.

Reference bounce code: http://www.motion-graphics-exchange.com/

after-effects/Object-bouncing-on-a-floor/

473c0e7522331 BOUNCE

67

Time Loop enables us to make seamless transition between the end and the beginning of our animation, so that the animation can repeat forever. Simple, we implement Time Loop by controlling Particle Age: if (pg.timeLoop > 0 && age < 0)

age += pg.timeLoop;

This code will make unfinished particles at the end of the loop continue their existence at the beginning of the loop.

TIME LOOP

68

Time Stretch defines the time and speed of the whole Particle Group. For example if Time Stretch = 50%, the Particle Group only has half the time to finish its animation, thus it will play faster at double speed. We can cheat it without changing the speed by speeding up Particle Age alone: timeStretch = abs(pg.timeStretch)/100;

age /= timeStretch;

if (pg.timeStretch < 0)

age = pg.life + pg.lifeRandom –

age – birth/timeStretch * 2;

if (pg.timeLoop > 0 && age < 0)

age += pg.timeLoop/timeStretch;

However Time Stretch also affects Particle Birth as they will get born sooner or later: birth = pg.startTime + timeStretch * index/pg.density;

TIME STRETCH

69

INPUT

OUTPUT

INPUT

1.

SHAPE SHAPE SIZE

POSITION SCALE

ROTATION

WIND DRAG GRAVITY BOUNCE TIME STRETCH TIME LOOP

OPACITY

DENSITY QUANTITY

SPREAD SPEED LIFE

ANCHOR

RANDOM SEED

POSITION SCALE ROTATION

LOOK

OPACITY

BIRTH

AGE

INDEX

LIFE

ANCHOR POSITION

SCALE ROTATION

OPACITY

DISTRIBUTION

ANCHOR NOISE

START TIME 2. 3.

SCALE

70

For more information contact: quangnd1503@gmail.com / quangnd@vng.com.vn

71

Recommended