게임프로그래밍 2 강의노트 02 ODE Basics 동명대학교 게임공학과 강영민....

Preview:

Citation preview

게임프로그래밍 2강의노트 02ODE Basics

동명대학교 게임공학과강영민

Introduction

• ODE– Free, industrial quality library– Articulated rigid body simuation– Good for

• Ground vehicles• Legged creatures• Moving objects

– Fast and robust– Built-in collision detection– Develped by Russell Smith

Features

• ODE is for– Articulated rigid bodies– Interactive or real-time simulation– Highly stable integrator

• Simulation system should not explode with no reason

– Collision detection• Fast identification of potentially intesecting

objects• Exploits the concept of “spaces”

Features

• ODE features– Rigid bodies with arbitrary mass distribution– Joint types: ball-and socket, hindge, slider, hinge-2,

fixed, angular motor, universal– Collision primitives: shpere, box, capped cylinder, plane,

ray, and triangluar mesh– Collision spaces: quad tree, hash space, and simple– Simulation method: Lagrange multiplier velocity based

model– First order integrator: fast but not accurate enough– Contact and Friction: based on Dantzig LCP solver by

Baraff, and faster approx. of Coloumb friction.– Native C interface– C++ interface

ODE License

• ODE– Free software

• You canredistribute it and/or modify it under the terms of Either

– 1. GNU Less General Public License– 2. BSD-style license

– It is distributed in the hope that it will be useful, but withouth any warranty

How to use

• Download– http://www.ode.org– Download the library

• Binary library for Windows

• Using ODE– #include <ode/ode.h>

Concepts

• Background– Baraff’s Siggraph Tutorial

• Rigid bodies– Variable Properties

• Position vector• Linear velocity• Orientation of a body• Angular velocity

– Contant properties• Mass• Inertial matrix

Concepts

• Integration– Numerical integration– ODE integration

• very stable• No particularly accurate unless the step is

small

• Force accumulator– Forces are added to “force accumulator”– Force accumulator

• Within a rigid body

Concepts

• Joints and constraints– Similar to joints in the real life

• Hindge, ball-socket …

• Joint groups– Special container that holds joints in the world

• Joints can be added to a group• When joints are no longer needed, entire group can be

destroyed– Most useful with contact joints

• Collision handling– Built-in collision functions

Concepts• Typical simulation code

1. Create a dynamics world2. Create bodies in the dynamics world3. Set the state of all bodies4. Create joints in the dynamics world5. Attach the joints to the bodies6. Set the parameters of all joints7. Create a collision world and collision geometry objects, as necessary8. Create a joint group to hold the contact joints9. Loop

(a) Apply force to the bodies(b) Adjust the joint parameters(c) Call collision detection(d) Create a contact joint for every collision point, and put it in the contact

joint group(e) Tack a simulation step(f) Remove all joints in the contact joint group

10. Destroy the dynamics and collision world

Data types• Data types

– dReal– dVector3– dVector4– dMatrix3– dMatrix4– dQuaternion

• Objects and IDs– dWorld: a dynamics world– dSpace: collision space– dBody: a rigid body– dGeom: geometry (for collision)– dJoint: a joint– dJointGroup: a group of joints– Functions that deal with these take and return object IDs

World

• World object– A container for rigid bodies and joints– Objects in different worlds can not interact

• Two rigid bodies from different worlds can’t collide

– Most application will only need one world• World creation and destruction

dWorldID dWorldCreate();Void dWorldDestroy(dWorldID);

World

• Gravity setting void dWorldSetGravity(dWorldID, dReal x, dReal y, dReal

z); void dWorldGetGravity(dWorldID, dVector3 gravity);

• Error reduction parameter void dWorldSetERP(dWorldID, dReal erp); void dWorldGetERP(dWorldID);

• Constraint force mixing setting void dWorldSetCFM(dWorldID, dReal cfm); dReal dWorldGetCFM(dWorldID);

Tutorial

• OpenGL 기반의 프로그램 작성– GLUT 확인

• GL 관련 라이브러리 – Opengl32.lib glu32.lib glut32.lib

– ODE 라이브러리 확인• 추가 포함 디렉토리• 추가 링크 디렉토리 지정• Dll 파일을 적절한 곳으로 보냄

Tutorial

• 라이브러리 링크– Opengl32.lib

glu32.lib glut32.lib– Ode.lib

• OpenGL 기반 프로그램 작성

Tutorial

• Main.cpp– 헤더파일 포함

• #include <stdlib.h> • #include <GL/glut.h> • #include <ode/ode.h> • #include "Timer.h“

– Time management

Timer.h#ifndef __KANGSTIMER2006_#define __KANGSTIMER2006_

