• 검색 결과가 없습니다.
N/A
N/A
Protected

Academic year: 2022

Share "[email protected] PBox2D"

Copied!
94
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

PBox2D

This presentation is based on the underline ppt file

http://pds21.egloos.com/pds/201304/09/15/Class4-PhysicalLibrary.pptx

2013.5.16

[email protected]

(2)
(3)

3

(4)
(5)

5

(6)
(7)

http://en.wikipedia.org/wiki/Box2D 7

(8)
(9)

https://code.google.com/p/box2d/ 9

(10)
(11)

Box2D Testbed

11

(12)
(13)

https://code.google.com/p/box2dweb/ 13

(14)
(15)

iforce2d advanced topics

http://www.iforce2d.net/b2dtut/ 15

(16)
(17)

http://paralaxer.com/box2d-physics/ 17

(18)
(19)

http://www.jangaroo.net/files/examples/flash/box2d/ 19

(20)
(21)

http://www.mrdoob.com/projects/chromeexperiments/google-gravity/ 21

(22)
(23)

http://natureofcode.com/book/chapter-5-physics-libraries/ 23

(24)

What is the Box2D?

 Open-Source 2D Physics Engine

 C++ by Erin Catto for the Game Developer’s Conference in 2006.

 Box2D site (http://www.box2d.org/) for reference

 Crayon Physics

 Angry Birds

 JBox2D : Java Wrapper

 Box2D site (http://www.jbox2d.org//) for reference.

 Can be directly used in Processing

 PBox2D : Processing Wrapper

 Make it easy to use JBox2D

 A layer library between JBox2D and Processing

 a Processing Box2D “helper” library

 PBox2D is not a Processing wrapper for all of Box2D

 https://github.com/shiffman/PBox2D

(25)

Box2D Basics

 In old physical simulation

 SETUP:

Create all the objects in our world.

 DRAW:

Calculate all the forces in our world.

Apply all the forces to our objects (F = M * A).

Update the locations of all the objects based on their acceleration.

Draw all of our objects.

 In Box2D

 SETUP:

Create all the objects in our world.

 DRAW:

Draw all of our objects.

25

(26)

Five core parts for using Box2D

1. World : Manages the physics simulation. It knows everything about the overall coordinate space and also stores lists of every element in the world

2. Body : Serves as the primary element in the Box2D world. It has a location. It has a velocity. Sound familiar? The Body is essentially the class we’ve been writing on our own in our vectors and forces examples.

3. Shape : Keeps track of all the necessary collision geometry attached to a body.

4. Fixture : Attaches a shape to a body and sets properties such as density, friction, and restitution.

5. Joint : Acts as a connection between two bodies (or between one body

and the world itself).

(27)

A new Vector Class : Vec2

27

PVector Vec2

PVector a = new PVector(1,-1);

PVector b = new PVector(3,4);

a.add(b);

Vec2 a = new Vec2(1,-1);

Vec2 b = new Vec2(3,4);

a.addLocal(b);

PVector a = new PVector(1,-1);

PVector b = new PVector(3,4);

PVector c = PVector.add(a,b);

Vec2 a = new Vec2(1,-1);

Vec2 b = new Vec2(3,4);

Vec2 c = a.add(b);

PVector a = new PVector(1,-1);

float n = 5;

a.mult(n);

Vec2 a = new Vec2(1,-1);

float n = 5;

a.mulLocal(n);

PVector a = new PVector(1,-1);

float n = 5;

PVector c = PVector.mult(a,n);

Vec2 a = new Vec2(1,-1);

float n = 5;

Vec2 c = a.mul(n);

PVector a = new PVector(1,-1);

float m = a.mag();

a.normalize();

Vec2 a = new Vec2(1,-1);

float m = a.length();

a.normalize();

(28)

Box2D worlds

How can we convert between them?

(29)

Helper functions

29

Task Function

Convert location from World to Pixels Vec2 coordWorldToPixels(Vec2 world)

Convert location from World to Pixels Vec2 coordWorldToPixels(float worldX, float worldY) Convert location from Pixels to World Vec2 coordPixelsToWorld(Vec2 screen)

Convert location from Pixels to World Vec2 coordPixelsToWorld(float pixelX, float pixelY) Scale a dimension (such as height, width, or radius) from

Pixels to World

float scalarPixelsToWorld(float val)

Scale a dimension from World to Pixels float scalarWorldToPixels(float val)

(30)

Set up the world

PBox2D box2d;

void setup() {

box2d = new PBox2D(this);

//Initializes a Box2D world with default settings box2d.createWorld();

}

(31)

Set up the Body

 Step 1: Define a body.

31

//define the properties of the body we intend to make BodyDef bd = new BodyDef();

Vec2 center = box2d.coordPixelsToWorld(width/2,height/2));

bd.position.set(center);

bd.fixedRotation = true; //Fixed, never rotating objects bd.linearDamping = 0.8; //Friction

bd.angularDamping = 0.9;

bd.bullet = true; //if it is FAST moving objects bd.type = BodyType.DYNAMIC; // body type

 Step 2: Configure the body definition.

(32)

Damping

A Damping node can be used to slow down a body (a Solid node with Physics). The speed of each body is reduced by the specified amount (between 0.0 and 1.0) every second. A value of 0.0 means

"no slowing down" and value of 1.0 means a

"complete stop", a value of 0.1 means that the speed should be decreased by 10 percent every second. A damped body will possibly come to rest and become disabled depending on the values specified in WorldInfo. Damping does not add any force in the simulation, it directly affects the

velocity of the body. The damping effect is applied after all forces have been applied to the bodies.

Damping can be used to reduce simulation

instability.

(33)

Body types

 Dynamic (BodyType.DYNAMIC)

a “fully simulated” body. A dynamic body moves around the

world, collides with other bodies, and responds to the forces in its environment.

 Static (BodyType.STATIC)

cannot move (as if it had an infinite mass). We’ll use static bodies for fixed platforms and boundaries.

 Kinematic(BodyType.KINEMATIC)

can be moved manually by setting its velocity directly. If you have a user-controlled object in your world, you can use a kinematic body. Note that kinematic bodies collide only with dynamic

bodies and not with other static or kinematic ones.

33

(34)

Body body = box2d.createBody(bd);

 Step 3: Create the body.

Set up the Body

 Step 4: Set any other conditions for the body’s starting state.

body.setLinearVelocity(new Vec2(0,3));

body.setAngularVelocity(1.2);

(35)

Linking Shape with Body

 Body does not have geometry

 We have to attach geometry shape to body with a Fixture

 We can attach multiple shapes to a single body in order to create more complex forms.

 Step 1: Define a shape

35

PolygonShape ps = new PolygonShape();

float box2Dw = box2d.scalarPixelsToWorld(150);

float box2Dh = box2d.scalarPixelsToWorld(100);

ps.setAsBox(box2Dw, box2Dh);

(36)

Width & Height

width height

height

width

Processing BOX2D

(37)

 Step 2: Create a fixture.

FixtureDef fd = new FixtureDef();

//The fixture is assigned the PolygonShape we just made.

fd.shape = ps;

fd.friction = 0.3; //The coefficient of friction for the shape, typically between 0 and 1

fd.restitution = 0.5; //The Shape’s restitution (i.e. elasticity), typically between 0 and 1

fd.density = 1.0; //The Shape’s density, measured in kilograms per meter squared

 Step 3: Attach the shape to the body with the fixture.

body.createFixture(fd);

Or you can use the default fixture

body.createFixture(ps,1); // Creates the Fixture and attaches the Shape with a density of 1

37

(38)

Friction

(39)

Restitution(Elasticity)

39

(40)

Density

(41)

In summary

1. Define a body using a BodyDef object (set any properties, such as location).

2. Create the Body object from the body definition.

3. Define a Shape object using PolygonShape, CircleShape, or any other shape class.

4. Define a fixture using FixtureDef and assign the fixture a shape (set any properties, such as friction, density, and restitution).

5. Attach the shape to the body.

41

(42)

Shapes

 Circle Shapes

 Polygon Shapes

b2CircleShape circle;

circle.m_p.Set(2.0f, 3.0f);

circle.m_radius = 0.5f;

// This defines a triangle in CCW order.

b2Vec2 vertices[3];

vertices[0].Set(0.0f, 0.0f);

vertices[1].Set(1.0f, 0.0f);

vertices[2].Set(0.0f, 1.0f);

int32 count = 3;

b2PolygonShape polygon;

polygon.Set(vertices, count);

(43)

Shapes

 Edge Shapes

43

// This an edge shape with ghost vertices.

b2Vec2 v0(1.7f, 0.0f);

b2Vec2 v1(1.0f, 0.25f);

b2Vec2 v2(0.0f, 0.0f);

b2Vec2 v3(-1.7f, 0.4f);

b2EdgeShape edge;

edge.Set(v1, v2);

edge.m_hasVertex0 = true;

edge.m_hasVertex3 = true;

edge.m_vertex0 = v0;

edge.m_vertex3 = v3;

(44)

Shapes

 Chain Shapes

// This a chain shape with isolated vertices b2Vec2 vs[4];

vs[0].Set(1.7f, 0.0f);

vs[1].Set(1.0f, 0.25f);

vs[2].Set(0.0f, 0.0f);

vs[3].(-1.7f, 0.4f);

b2ChainShape chain;

chain.CreateChain(vs, 4);

(45)

In processing term.

45 //Step 1. Define the body.

BodyDef bd = new BodyDef();

bd.position.set(box2d.coordPixelsToWorld(width/2,height/2));

//Step 2. Create the body.

Body body = box2d.createBody(bd);

//Step 3. Define the shape.

PolygonShape ps = new PolygonShape();

float w = box2d.scalarPixelsToWorld(150);

float h = box2d.scalarPixelsToWorld(100);

ps.setAsBox(w, h)

//Step 4. Define the fixture.

FixtureDef fd = new FixtureDef();

fd.shape = ps;

fd.density = 1;

fd.friction = 0.3;

fd.restitution = 0.5;

//Step 5. Attach the shape to the body with the Fixture.

body.createFixture(fd);

(46)

How can we keep tracking objects?

 Use the arrayList (Dynamic array)

 Exercise

Making boxes on the fly whenever we move the box and put it on an arrayList.

(47)

// A list for all of our rectangles ArrayList<Box> boxes;

void setup() { size(800,200);

smooth();

// Create ArrayLists

boxes = new ArrayList<Box>();

}

void draw() { background(255);

// When the mouse is clicked, add a new Box object if (mousePressed) {

Box p = new Box(mouseX,mouseY);

boxes.add(p);

}

// Display all the boxes for (Box b: boxes) { b.display();

} }

