Download Avatar

Document related concepts
no text concepts found
Transcript
Do it yourself
3D Games with OpenGL
Szirmay-Kalos László
Dept. of Control Engineering and Information Technology
Budapest University of Technology
email: [email protected]
Web: http://www.iit.bme.hu/~szirmay
Demo 1: The goal
sgame/SpaceGame I
3D
Games
Field objects
Self
Enemy
AI
Virtual reality
rendering
interaction
control
avatar
virtual world
Subtasks of Games
Rendering the scene from the point of view
of the avatar (virtual self)
 Controlling the avatar through the input
devices (keyboard, mouse)
 Controlling the „intelligent” virtual objects
(AI)
 Simulating the physical world

Libraries for input and output
Windows + GLUT
simulation
input
virtual world
modell
rendering
OpenGL
Interaction schemes
printf
scanf var1
event
state
printf var2
scanf
Event
handler
Program driven:
event - variable
correspondance: PC
Event driven:
event - variable
correspondance: state
Input/Output management
initialization
callback registration
Operating
system
Windows
main
DisplayFunc
GLUT
KeyboadFunc
SpecialFunc
callbacks
IdleFunc
graphics
hardware
OpenGL
application
OpenGL

Rendering API (library)
– Rendering of 2D and 3D objects
– follows the drawing state concept
– Image operations

Independent of the windowing and
operation systems
– Window management should be done
separately
OpenGL
application
GLUT
glX, wgl
glu
Xwindow, MS-Windows
gl
hw
Window
system
Windowing
bridge
Window
management
Convenience,
tessellators
OpenGL syntax (C API)
part of OpenGL API
glVertex3dv( … )
# of parameters
2 - (x, y)
3 - (x, y, z),
(R, G, B)
4 - (x, y, z, h)
(R, G, B, A)
Data type
b - byte
ub - unsigned byte
s - short
i - int
f - float
d - double
Vector or scalar
v - vector
- scalar
R,G,BInitialization
- R,G,B - Z
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
// initialization
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
glutCreateWindow( "Space Game" );
glutDisplayFunc( DisplayFunc ); // callback registration
glutIdleFunc( IdleFunc );
glutKeyboardFunc( KeyboardFunc );
glutSpecialFunc( SpecialKeyboardFunc );
glutMainLoop();
}
Demo 2:
Single and double buffering
single:sgame/Files/sgamesing.exe
double: sgame/Files/sgame.exe
Double buffering for animation
draw
frame
buffer
1.
frame
buffer
2.
glClear(GL_COLOR_BUFFER_BIT);
drawing…
glutSwapBuffers( );
display
monitor
Rendering with OpenGL
world definition
modell-view transform
2.
perspective
transform
1.

628
clipping
z-buffering
1325 1325
628
display
Why do we need
perspective transform?
perspective
transform
What is seen in a pixel?
x1
x2
X = d z1 = d
z2
X = x1 = x2
y2
y1
Y = d z1 = d z2
Y = y1 = y2
Definition of transformations
X
Y
Z
Tmodellview
x
y
z
Tmodell
Tview
Tperspective
XP
Tviewport
YP
move,
rotate
scale
objects
eye position
viewing direction
view up
field of view
aspect ratio
front-back clipping
Elementary transformations
glTranslate:
r’ = r + p
 glScale: x’= Sx x; y’= Sy y; z’ = Sz z

r’ = r

Sx
0
0
0
Sy
0
0
0
Sz
glRotate (ex. Rotation around axis z):
r’ = r
cos f
sin f 0
-sin f
cos f 0
0
0
1
Homogeneous coordinates

Translation cannot fit into a 3x3 matrix
– Let us work with 4x4 matrices
a11
A
a12 a13
0
[r’, 1] = [r, 1] a21 a22 a23
= [r A + p, 1]
0
a31 a32 a33
p
0
p1 p2 p 3
[r’,1] = (...([r,1] Tn1) Tn-1)... T1) = [r,1] (TnTn-1... T1)
Definition of transformations
glViewport(0, 0, w, h);
h
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
gluPerspective(fov,w/h,front,back);
w
fov
eye
w
h
lookat
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( );
gluLookAt(eyex, eyey, eyez,
lookatx, lookaty, lookatz,
vupx, vupy, vupz);
glTranslatef(px, py, pz);
world definition glRotatef(angle, axx, axy, axz);
Scene Definition OpenGL
glBegin(GL_TRIANGLES);
x12,y12,z12
x13,y13,z13
x11,y11,z11
glColor3f( 1, 1,
glVertex3f( x11,
glVertex3f( x12,
glVertex3f( x13,
0 );
y11, z11 );
y12, z12 );
y13, z13 );
glColor3f( 0, 1,
glVertex3f( x21,
glVertex3f( x22,
glVertex3f( x23,
0 );
y21, z21 );
y22, z22 );
y23, z23 );
glColor4f(R,G,B,A)
glEnd();
Texturing
Texture Mapping in OpenGL
(u2, v2)
x3,y3,z3
(u1, v1)
(u3, v3)
x2,y2,z2
x1,y1,z1
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_id); //
glBegin(GL_TRIANGLES);
glTexCoord2f(u1, v1);
glVertex3f(x1, y1,
glTexCoord2f(u2, v2);
glVertex3f(x2, y2,
glTexCoord2f(u3, v3);
glVertex3f(x3, y3,
glEnd();
glDisable(GL_TEXTURE_2D);
which texture
z1);
z2);
z3);
Definition of Textures
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
// load image
int width, height;
unsigned char * image;
image = LoadImage( filename, &width, &height );
// store texture
glTexImage2D(GL_TEXTURE_2D, 0,
GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, image );
Images, image formats