#include <windows.h>

// Timer Class// // Young-Min Kang (c) 2006// -----------------------------------

class CTimer {bool mWorking;// Time variables (second)double mET; //- Elapsed Timedouble mDT; //- Time difference between the previous frame and the current frame// Time variables (millisecond)long mStartTime;long mPreviousTime;long mCurrentTime;long mTotalElapsedTime;long mDiffTime;

public:CTimer();void Init(void);void Reset(void);void UpdateTime(void);double GetElapsedTime(void); // returns elapsed time in secondsdouble GetTimeDifference(void); // returns the time difference btw the curr and the prev frames in secondsvoid RemoveDelay();

};

#endif

Tutorial

• Main.cpp– Constant definition and variable declaration

• #define MASS 0.01

• dWorldID world; • dSpaceID space; • dBodyID body; • dJointGroupID contactgroup; • dGeomID ground; • dGeomID box;

• CTimer myTimer;

Tutorial• General OpenGL structure

static void resize(int width, int height) { const float a = (float) width / (float) height; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-a, a, -1.0, 1.0, 2.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity() ; }

static void display(void) { }

Main function

const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };

int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowSize(640,480); glutInitWindowPosition(10,10); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

glutCreateWindow("ODE");

glutReshapeFunc(resize); glutDisplayFunc(display); glutKeyboardFunc(key); glutIdleFunc(idle);

glClearColor(1,1,1,1); glEnable(GL_CULL_FACE); glCullFace(GL_BACK);

glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS);

glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING);

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); …

Create a dynamics world in main

function

// create world world = dWorldCreate(); space = dHashSpaceCreate (0); contactgroup = dJointGroupCreate (0); dWorldSetGravity (world,0, -9.8, 0);ground = dCreatePlane (space,0,1,0,0);

// Rigid Body CreationdMass m; body = dBodyCreate (world); dMassSetBox (&m,1,1,1,1); dMassAdjust (&m,MASS); dBodySetMass (body,&m); dBodySetPosition (body,0,2,-6);

box = dCreateBox (space,1,1,1); dGeomSetBody (box,body);

myTimer.Init();

dBodyAddForce (body,0.5,0,0); dBodyAddTorque(body, -0.1, 0.00, 0.03);

glutMainLoop();

dJointGroupDestroy (contactgroup); dSpaceDestroy (space); dWorldDestroy (world);

return 0; }

Display function

static void display(void) { myTimer.UpdateTime();

double dt = myTimer.GetTimeDifference();

dSpaceCollide (space,0,&nearCallback);

if(dt>0) dWorldQuickStep (world,dt);

// remove all contact joints dJointGroupEmpty (contactgroup);

float* pos = (float*)dGeomGetPosition(box); float* rot = (float*)dGeomGetRotation(box);

float m[16]; m[0]=rot[0]; m[4]=rot[1]; m[8] =rot[2]; m[12]=pos[0]; m[1]=rot[4]; m[5]=rot[5]; m[9] =rot[6]; m[13]=pos[1]; m[2]=rot[8]; m[6]=rot[9]; m[10]=rot[10];m[14]=pos[2]; m[3]= 0.0f; m[7]= 0.0f; m[11]= 0.0f; m[15]=1.0f;

// u v w t

Display function

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3d(1,0,0); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); gluLookAt(0,1,0,0,0,-6,0,1,0);

// Box Drawing

glPushMatrix(); glMultMatrixf( m );

glutSolidCube(1);glPopMatrix();

// ShadowglPushMatrix(); glColor3f(0.5,0.5,0.5);glDisable(GL_LIGHTING);glScalef(1.0,0.01,1.0);glMultMatrixf( m );glEnable(GL_LIGHTING);glutSolidCube(1);glPopMatrix();

glutSwapBuffers(); }

Keyboard & idle functionsstatic void key(unsigned char key, int x, int y) {

switch (key) {case 27 :exit(0); case 'r':

dBodySetPosition (body,0,2,-6); dBodyAddForce(body,(rand()%10)/10.0,(rand()%10)/10.0,(rand()%10)/10.0); dBodyAddTorque(body,

(rand()%10)/30.0, (rand()%10)/30.0,(rand()%10)/30.0);

break;}glutPostRedisplay();

}

static void idle(void) { glutPostRedisplay(); }

Collision Handling// this is called by dSpaceCollide when two objects in space are // potentially colliding. static void nearCallback (void *data, dGeomID o1, dGeomID o2) { int i;

dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2);