// A rectangular box class Box {

float x,y;

float w,h;

// Constructor

Box(float x_, float y_) { x = x_;

y = y_;

w = 16;

h = 16;

}

// Drawing the box void display() { fill(127);

stroke(0);

strokeWeight(2);

rectMode(CENTER);

rect(x,y,w,h);

} }

Class Design

47

(48)

Let’s put those boxes on the Box2D world

 Revise the Box class

 Box size (8,8)

 fd.density = 1;

 fd.friction = 0.3;

 fd.restitution = 0.5;

class Box { Body body;

float w,h;

Box(float x, float y) { //initial position w = 16;

h = 16;

}

display() {

Vec2 pos = box2d.getBodyPixelCoord(body);

float a = body.getAngle();

pushMatrix();

translate(pos.x,pos.y);

// Box2D coordinate system considers rotation in the opposite direction from Processing rotate(-a);

fill(127);

stroke(0);

strokeWeight(2);

rectMode(CENTER);

rect(0,0,w,h);

popMatrix();

} } // following the steps

// Step 1. Define the body.

// Step 2. Create the body.(bodyType=DYNAMIC) // Step 3. Define the shape.

// Step 4. Define the fixture.

// Step 5. Attach the shape to the body with the Fixture

(49)

Main function

49

import pbox2d.*;

