(Inbe) Tweening : the process of generating intermediate frames - - PowerPoint PPT Presentation

inbe tweening the process of generating intermediate
SMART_READER_LITE
LIVE PREVIEW

(Inbe) Tweening : the process of generating intermediate frames - - PowerPoint PPT Presentation

(Inbe) Tweening : the process of generating intermediate frames between two key frames to give the appearance that the first evolves smoothly into the second. http://www.senocular.com http://en.wikipedia.org/wiki/Inbetweening Easing Functions :


slide-1
SLIDE 1

(Inbe)Tweening : the process of generating intermediate frames between two key frames to give the appearance that the first evolves smoothly into the second.

http://www.senocular.com http://en.wikipedia.org/wiki/Inbetweening

slide-2
SLIDE 2

Easing Functions : Mathematical functions used by tweening algorithms to calculate property values at time points between key frames Ease-in : The gradual shift of a tweened property from a stationary value to full animation Ease-out : The gradual shift of a tweened property from full animation to a stationary value. Easing can be applied to any numeric property

  • x, y position
  • width, height
  • fill and line colors
  • line width

Easing.pde

slide-3
SLIDE 3

Ease-in Functions

N

Time Value

0.2 0.4 0.6 0.8 1 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Fractional Value Change Normalized Time

Ease-in

Linear (N=1) Quadratic (N=2) Cubic (N=3) Quartic (N=4) Quintic (N=5)

EaseInRace.pde

slide-4
SLIDE 4

Ease-out Functions

N