dContact contact[3]; // up to 3 contacts per box for (i=0; i<3; i++) { contact[i].surface.mode = dContactSoftCFM | dContactApprox1; contact[i].surface.mu = 0.5; contact[i].surface.soft_cfm = 0.01; } if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) { for (i=0; i<numc; i++) { dJointID c = dJointCreateContact (world,contactgroup,contact+i); dJointAttach (c,b1,b2); } } }

Simulation Result

Reference Manual

• dWorldID dWorldCreate(void)– Create a new, empty world and return its ID

• void dWorldDestroy(dWorldID world)– Destroy a world and everything in it

• void dWorldSetGravity(dWorldID, dReal x, dReal y, dReal z)– Set the world’s global gravity vector

• dSpaceID dHashSpaceCreate(dSpaceID spc)– Create a multi-resolution hash table space

• void dSpaceDestroy(dSpaceID)– Destroy a space

Reference Manual• dBodyID dBodyCreate(dWorldID)

– Create a body in given world• dMassSetBox• dMassAdjust• void dBodySetMass(dBodyID, const dMass *m)

– Set the mass of a body• dBodySetPosition

– Set position of a body• dGeomID dCreateBox(dSpaceID space, dReal x, dReal y,

dReal z)– Create a body of the givie x,y,z size lengths and return it ID– If space is nonzero, insert it into the space

• void dGeomSetBody(dGeomID, dBodyID)– Set the body associated with a placeable geom

Reference Manual• void dBodyAddForce(dBodyID, dReal x, dReal y, dReal z)

– Add force at center of mass of body in absolute cordinate• Void dBodyAddTorque(dBodyID, dReal, dReal, dReal)

– Add torque at center of mass of body in absolute cordinate• dGeomID dGeomGetBody(dBodyID)

– Get the body associated with a placeable geom• dJointID dJointCreateContact(dWorldID, dJointGroupID, const

dContact *)– Create a new joint of the contact type

• void dJointAttach(dJointID, dBodyID body1, dBodyID body2)– Attach a joint to some new bodies

• dJointGroupID dJointGroupCreate(int max_size)– Create a joint group

• void dJointGroupDestroy(dJointGroupID)– Destroy a joint group

ODE Joints

• Joint– Real life

• Something like a hinge, that is used to connect two objects.

– ODE• Very similar to the real joints• Constraints that enforces two bodies to be

connected• Mathematical view: constraints satisfaction

Types of joints

• Ball-Socket• Hinge• Slider

Joint Simulation

• New Example– Based on the previous source code

• Result– Two box objects are linked to a ball with

hinge joints

Joint Simulation

• Object Creation– Body and Geometry

dMass mSphere; dMassSetSphereTotal (&mSphere,MASS,RADIUS);dMassAdjust (&mSphere,MASS); SphereBody = dBodyCreate (world); dBodySetMass (SphereBody,&mSphere);dBodySetPosition (SphereBody,0, BOXH*1.5+RADIUS,

0); SphereGeom = dCreateSphere (space,RADIUS);dGeomSetBody (SphereGeom, SphereBody);

Joint Simulation

• Linking objectsvoid LinkBoxAndSphere (){

// Creation of hinge jointjoint1 = dJointCreateHinge (world, 0);// Connecting the bodies with hinnge jointdJointAttach (joint1, BoxBody, SphereBody);// The anchor of the hinge joint dJointSetHingeAnchor (joint1,

0, BOXH*1.5, 0);dJointSetHingeAxis (joint1, 1, 0, 0);

}

API

void dMassSetSphereTotal(dMass, double mass, double radius);

dCreateSphere(dSpaceID, double radius);

dMassSetBoxTotal(dMass,double mass, double x, double y, double z);

dCreateBox(dSpaceID,double x, double y, double z);

API

void dJointCreateHinge(dWorldID, dJointGroupID);

dJointSetHingeAnchor(dJointID, x, y, z);

dJointSetHingeAxis(axis_u, axis_v, axis_w);

Ball Joints

• Ball Joints– Axis is not needed– dJointCreateBall– dJointAttach– dJointSetBallAchor

Slider Joints

• Slider Joints– Need axis– dJointCreateSlider– dJointAttach– dJointSetSliderAxis– dJointSetSliderParam

Examples

• Ball-Socket– joint2 = dJointCreateBall (world, 0);– dJointAttach (joint2, BoxBody2, SphereBody);– dJointSetBallAnchor (joint2, 0, BOXH*1.5 +

RADIUS*2.0, 0);

• Slider– joint2 = dJointCreateSlider (world, 0);– dJointAttach (joint2, BoxBody2, SphereBody);– dJointSetSliderAxis(joint2, 0, 1, 0);– dJointSetSliderParam(joint2, dParamLoStop, -10);– dJointSetSliderParam(joint2, dParamHiStop, 10);

Recommended