import org.jbox2d.collision.shapes.*;

import org.jbox2d.common.*;

import org.jbox2d.dynamics.*;

// A list for all of our rectangles ArrayList<Box> boxes;

PBox2D box2d;

void setup() { size(800, 200);

smooth();

// Initialize and create the Box2D world box2d = new PBox2D(this);

box2d.createWorld();

// Create ArrayLists

boxes = new ArrayList<Box>();

}

void draw() { background(255);

// We must always step through time!

box2d.step();

// When the mouse is clicked, add a new Box object Box p = new Box(mouseX, mouseY);

boxes.add(p);

// Display all the boxes for (Box b: boxes) { b.display();

} }

(50)

Let’s put some boundaries.

 To create boundaries,

we need to set BodyDef object’s type to STATIC.

(51)

class Boundary {

// A boundary is a simple rectangle with x,y,width,and height float x;

float y;

float w;

float h;

// But we also have to make a body for box2d to know about it Body b;

Boundary(float x_,float y_, float w_, float h_) { x = x_;

y = y_;

w = w_;

h = h_;

}

// Draw the boundary, if it were at an angle we'd have to do something fancier void display() {

fill(0);

stroke(0);

rectMode(CENTER);

rect(x,y,w,h);

} }

Let’s design Boundary class

// following the steps // Step 1. Define the body.

