Ode a quick start
BlitzMax Forums/BlitzMax Tutorials/Ode a quick start
| ||
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 |
| ||
Where are libodemax.a, liboderelease.a and odemax-utils.bmx? |
| ||
sorry, found it. |