Ode a quick start

BlitzMax Forums/BlitzMax Tutorials/Ode a quick start

Chris C(Posted 2005) [#1]
OdeMax is far from finnished but it can be used to get
some good results...

This is aimed at people who are confused by what an opengl matrix is
and frankly would rather be using positionentity

some exposure to opengl is needed but I hope to explain things
by analogy there are a lot of terms like "object" that are very
confusing because they can relate to many things...


Lets rush through a basic framework that will get you up and running,
with simple shapes like a ball and box in an iteractive 3d
enviroment

looking at the gutted framework in OdeMax

Import "libodemax.a"
Import "liboderelease.a"


here we import or link into out program the ode library
and a small library of support routines that will make
our life easier.

include "odemax-utils.bmx"


more routines to help with ode, hopefully all of odemax will
live here one day...






	world=dworldcreate()
	dWorldSetGravity (world, 0,-9.81,0)
	space = dHashSpaceCreate (0);
	plane=dCreatePlane (space,0,1,0,0);

World, space and plane are just integers (or handles) to identify ode
"objects" think entities to avoid confusion with OOP objects!

Check the ODE .pdf from www.ode.org for info on what ode routines
like dWorldCreate actually does...

space contains all the ode entities that are in the same collision
space...





'this is a "static" box

hmmmm ignore this totally incorrect comment!!!!!

	Local v:Float[]=[0.0,2.0,0.0,1.0,.0,1.0]
	Local ss:Float[]=[0.2,1.6,0.2]
	Local e:odeent=OdeEnt.createBox(world,space,ss,v,10)

v is an array of float values the first 3 are xyz positions so its 2 units high
the next 3 floats are the xyz velocity

the ss variable is an array of dimensions for the box.

can you see from the values that its a long thin box?







	OMinitcontacts(world)

Do this once.
it sets up a few ode things.







' main loop
	While Not KeyHit( KEY_ESCAPE )
		omEmptyContactGroup()
		dSpaceCollide (space,Null, Byte Ptr omnearCallback);
		dWorldStep (world,0.016666)

we clear out any old contacts (or collisions)
check for collisions
and then step the simulation to handle ode interactions

so whats this magic number 0.016666 then?

well ode works best with time steps always the same size
now for us this is very use full hopefully out display
frame rate will be fixed to say 60 frames displayed
each second

so we take 1 second and divide it 60 frames
1/60=0.01666

Incidently 30 frames per second is faster that TV refresh
rate (1/2 frame every 50th second=25fps)
and will result in very impressive results when pushing
ode as far as you can

In addition if you find a machine that cant run a 3d app
at 30fps it sooo needs upgrading
Meaning your app should run on even modest machines




	If KeyHit(KEY_n) Then		blend = Not blend
	If blend = 0 Then
		glDisable GL_BLEND
		glEnable GL_DEPTH_TEST
	Else
		glEnable GL_BLEND
		glDisable GL_DEPTH_TEST
	End If

Inside the display loop theres a range of opengl "states" that will
alter the way that the objects are displayed
here for example is blending
often you will have to set up 1 or 2 simple opengl variables or
structures www.opengl.org has some "out of date" but perfectly
useful pdf's of previously published books the "Red" book
is particularly relevent here








	For Local e:odeent=EachIn OdeEntlist
		glpushmatrix()
		SetTransformMat(e.geom)
			If e.etype=OM_BOX Then
				If e.body=-1 Then
					glBindTexture GL_TEXTURE_2D, Texname3
				Else
					glBindTexture GL_TEXTURE_2D, Texname
				EndIf
				drawbox([e.size[0],e.size[1],e.size[2]])
			End If
			If e.etype=OM_BALL Then
				glBindTexture GL_TEXTURE_2D, earthtex
				drawsphere(e.size[0])
			EndIf
			glColor4f 1.0,1.0,1.0,1.0
			glenable(GL_LIGHTING)
		glpopmatrix()
	Next

Here's the meat of it all! every time the odemax utils are used to create
a box or sphere (and soon trimesh I hope!) like this:-
OdeEnt.createBox
an "entity" is added to the OdeEntList to draw all the objects we loop through
each one at a time
the first step is to save the current matrix (think of a matrix as just a
mathmatical discription of the objects, position, rotation and scale etc)
then using ode's matrix for the object in question SetTransformMat sets
up opengl's matrix so that when it draws the object it will be the
correct position/orientation etc

depending on the shape and object type a texture is selected and then
either drawbox or drawsphere draws the actual object

bare in mind these routines for ball and box always draws a shape unrotated
translated and without any allowance for perspective
Opengl then runs this shape through the matrix, its then that its actually
"distorted" so it looks as if its 3d.





Okay I think I understand that... now what do I do?


try
global myent:odeent

at the top of the code

after
	Local v:Float[]=[0.0,2.0,0.0,1.0,.0,1.0]
	Local ss:Float[]=[0.2,1.6,0.2]
	Local e:odeent=OdeEnt.createBox(world,space,ss,v,10)

add
	v[1]=1
	myent=OdeEnt.createSphere(world,space,ss,v,1)


after
Function DisplayLoop()
	Local x_m:Float; Local y_m:Float; Local z_m:Float; Local u_m:Float ; Local v_m:Float
	Local loop_m:Int

add
	If KeyDown(key_w) Then
		dBodyAddForce(myent.body, 0,0,1)
	EndIf
	If KeyDown(key_x) Then
		dBodyAddForce(myent.body, 0,0,-1)
	EndIf
	If KeyDown(key_a) Then
		dBodyAddForce(myent.body, 1,0,0)
	EndIf
	If KeyDown(key_d) Then
		dBodyAddForce(myent.body, -1,0,0)
	EndIf



now you have a marble to run round and collide with the long box




I do hope I haven't confused anyone here.


Must get back to implementing trimesh....


at the moment you are stuck with fixed surface interactions
I plan to add the ability to define how different
surfaces react to each other
	wood	stone	ice

wood    medium	rough	smooth

stone   xxx	v.rough	med smooth

ice	xxx	xxx	very slippy

so you could define how surfaces react together



If anyone would like to contribude a demo for odemax please contact me directly


Enjoy


Trumpetto(Posted 2005) [#2]
Where are libodemax.a, liboderelease.a and odemax-utils.bmx?


Trumpetto(Posted 2005) [#3]
sorry, found it.