// Step 2. Create the body.(bodyType=DYNAMIC) // Step 3. Define the shape.

// Step 4. Define the fixture.

// Step 5. Attach the shape to the body with the Fixture

51

(52)

// A reference to our box2d world PBox2D box2d;

// A list we'll use to track fixed objects ArrayList<Boundary> boundaries;

// A list for all of our rectangles ArrayList<Box> boxes;

void setup() { size(800, 200);

smooth();

// Initialize and create the Box2D world box2d = new PBox2D(this);

box2d.createWorld();

// Create ArrayLists

boxes = new ArrayList<Box>();

boundaries = new ArrayList<Boundary>();

// Add a bunch of fixed boundaries

boundaries.add(new Boundary(width/4,height-5,width/2-50,10));

boundaries.add(new Boundary(3*width/4,height-50,width/2-50,10));

}

Let’s design main function

(53)

One problem of this example

 Computationally expensive as we increase the number of boxes

 It is getting slow as it goes.

 How can we fix it?

If the box is out of screen, remove it!!

53

(54)

void killBody() {

box2d.destroyBody(body);

//ask box2d to destroy the body }

// Is the particle ready for deletion?

boolean done() {

// Let's find the screen position of the particle Vec2 pos = box2d.getBodyPixelCoord(body);

// Is it off the bottom of the screen?

if (pos.y > height+h) { killBody();

return true;

}

return false;

}

Let’s modify Box class and main function

for (int i = boxes.size()-1; i >= 0; i--) { Box b = boxes.get(i);

if (b.done()) {

boxes.remove(i); //remove from the array }

}

BOX class Draw() in main function

(55)

Curvy Boundary

 If you want a fixed boundary that is a curved surface (as opposed to a polygon)

 Use the ChainShape

55

(56)

polygonShape : Convex moving object

chainShape : static game world

(57)

Steps

 Step 1: Define a body.

57

BodyDef bd = new BodyDef();

Body body = box2d.world.createBody(bd);

 Step 2: Define the Shape.

ChainShape chain = new ChainShape();

 Step 3: Configure the Shape.

Vec2[] vertices = new Vec2[2];

vertices[0] = box2d.coordPixelsToWorld(0,150);

vertices[1] = box2d.coordPixelsToWorld(width,150);

chain.createChain(vertices, vertices.length);

(58)

Steps

 Step 4: Attach the Shape to the body with a Fixture.

FixtureDef fd = new FixtureDef();

fd.shape = chain;

fd.density = 1;

fd.friction = 0.3;

fd.restitution = 0.5;

body.createFixture(fd);

(59)

Define a Surface

59

class Surface {

// We'll keep track of all of the surface points ArrayList<Vec2> surface;

Surface() {

surface = new ArrayList<Vec2>();

// Here we keep track of the screen coordinates of the chain surface.add(new Vec2(0, height/2));

//surface.add(new Vec2(width/2, height/2+50));

surface.add(new Vec2(width, height/2));

// This is what box2d uses to put the surface in its world ChainShape chain = new ChainShape();

// We can add 3 vertices by making an array of 3 Vec2 objects Vec2[] vertices = new Vec2[surface.size()];

for (int i = 0; i < vertices.length; i++) {

vertices[i] = box2d.coordPixelsToWorld(surface.get(i));

}

chain.createChain(vertices, vertices.length);

// The edge chain is now a body!

BodyDef bd = new BodyDef();

Body body = box2d.world.createBody(bd);

// Shortcut, we could define a fixture if we // want to specify frictions, restitution, etc.

body.createFixture(chain, 1);

}

(60)

How to draw it?

void display() { strokeWeight(1);

stroke(0);

fill(0);

beginShape();

for (int i=0; i<surface.size(); i++) { Vec2 v = surface.get(i);

vertex(v.x,v.y);

}

vertex(width, height);

vertex(0, height);

endShape(CLOSE);

}

(0,height) (width,height)

vertex(v.x,v.y);

(61)

Exercise

 Use the sin() to draw the mountains

 Use the mouse to create circles

 Use the CircleShape cs = new CircleShape() for body

61

(62)

Body type and parameters

float r = random(4,8);

CircleShape cs = new CircleShape();

cs.m_radius = box2d.scalarPixelsToWorld(r);

FixtureDef fd = new FixtureDef();

fd.shape = cs;

fd.density = 1;

fd.friction = 0.01;

fd.restitution = 0.3;

. . .

body.setLinearVelocity(new Vec2(random(-10f,10f),random(5f,10f)));

(63)

Building Mountain:use the sin function

float angle = 0;

float angleVel = 0.2;

float amplitude = 100;

size(400,200);

background(255);

smooth();

stroke(0);

strokeWeight(2);

noFill();

beginShape();

for (int x = 0; x <= width; x += 5) {

//map one value from the current range to another range float y = map(sin(angle),-1,1,0,height);

vertex(x,y);

angle +=angleVel;

}

endShape();

63

(64)

Complex Shapes

 How to create more complex shapes?

 build a completely custom shape as a series of connected vertices

(65)

Vec2[] vertices = new Vec2[4];

// An array of 4 vectors

vertices[0] = box2d.vectorPixelsToWorld(new Vec2(-15, 25));

vertices[1] = box2d.vectorPixelsToWorld(new Vec2(15, 0));

vertices[2] = box2d.vectorPixelsToWorld(new Vec2(20, -15));

vertices[3] = box2d.vectorPixelsToWorld(new Vec2(-10, -10));

PolygonShape ps = new PolygonShape();

ps.set(vertices, vertices.length);

1. Order of vertices! If you are thinking in terms of pixels (as above) the vertices should be defined in counterclockwise order.

2. Convex shapes only! A concave shape is one where the surface curves inward. Convex is the opposite

65

(66)

Complex shapes

 We can attach several shapes on a single body

BodyDef bd = new BodyDef();

bd.type = BodyType.DYNAMIC;

bd.position.set(box2d.coordPixelsToWorld(center));

body = box2d.createBody(bd);

PolygonShape ps = new PolygonShape();

float box2dW = box2d.scalarPixelsToWorld(w/2);

float box2dH = box2d.scalarPixelsToWorld(h/2);

sd.setAsBox(box2dW, box2dH);

CircleShape cs = new CircleShape();

cs.m_radius = box2d.scalarPixelsToWorld(r);

body.createFixture(ps,1.0);

body.createFixture(cs, 1.0);

Body center

(67)

Moving

67

Vec2 offset = new Vec2(0,-h/2);

//Converting the vector to Box2D world offset = box2d.vectorPixelsToWorld(offset);

//Setting the local position of the circle circle.m_p.set(offset.x,offset.y);

m_p : local center of shape

(68)

Setting shapes on body

 Setting proper shapes on the body is really important for correct simulation.

 If not, the collision detection does not work and simulation has errors.

Overlapping each other !!

(69)

Exercise : Revise the old example

69

void display() {

Vec2 pos = box2d.getBodyPixelCoord(body);

float a = body.getAngle();

rectMode(CENTER);

pushMatrix();

translate(pos.x,pos.y);

rotate(-a);

fill(175);

stroke(0);

//First the rectangle at (0,0) rect(0,0,w,h);

//Then the ellipse offset at (0,-h/2) ellipse(0,-h/2,r*2,r*2);

popMatrix();

}

(70)

Box2D Joints

 Connecting one body to another

 Three different joints

 distance joints

 revolute joints

 mouse joints

(71)

Distant Joints

 A joint that connects two bodies with a fixed length

 Steps

Step 1. Make sure you have two bodies ready to go.

Step 2. Define the joint.

Step 3. Configure the joint’s properties (What are the bodies? Where are the anchors? What is its rest length? Is it elastic or rigid?)

Step 4. Create the joint.

71

(72)

Example

 Assume that we have a particle body

Particle p1 = new Particle();

Particle p2 = new Particle();

DistanceJointDef djd = new DistanceJointDef();

djd.bodyA = p1.body;

djd.bodyB = p2.body;

//if our rest length is in pixels, we need to convert it!

djd.length = box2d.scalarPixelsToWorld(10);

Joint dj = (DistanceJoint) box2d.world.createJoint(djd);

(73)

Revolute Joints

 connects two Box2D bodies at a common anchor point,

 Steps

Step 1. Make sure you have two bodies ready to go.

Step 2. Define the joint.

Step 3. Configure the joint’s properties (What are the bodies?)

Step 4. Create the joint.

73

(74)

Example

 Assume that we have a particle body

Box box1 = new Box();

Box box2 = new Box();

RevoluteJointDef rjd = new RevoluteJointDef();

//the anchor point (i.e. where they are connected)is set with the function initialize().

rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());

rjd.motorSpeed = PI*2; // how fast?

rjd.maxMotorTorque = 1000.0; // how powerful?

rjd.enableMotor = false; // is it on?

rjd.enableLimit = true;

rjd.lowerAngle = -PI/8;

rjd.upperAngle = PI/8;

Joint joint = box2d.world.createJoint(rjd);

(75)

Exercise: Let’s making a windmill

75

class Windmill { RevoluteJoint joint;

Box box1;

Box box2;

Windmill(float x, float y) {

// Initialize locations of two boxes

box1 = new Box(x, y-20, 120, 10, false);

box2 = new Box(x, y, 10, 40, true);

// Define joint as between two bodies

RevoluteJointDef rjd = new RevoluteJointDef();

rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());

// Turning on a motor (optional)

rjd.motorSpeed = PI*2; // how fast?

rjd.maxMotorTorque = 1000.0;

// how powerful?

rjd.enableMotor = false; // is it on?

// Create the joint rjd.enableLimit = true;

rjd.lowerAngle = -PI/8;

rjd.upperAngle = PI/8;

}

void display() { box2.display();

box1.display();

// Draw anchor just for debug

Vec2 anchor = box2d.coordWorldToPixels(box1.body.getWorldCenter());

fill(0);

noStroke();

ellipse(anchor.x, anchor.y, 8, 8);

} }

Create a ball whenever you click the mouse!

(76)

import pbox2d.*;

import org.jbox2d.common.*;

import org.jbox2d.dynamics.joints.*;

import org.jbox2d.collision.shapes.*;

import org.jbox2d.collision.shapes.Shape;

import org.jbox2d.common.*;

import org.jbox2d.dynamics.*;

import org.jbox2d.dynamics.contacts.*;

// A reference to our box2d world PBox2D box2d;

// An object to describe a Windmill (two bodies and one joint) Windmill windmill;

// An ArrayList of particles that will fall on the surface ArrayList<Particle> particles;

void setup() { size(800,200);

smooth();

// Initialize box2d physics and create the world box2d = new PBox2D(this);

box2d.createWorld();

// Make the windmill at an x,y location windmill = new Windmill(width/2,175);

// Create the empty list

particles = new ArrayList<Particle>();

}

void mousePressed() {

float sz = random(4,8); //radius

particles.add(new Particle(mouseX,mouseY,sz));

}

// Create a particle class!!

Class Particle {

//following the steps for creating body and shape }

Exercise: main function

(77)

77

Joints

 Prismatic Joint

 Pulley Joint

 Gear Joint

 Mouse Joint

 Wheel Joint

 Weld Joint

 Rope Joint

 Friction Joint

(78)

Applying Forces

 When we want to apply any forces other than gravity, call applyForce() function

class Box { Body body;

void applyForce(Vec2 force) {

Vec2 pos = body.getWorldCenter();

//Calling the Body's applyForce() function body.applyForce(force, pos);

} }

Our earlier forces examples assumed that the force was always applied at

the mover’s center. Here we get to specify exactly where on the body the

force is applied

(79)

Collision Detection

 How do we know when two objects collide?

beginContact() is triggered when two shapes collide

79 void setup() {

box2d = new PBox2D(this);

box2d.createWorld();

Add this line if you want to listen for collisions.

box2d.listenForCollisions();

}

void beginContact(Contact cp) {

println("Something collided in the Box2D World!");

}

(80)

Collision Call-back functions

1. beginContact() —Triggered whenever two shapes first come into contact with each other.

2. endContact() —Triggered over and over again as long as shapes continue to be in contact.

3. preSolve() —Triggered before Box2D solves the outcome of the collision, i.e. before beginContact(). It can be used to disable a collision if necessary.

4. postSolve() —Triggered after the outcome of the collision is solved. It allows you to gather information about that “solution”

(known as an “impulse”).

endContact() works identically to beginContact(),

the only difference being that it occurs the moment bodies separate.

(81)

Set-up steps : Given a particle class

 Step 1: Contact, could you tell me what two things collided?

Box2D detects collisions between shapes, but shapes are attached by fixtures. So, we need to find two fixtures collided

81

Fixture f1 = cp.getFixtureA();

Fixture f2 = cp.getFixtureB();

 Step 2: Fixtures, could you tell me which body you are attached to?

Body b1 = f1.getBody();

Body b2 = f2.getBody();

(82)

Set-up steps : Given a particle class

 Step 3: Bodies, could you tell me which Particles you are associated with?

How can the body know about the particle class?

Box2D provides a function that allows us to attach our Processingobject (a Particle) to a Box2D body via the setUserData() and getUserData() methods.

class Particle { Body body;

Particle(float x, float y, float r) { BodyDef bd = new BodyDef();

bd.position = box2d.coordPixelsToWorld(x, y);

bd.type = BodyType.DYNAMIC;

body = box2d.createBody(bd);

CircleShape cs = new CircleShape();

cs.m_radius = box2d.scalarPixelsToWorld(r);

body.createFixture(fd,1);

body.setUserData(this);

}

(83)

beginContact() call-back function

83 void beginContact(Contact cp) {

Fixture f1 = cp.getFixtureA();

Fixture f2 = cp.getFixtureB();

Body b1 = f1.getBody();

Body b2 = f2.getBody();

// When we pull the “user data” object out of the Body object, we have to remind our program // that it is a Particle object. Box2D doesn’t know this.

Particle p1 = (Particle) b1.getUserData();

Particle p2 = (Particle) b2.getUserData();

//Once we have the particles, we can do anything to them. Here we just call a function that // changes their color.

p1.change();

p2.change();

}

void change() {

col = color(255, 0, 0);

}

(84)

What if the colliding objects are not particle object?

 What if the colliding objects are boundary, box or any other class?

 Use the query function

 You cannot create or destroy Box2D entities inside of beginContact(), endContact()

Object o1 = b1.getUserData();

//Asking that object if it’s a Particle if (o1.getClass() == Particle.class) { Particle p = (Particle) o1;

p.change();

}

(85)

Integration & Differentiation

 Integration, Differentiation

 Differentiation : The derivative of a function is a measure of how a function changes over time.

Velocity can be described as the “derivative” of location Acceleration is the “derivative” of velocity.

 Integration : inverse of differentiation, How can we update location from given velocity?

Location is the integral of velocity Velocity is the integral of acceleration

85

(86)

Euler integration

 The simplest form of integration and very easy to implement in our code

velocity.add(acceleration);

location.add(velocity);

 But, not accurate! : Real world is continuous, but our world is discrete

Real world is curve

But, our world is line segments

(87)

Better integration methods

 semi-explicit Euler : Box2D use

http://en.wikipedia.org/wiki/Symplectic_Euler_method

 Runge-Kutta : other game engine

 Verlet integration

Do not store velocity,

we always know the all past locations and current locations.

Library toxiclibs(http://toxiclibs.org/)

87

(88)

Toxiclib

(89)

Verlet Physics with toxiclibs

 toxiclibs includes a suite of other wonderful packages that help with audio, color, geometry, and more

 designed specifically for use with Processing

 coordinate system that we’ll use for the physics engine is the coordinate system of Processing

 all of the physics simulations and functions work in both two and three dimensions

 Does not have collision detection

 Best work if you have lots of particles flying around the screen.

Sometimes they attract each other. Sometimes they repel each other. And sometimes they are connected with springs.

 High performance due to the Verlet integration algorithm

89

(90)

Comparison

Feature Box2D toxiclibs Verlet

Physics

Collision geometry Yes No

3D physics No Yes

Particle attraction /

repulsion forces No Yes

Spring connections Yes Yes

Other connections: revolute,

pulley, gear, prismatic Yes No

Motors Yes No

Friction Yes No

(91)

VerletPhysics

 toxiclibs (http://toxiclibs.org/)

 core elements

91

Box2D toxiclibs VerletPhysics

World VerletPhysics

Body VerletParticle

Shape Nothing! toxiclibs does not handle shape geometry Fixture Nothing! toxiclibs does not handle shape geometry

Joint VerletSpring

(92)

A new vector class for

 Vec2D (http://toxiclibs.org/docs/core/toxi/geom/Vec2D.html)

 Vec3D (http://toxiclibs.org/docs/core/toxi/geom/Vec3D.html)

PVector Vec2D

PVector a = new PVector(1,-1);

PVector b = new PVector(3,4);

a.add(b);

Vec2D a = new Vec2D(1,-1);

Vec2D b = new Vec2D(3,4);

a.addSelf(b);

PVector a = new PVector(1,-1);

PVector b = new PVector(3,4);

PVector c = PVector.add(a,b);

Vec2D a = new Vec2D(1,-1);

Vec2D b = new Vec2D(3,4);

Vec2D c = a.add(b);

PVector a = new PVector(1,-1);

float m = a.mag();

a.normalize();

Vec2D a = new Vec2D(1,-1);

float m = a.magnitude();

a.normalize();

(93)

Basic setup

93

import toxi.physics2d.*;

import toxi.physics2d.behaviors.*;

import toxi.geom.*;

VerletPhysics2D physics;

void setup() {

//Creating a toxiclibs Verlet physics world physics=new VerletPhysics2D();

//put hard boundaries

physics.setWorldBounds(new Rect(0,0,width,height));

//set the gravity

physics.addBehavior(new GravityBehavior(new Vec2D(0,0.5)));

}

void draw() {

// This is the same as Box2D’s “step()” function physics.update();

}

(94)

Example codes

I will give several example source codes that use the toxiclib.

If you are interested in this code, take a look at those codes and use

for your project

참조

관련 문서