Head:
– type, size (width, height)
– bits-per-pixel, indexed-true color, lookup table
Body:
– width x height number of pixels: (R,G,B) or idx
– Encoding, compression (run length, LZW,
Huffmann, FFT, wavelet)
Standard formats:
– TARGA, BMP, GIF, JPEG, TIFF, PCX
TARGA (.TGA)
Head:
0
0
2
9 zeros
lower byte of width
upper byte of width
lower byte of height
upper byte of height
Bits-per-pixel: 24
32
Body
Body:
b1
g1
r1
b2
g2
r2
…
Definition of surfaces as
triangle meshes: Tessellation
1. Find a parametric equation:
x(u,v) = x0 + r cos 2u sin v
y(u,v) = y0 + r sin 2u sin v
z(u,v) = z0 + r cos v
u,v  [0,1]
2. Select points in the unit rectangle
Quadrics: Sphere
// definition
GLUquadricObj * quadric;
quadric = gluNewQuadric( );
gluQuadricTexture(quadric, GL_TRUE);
// draw
glBindTexture(GL_TEXTURE_2D, texture_id);
gluSphere(quadric, R, 16, 10);
Rotating Earth: init
GLUquadricObj * quadric;
unsigned int earth_texture;
void Init( ) {
quadric = gluNewQuadric( );
gluQuadricTexture(quadric, GL_TRUE);
glGenTextures(1, &earth_texture);
glBindTexture(GL_TEXTURE_2D, earth_texture_id);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
image = LoadImage(”earth.tga”, &width, &height );
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,
0, GL_RGB, GL_UNSIGNED_BYTE, image);
}
GLUT timer control
long time;
void IdleFunc( ) {
// idle call back
float old_time = time;
time = glutGet( GLUT_ELAPSED_TIME );
float dt = time - old_time;
AnimateIt( dt );
DrawIt( );
}
Rotating Earth: animate, draw
void AnimateIt( float dt ) {
angle += rot_speed * dt;
if (angle > 360.0) angle -= 360.0;
}
void DrawIt( ) {
glClearColor(0, 0, 0, 0);
// R,G,B,A
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix( );
glRotatef( angle, 0, 0, 1 );
glBindTexture(GL_TEXTURE_2D, earth_texture);
gluSphere( quadric, 1.0, 16, 10 );
glPopMatrix( );
glutSwapBuffers( );
}
Demo 3: Rotating Earth
sgame/earth/earth1.exe
Earth Revolves around
the Sun
void AnimateIt( float dt ) {
rot_angle += rot_speed * dt;
rev_angle += rev_speed * dt;
}
rot_angle
rev_angle
dist
void DrawIt( ) {
glPushMatrix( );
glRotatef(rev_angle, 0, 0, 1);
glTranslatef(dist, 0, 0 );
glRotatef(rot_angle, 0, 0, 1);
glBindTexture(GL_TEXTURE_2D,
earth_texture);
gluSphere(quadric, 1, 16, 10);
glPopMatrix( );
glutSwapBuffers( );
}
Demo 3: Rotating Earth
revolves around the Sun
sgame/earth/earth.exe
SS,SS,SS
Creating the space
void DrawIt( ) {
glBindTexture(GL_TEXTURE_2D,
space_texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(-SS, -SS, -SS);
-SS,-SS,-SS
glTexCoord2f(0, 1);
glVertex3i(-SS, SS, -SS);
glTexCoord2f(1, 1);
glVertex3i( SS, SS, -SS);
glTexCoord2f(1, 0);
glVertex3i( SS, -SS, -SS);
...
glEnd();
}
ControlIt(dt)
Games
AnimateIt(dt), DrawIt()
rendering
interaction
control
avatar
virtual world
Game Object

ControlIt:
– interacts with the others, ”thinks” and sets the
available controls (e.g. rockets)

InteractIt:
– communication between two objects

AnimateIt:
– moves to the next position and orientation

DrawIt:
– renders the object with OpenGL
Simulation loop (Game loop)
dt
void IdleFunc( ) {
// idle call back
float old_time = time;
time = glutGet( GLUT_ELAPSED_TIME );
float dt = time - old_time;
avatar -> ProcessInput( );
world -> Control( dt );
world -> Animate( dt );
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
avatar -> SetCameraTransform();
world -> Draw();
glutSwapBuffers( );
}
Game dataflow
Input
Processing:
KeyboardFunc,
SpecialFunc
input
Simulate:
IdleFunc
virtual
world
Render
Representation of the
virtual world



Dynamic objects (kill)
Different object types (heterogeneous collection)
Linked list (hierarchical structures, trees)
world
ship1
ship2
space
avatar
sun
bullet
explosion
Join: add new element
Spaceship

Complex geometry
– quadrilateral mesh
Complex texture
 Physical animation

– forces (gravitation, rockets)
– collisions

Behaviour (AI)
– control rockets

avoid collisions, escape from avatar, chase avatar
Building a ship:
Polygon modelling in Maya
Extruding
Extruding (still)
Extruding (once more)
Extruding (final)
Smoothing by Subdivision
Subdivision surfaces
= 1/4 
= 1/4  + 1/4 
= 1/2 + 1/16 
+ 1/16 
Subdivision smoothing:
1 level
Subdivision smoothing:
2 levels
Texturing
modell
texture
Definition of the parameterization
in Maya
(0,0)
(1,1)
Definition of the parameterization
Creating a texture for the ship
Textured ship
Animate: using Newton’s laws
m
force
position
velocity
void Ship :: AnimateIt( float dt ) {
acceleration = force/m;
velocity += acceleration * dt;
position += velocity * dt;
}
void Ship :: DrawIt() {
glPushMatrix( );
glTranslatef(position.x, position.y, position.z);
glBegin( GL_QUADS ); ... ; glEnd( );
glPopMatrix();
}
modell_head
Orientation Control
world_head = velocity.UnitVector();
void Ship :: DrawIt() {
glPushMatrix( );
glTranslatef(position.x, position.y, position.z);
Vector modell_head( 0, 0, 1 );
Vector world_head = velocity.UnitVector();
Vector rotate_axis = modell_head % world_head;
float cos_rotate_angle = world_head * modell_head;
glRotatef( acos(cos_rotate_angle)* 180 / M_PI,
rotate_axis.x,rotate_axis.y,rotate_axis.z);
glBegin( GL_QUADS ); ... ; glEnd( );
glPopMatrix( );
}
Ship :: ControlIt
void Ship :: ControlIt( float dt ) {
force = Vector(0, 0, 0);
Interact( world );
}
void Ship::InteractIt( GameObject * object )
world
ship1
ship2
space
avatar
sun
bullet
explosion
Ship: InteractIt
void Ship :: InteractIt( GameObject * object ) {
if ( object->GetType( ) == PLANET ) {
F = f m·M
r2
}
if ( object->GetType( ) == AVATAR ) {
bullet
avatar
}
}
avatar
aiming angle
Ship: InteractIt
F = f m·M
r2
if ( object->GetType( ) == PLANET ) {
Planet * planet = (Planet *)object;
Vector dist = planet->position - position;
float r = dist.Length();
force += dist * f * mass * planet->mass /r/r/r;
if ( r < planet->Radius() * 2 )
force += (position - planet->position)/r;
if ( r < planet->Radius()+BoundingRadius() )
Kill();
}
Ship: InteractIt
bullet
avatar
avatar
aim
if ( object->GetType( ) == AVATAR ) {
Avatar * avatar = (Avatar *)object;
Vector goal = avatar -> position - position;
force += goal * 0.05;
cosaim = velocity.UnitVector()*goal.UnitVector();
if (cosaim > 0.9) {
world-> Join( new Bullet(position, velocity));
}
}
Collision detection between
two slow objects
Problem with fast objects
t
given t
t+t
dist = obj1.position - obj2.position
min = obj1.BoundingRadius() + obj2.BoundingRadius()
if (dist.Length() < min) Collision!
Bullet
Seemingly complex
geometry
 Similar look from all
directions
 Easier to define its image

transparent

Hit detection = fast collision detection
Billboards

Single semi-transparent texture on an
oriented quadrilateral
pos
pos
QUAD
QUAD
x
y
z
Tmodell
position
orientation
Tview
Tperspective
camera position
camera orientation
X
Y
Z
Bullet :: DrawIt
void Bullet :: DrawIt() {
Set transformation to compensate the rotation
of the camera transform
glEnable(GL_BLEND);
// transparency
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glTexCoord2f(1, 0);
glTexCoord2f(1, 1);
glTexCoord2f(0, 1);
glEnd();
glDisable(GL_BLEND);
}
glVertex2f(-size, -size);
glVertex2f(size, -size);
glVertex2f(size, size);
glVertex2f(-size, size);
How can we store
transparent textures?
Some image file formats allow not only
RGB triplets, but also RGBA quadruples
 Store the texture into two images

– image 1: rgb
– image 2: a gray-scale image of alpha
Compensate camera
transform
float viewMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
0
Rotation
0
0
tx, ty, tz 1
invert
pos.x, pos.y, pos.z
glMultMatrixf( viewMatrix );
Collision detection with fast objects:
ray-tracing
position
vel2
velocity
rel_velocity = velocity - vel2
ray: position + rel_velocity·t
If (ray intersects bounding sphere first
AND tintersect < dt) Collision!
hit_object = world->Intersect(position,velocity,t);
world
ship1
ship2
avatar
space
sun
bullet
explosion
Bullet :: ControlIt
void Bullet :: ControlIt( float dt ) {
GameObject * hit_object =
world -> Intersect(position, velocity, t);
if ( t > 0 && t <= dt ) {
Kill();
// bullet disappears
Vector hit_point = position + velocity * t;
int hit_type = hit_object -> GetType();
if ( hit_type == AVATAR ) exit(1); // player is killed
else {
world -> Join( new Explosion( hit_point ) );
if (hit_type == SHIP) hit_object -> Kill();
}
}
age += dt;
if ( age > 10 ) Kill();
// bullet disappears
}
Explosion
Seemingly complex,
randomly animated
structure
 Similar look from all
directions
 Collection of billboards


Particle system
Particle Systems
global force field
(smoke)
random
initial
values
position:
velocity:
acceleration:
position += velocity * dt
velocity += acceleration * dt
acceleration = force / weight
lifetime
age:
age += dt; if (age > lifetime) Kill();
size, dsize:
weight, dweight:
color, dcolor:
size += dsize * dt;
weight += dweight * dt
color += dcolor * dt
Explosion settings
var
Rand(mean, var)
position = Rand( center, 0.1 );
lifetime = Rand( 2.0, 1.0 );
mean
// initially focused
size = 0.001;
// initially small
dsize = Rand( 1.0, 0.5 ) / lifetime / 2.0;
velocity = Rand( Vector(0, 0, 0), 0.4 );
// symmetric
acceleration = Rand( Vector(0, 0, 0), 0.4 );
// from yellow opaque animate to reddish transparent
color = Rand( Color(1, 0.5, 0, 1), Color(0, 0.5, 0, 0) );
dcolor = Color(0, -0.5, 0, -1) / lifetime / 2;
Avatar

Keyboard controls its behavior:
– ProcessInput

Its position and orientation will be the
camera position and orientation before
rendering
– SetCameraTransform

Like a ship but is not drawn
– Control: gravitation, bullet collision
Avatar :: SetCameraTransform
Avatar :: SetCameraTransform( ) {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z,
position.x + velocity.x,
position.y + velocity.y,
position.z + velocity.z,
up.x, up.y, up.z);
}
eye
up = [0, 1, 0]
lookat
Keyboard Processing
KeyboardFunc
SpecialFunc
input
IsSpace, IsLeft, IsRight, IsUp, IsDown
IdleFunc:
GameLoop
virtual
world
Avatar :: ProcessInput
Avatar :: ProcessInput( GLUTWindow * input ) {
if ( input->IsSpace( ) ) // shoot
world -> Join(new Bullet(position, velocity));
Vector head = velocity.UnitVector();
if
if
if
if
}
(
(
(
(
input->IsUp() )
input->IsDown() )
input->IsLeft() )
input->IsRight() )
force
force
force
force
+=
+=
+=
+=
up * (-1);
up;
up % head;
head % up;
GLUTWindow
GameEngine
DisplayFunc
IdleFunc
KeyPress
GameObject
position, velocity, acceleration
ControlIt(float dt )
AnimateIt(float dt)
InteractIt( GameObject * o)
DrawIt( )
IntersectIt(Ray r, float& t)
world
Member
Control, Animate, Draw
Interact, Intersect, Join
next
Game
Engine
500 C++ lines
Texture
Load( char * fname)
Particle
avatar
Avatar
ProcessInput()
SetCameraTransform()
ParticleSystem
TexturedObject BillBoard
Emit(int n)
DrawIt()
Space Game
GameEngine
Avatar
BillBoard
Self
ProcessInput
ControlIt
InteractIt
Bullet
ControlIt
TexturedObject
Space
DrawIt
Ship
Planet
DrawIt
DrawIt
InteractIt
AnimateIt
ControlIt
SpaceGame
350 C++ lines
Related documents