Time Value ) 1 ( 1

0.2 0.4 0.6 0.8 1 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Fractonal Value Change Normalized Time

Ease-out

Linear (N=1) Quadratic (N=2) Qubic (N=3) Quartic (N=4) Quintic (N=5)

EaseOutRace.pde

slide-5
SLIDE 5

Ease-in + Ease-out

  • First half – Scaled Ease in
  • Second half – Scaled and translated Ease out

0.2 0.4 0.6 0.8 1 0.2 0.4 0.6 0.8 1 Fractional Value Change Normalized Time

Ease-in + Ease-out

Linear Quadratic Qubic Quartic Quintic

EaseInOutRace.pde

slide-6
SLIDE 6

Many other types of easing functions

– Sinusoidal Easing – Exponential Easing – Circular Easing – Oscillatory Easing (passes target and returns)

slide-7
SLIDE 7

http://www.robertpenner.com/easing/easing_demo.html

Robert Penner's Easing Website

– Sample chapter on easing

slide-8
SLIDE 8

Implementing Easing in Processing

  • 1. Develop Bullseye class and draw

// BullsEye class BullsEye { float X; float Y; BullsEye(float _X, float _Y) { X = _X; Y = _Y; } // Draw BullsEye void draw() { pushMatrix(); translate(X, Y); scale(0.5,0.5); stroke(0); ellipseMode(CENTER); fill(0); ellipse(0,0,105,105); fill(255,0,0); ellipse(0,0,100,100); fill(255); ellipse(0,0,80,80); fill(255,0,0); ellipse(0,0,60,60); fill(255); ellipse(0,0,40,40); fill(0); noStroke(); ellipse(0,0,20,20); popMatrix(); } }

Easing1.pde

slide-9
SLIDE 9

// Easing1 BullsEye be; void setup() { size(500, 500); smooth(); be = new BullsEye(250, 250); } void draw() { background(255); be.draw(); } void mousePressed() { be.X = mouseX; be.Y = mouseY; }

Easing1.pde

slide-10
SLIDE 10

Implementing Easing in Processing

  • 2. Build Linear Easing into BullsEye

// BullsEye class BullsEye { float X; float Y; // Parameters for easing float startV; float deltaV; float nSteps; float currentStep = 0.0; boolean easing = false; BullsEye(float _X, float _Y) { X = _X; Y = _Y; } // Incrememt location float next() { float nextV; // Increment ease step currentStep++; // Only ease within step range if (currentStep > nSteps) { currentStep = nSteps; nextV = startV + deltaV; easing = false; currentStep = 0; } else { float fracT = currentStep/nSteps; nextV = startV + deltaV * fracT; } return nextV; }

Easing2.pde

slide-11
SLIDE 11

Implementing Easing in Processing

  • 2. Build Linear Easing into BullsEye (2)

// Easing2 BullsEye be; void setup() { size(500, 500); smooth(); be = new BullsEye(250, 250); } void draw() { background(255); if (be.easing) be.X = be.next(); be.draw(); } void mousePressed() { be.startV = be.X; be.deltaV = mouseX-be.X; be.nSteps = 50; be.easing = true; }

Easing2.pde

slide-12
SLIDE 12

Implementing Easing in Processing

  • 3. Extract easing behavior into an Ease class

// Class encapsulating easing behavior class Ease { float startV; float deltaV; float nSteps; float currentStep = 0.0; Ease(float _startV, float _endV, float _nSteps) { startV = _startV; deltaV = _endV - _startV; nSteps = _nSteps; } float calcEase(float fracT) { return fracT; } // Incrememt location float next() { float nextV; // Increment ease step currentStep++; // Only ease within step range if (currentStep > nSteps) { currentStep = nSteps; nextV = startV + deltaV; } else { float fracT = currentStep/nSteps; nextV = startV + deltaV*calcEase(fracT); } return nextV; }

Easing3.pde

slide-13
SLIDE 13

// BullsEye class BullsEye { float X; float Y; // Position easing objects Ease easeX = null; Ease easeY = null; BullsEye(float _X, float _Y) { X = _X; Y = _Y; } // Increment Easing, // if an Ease object is specified void next() { if (easeX != null) X = easeX.next(); if (easeY != null) Y = easeY.next(); } …

Implementing Easing in Processing

  • 3. Extract easing behavior into an Ease class (2)

// Easing3 BullsEye be; void setup() { size(500, 500); smooth(); be = new BullsEye(250, 250); } void draw() { background(255); be.next(); be.draw(); } void mousePressed() { // Set easing in on mouse pressed be.easeX = new Ease(be.X, mouseX, 50); be.easeY = new Ease(be.Y, mouseY, 50); }

Now, both X and Y (or any field) can be eased

Easing3.pde

slide-14
SLIDE 14

Implementing Easing in Processing

  • 4. Create new kinds of Easing classes

Easing4.pde

// Class encapsulating quadratic easing class QuadEaseIn { float startV; float deltaV; float nSteps; float currentStep = 0.0; QuadEaseIn(float _startV, float _endV, float _nSteps) { startV = _startV; deltaV = _endV - _startV; nSteps = _nSteps; } float calcEase(float fracT) { return pow(fracT, 2); } // Incrememt location float next() { float nextV; // Increment ease step currentStep++; // Only ease within step range if (currentStep > nSteps) { currentStep = nSteps; nextV = startV + deltaV; } else { float fracT = currentStep/nSteps; nextV = startV + deltaV*calcEase(fracT); } return nextV; }

The only difference between Ease and QuadEaseIn is the name and part of the easing function

slide-15
SLIDE 15

Implementing Easing in Processing

  • 4. Create new kinds of Easing classes (2)

Easing4.pde

// BullsEye class BullsEye { float X; float Y; // Position easing objects QuadEaseIn easeX = null; QuadEaseIn easeY = null; BullsEye(float _X, float _Y) { X = _X; Y = _Y; } // Increment Easing, // if an Ease object is specified void next() { if (easeX != null) X = easeX.next(); if (easeY != null) Y = easeY.next(); } … // Easing3 BullsEye be; void setup() { size(500, 500); smooth(); be = new BullsEye(250, 250); } void draw() { background(255); be.next(); be.draw(); } void mousePressed() { // Set easing in on mouse pressed be.easeX = new QuadEaseIn(be.X, mouseX, 50); be.easeY = new QuadEaseIn(be.Y, mouseY, 50); }

slide-16
SLIDE 16
  • In fact, if we want to change the easing

behavior of the BullsEye class, we have to edit its source code every time!

  • There has to be a better way …

… Hold that thought …

slide-17
SLIDE 17

Object Oriented Programming

– Encapsulation

  • Classes encapsulate state (fields) and behavior (methods)

– Polymorphism

  • Signature Polymorphism – Overloading
  • Subtype Polymorphism – Inheritance
slide-18
SLIDE 18

Creating a set of Graphic Object Classes

  • All have…
  • X, Y location
  • width and height fields
  • fill and stroke colors
  • A draw() method
  • A next() method defining how they move
  • Implementation varies from class to class
slide-19
SLIDE 19

Creating a set of Graphic Object Classes

  • Problems

How would you hold all your objects? – Array? – ArrayList or HashMap? What if one class had extra methods or special arguments?

Sometimes you want to think of an object as a generic Graphic (X,Y location and draw() method) Sometimes you want to think of an object as a specific type (extra methods, extra fields, …)

slide-20
SLIDE 20

Graphic Ellipse Rectangle Arc Curve Shape Circle Square

More General More Specific

Graphic Object Hierarchy

X,Y fields draw() method … diameter

Inheritance gives you a way to relate your objects in a hierarchical manner

slide-21
SLIDE 21

Inheritance

  • Superclass (base class) – higher in the hierarchy
  • Subclass (child class) – lower in the hierarchy
  • A subclass is derived from from a superclass
  • Subclasses inherit the fields and methods of their

superclass.

– I.e. subclasses automatically "get" stuff in superclasses

  • Subclasses can override a superclass method by

redefining it.

– They can replace anything by redefining locally

slide-22
SLIDE 22

// Ellipse base class class Ellipse { float X; float Y; float W; float H; // Ellipses are always red color fillColor = color(255,0,0); Ellipse(float X, float Y, float W, float H) { this.X = X; this.Y = Y; this.W = W; this.H = H; } void draw() { ellipseMode(CENTER); fill(fillColor); ellipse(X, Y, W, H); } } // Circle derived class class Circle extends Ellipse { Circle(float X, float Y, float D) { super(X, Y, D, D); // Circles are always blue fillColor = color(0,255,0); } }

  • The extends keyword creates

hierarchical relationship between classes.

  • The Circle class gets all fields and

methods of the Ellipse class, automatically.

  • The super keyword refers to the base

class in the relationship.

  • The this keyword refers to the object

itself.

Graphics.pde

slide-23
SLIDE 23

Graphics.pde

// Graphics Ellipse e = new Ellipse(150, 250, 150, 50); Circle c = new Circle(350, 250, 75); void setup() { size(500, 500); smooth(); } void draw() { e.draw(); c.draw(); }

slide-24
SLIDE 24

// Graphics2 Ellipse[] e = new Ellipse[20]; void setup() { size(500, 500); smooth(); for (int i=0; i<e.length; i++) { float X = random(0, width); float Y = random(0, height); float W = random(10, 100); float H = random(10, 100); // Ellipses are Circles are // stored in the same array if (random(1.0) < 0.5) e[i] = new Ellipse(X,Y,W,H); else e[i] = new Circle(X,Y,W); } } void draw() { for (int i=0; i<e.length; i++) e[i].draw(); }

Ellipses and Circles in the same array!

Graphics2.pde

slide-25
SLIDE 25

Graphics3.pde

// Ellipse base class class Ellipse { float X; float Y; float W; float H; // Ellipses are always red color fillColor = color(255,0,0); Ellipse(float X, float Y, float W, float H) { this.X = X; this.Y = Y; this.W = W; this.H = H; } void draw() { ellipseMode(CENTER); fill(fillColor); ellipse(X, Y, W, H); } // Do nothing void mousePressed() {} } // Circle derived class class Circle extends Ellipse { Circle(float X, float Y, float D) { super(X, Y, D, D); // Circles are always blue fillColor = color(0,255,0); } // Change color of circle when clicked void mousePressed() { if (dist(mouseX, mouseY, X, Y) < 0.5*W) fillColor = color(0,0,255); } }

  • The mousePressed behavior of the

Circle class overrides the default behavior of the Ellipse class.

slide-26
SLIDE 26

Graphics3.pde

// Graphics3 Ellipse[] e = new Ellipse[20]; void setup() { size(500, 500); smooth(); // Stuff removed … } void draw() { for (int i=0; i<e.length; i++) e[i].draw(); } void mousePressed() { for (int i=0; i<e.length; i++) e[i].mousePressed(); }

slide-27
SLIDE 27

A few more rules about inheritance …

  • A child’s constructor is responsible for calling

the parent’s constructor

  • The first line of a child’s constructor should use

the super reference to call the parent’s constructor

  • The super reference can also be used to

reference other variables and methods defined in the parent’s class

slide-28
SLIDE 28

Use inheritance to solve our Ease class problem

– The BullsEye class should declare easeX and easeY as variables of type Ease. – New kinds of Ease classes can be defined as subclasses of Ease – Only the calcEase() function must be overridden.

Ease PolyEaseIn LinearEase PolyEaseOut PolyEaseInOut … Easing.pde

slide-29
SLIDE 29

// Class encapsulating polynomial ease-in behavior class PolyEaseIn extends Ease { PolyEaseIn(float _startV, float _endV, float _nSteps, float _param) { super(_startV, _endV, _nSteps, _param); } float calcEase(float fracT) { return pow(fracT, param); } } // Class encapsulating polynomial ease-out behavior class PolyEaseOut extends Ease{ PolyEaseOut(float _startV, float _endV, float _nSteps, float _param) { super(_startV, _endV, _nSteps, _param); } float calcEase(float fracT) { return 1.0-pow(1.0-fracT, param); } } // Class encapsulating polynomial ease-in and ease-out behavior class PolyEaseInOut extends Ease { PolyEaseInOut(float _startV, float _endV, float _nSteps, float _param) { super(_startV, _endV, _nSteps, _param); } float calcEase(float fracT) { if (fracT < 0.5) return 0.5*pow(2.0*fracT, param); else return 0.5+0.5*(1.0-pow(1.0-(2.0*(fracT-0.5)), param)); } }

slide-30
SLIDE 30

// BullsEye class BullsEye { float X; float Y; // Position easing objects Ease easeX = null; Ease easeY = null; BullsEye(float X, float Y) { this.X = X; this.Y = Y; } // Increment Easing void next() { if (easeX != null) X = easeX.next(); if (easeY != null) Y = easeY.next(); }

The BullsEye class can declare its easing objects using the more general type Ease…

slide-31
SLIDE 31

// Easing BullsEye be; void setup() { size(500, 500); smooth(); be = new BullsEye(250, 250); } void draw() { background(255); be.next(); be.draw(); } void mousePressed() { // Set easing in on mouse pressed be.easeX = new LinearEase(be.X, mouseX, 50); be.easeY = new LinearEase(be.Y, mouseY, 50); // be.easeX = new PolyEaseInOut(be.X, mouseX, 50, 2); // be.easeY = new PolyEaseInOut(be.Y, mouseY, 50, 2); }

… but they can be assigned using

  • ne of several more specific types
  • f Ease.