OdeMax

BlitzMax Forums/BlitzMax Programming/OdeMax

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Here's a tweaked version of the included example:
Strict

Import ".\libode.a" 
Import ".\libodemax.a"

Incbin "wcrate.jpg"
Incbin "ground.bmp"
 
Global ScreenWidth:Float	= 800
Global ScreenHeight:Float	= 600
Global ScreenDepth:Int		= 32
Global FullScreen:Int		= 1

Global Texname,texname2

Global lastspace
Global light:Int=True									' Lighting ON/OFF
Global blend:Int									' Blending ON/OFF
Global xrot:Float									' X Rotation
Global yrot:Float									' Y Rotation
Global lookupdown:Float=0.0
Global heading:Float=0.0
Global xpos:Float=0.0
Global zpos:Float=0.0

Global LightAmbient:Float[]=[0.8, 0.8, 0.8, 1.0]		' Ambient Light
Global LightDiffuse:Float[]=[1.0, 1.0, 1.0, 1.0]		' Diffuse Light
Global LightPosition:Float[]=[0.0, 2.0, 1.0, 1.0]	' Light Position

Global FPS,lfc,fc   ' frame counter since app start
Global s:String=""

Global OdeEntList:tList = CreateList()

Global selectbuffer:Int[512],hits
Global SelectedName,lastselected:odeent
Global viewport:Int[4]

Global world,space,plane,boxbody,boxgeom,mass:Int[1024],boxsize:Float=0.1
Global lms:Int=MilliSecs()

Const MaxOdeEnts=50

include "ode-defs.bmx"

'
' Setup display
Local ScreenFlags = BGL_BACKBUFFER | BGL_DEPTHBUFFER
If FullScreen
	ScreenFlags = ScreenFlags | BGL_FULLSCREEN
EndIf
bglCreateContext(ScreenWidth,ScreenHeight,ScreenDepth,0,ScreenFlags)
bglSetSwapInterval(1)

InitGl()

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

'
' Create ODE boxes
For Local i:Float=1 To MaxOdeEnts/2	
	OdeEnt.createBox(world,space,i, 0.1,(i Mod 4-2)/4, (i / 4), -1)
Next
For Local i:Float=1 To MaxOdeEnts/2			' 2 loops name param must be created sequentially
	OdeEnt.createBox(world,space,i+MaxOdeEnts/2, 0.1,(i Mod 4-2.5)/4, (i / 4), -1.25)
Next

OMinitcontacts(world)


While Not KeyHit( KEY_ESCAPE )
	
	'
	' Update ODE
	omEmptyContactGroup()
	dSpaceCollide (space,Null, Byte Ptr omnearCallback);
	dWorldStep (world,0.01)
	
	'
	' Render and stuff
	glEnable(GL_TEXTURE_2D)
	DisplayLoop()
	glDisable(GL_TEXTURE_2D)
	glColor3f 1.0,1.0,1.0
	
	Local y=0

	If MilliSecs()>lms+1000 Then
		lms=MilliSecs()
		FPS=(fc-lfc)
		lfc=fc
	EndIf
	s = "#FPS: "+FPS
	s:+"##Use mouse to look around"
	s:+"#WASD/Arrow Keys to move"
	s:+"#Left click to select#"
	If lastselected
		s:+"#Selection: "+lastselected.name+"#"
	EndIf
	
	Local f=Instr(s,"#",1)
	Repeat 
		Local l:String= Left(s,f-1)
		s= Right(s,Len(s)-f)
		bglDrawText(l,10,y)
		y:+12
		f=Instr(s,"#",1)
	Until f=0
		
	FlushMem
	bglSwapBuffers
	fc:+1
Wend
End

'
' transfers the objects matrix into opengl ready to render
Function SetTransformMat(geom:Int)

	Local R:Float Ptr
	Local pos:Float Ptr 
	Local matrix:Float[16];

	pos =Float Ptr  dGeomGetPosition (geom);
	R = Float Ptr dGeomGetRotation (geom);

	matrix[0]=R[0];		matrix[1]=R[4];		matrix[2]=R[8];		matrix[3]=0;
	matrix[4]=R[1];		matrix[5]=R[5];		matrix[6]=R[9];		matrix[7]=0;
	matrix[8]=R[2];		matrix[9]=R[6];		matrix[10]=R[10];		matrix[11]=0;

	matrix[12]=pos[0];	matrix[13]=pos[1];	matrix[14]=pos[2];	matrix[15]=1;

	glMultMatrixf (matrix);

EndFunction

Function InitGl()
'''''' initial setup of gl
	Local tex:TPixmap=LoadPixmap("incbin::wcrate.jpg")
	texname=bglTexFromPixmap(tex)
	texname2=bglTexFromPixmap(LoadPixmap("incbin::ground.bmp"))

	glBindTexture GL_TEXTURE_2D, Texname2
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST

	glBindTexture GL_TEXTURE_2D, Texname
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
	glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST

	glEnable GL_TEXTURE_2D
	glBlendFunc GL_SRC_ALPHA, GL_ONE
	glClearColor(0.4, 0.4, 0.4, 0.0)
	glClearDepth 1.0
	glDepthFunc GL_LESS
	glEnable GL_DEPTH_TEST
	glShadeModel(GL_SMOOTH)
	
	glViewport(0,0,ScreenWidth,ScreenHeight)
	glMatrixMode(GL_PROJECTION)
	glLoadIdentity()
	gluPerspective(45.0,Float(ScreenWidth)/Float(ScreenHeight),0.1,100.0)
	glMatrixMode(GL_MODELVIEW)
	
	glLightfv GL_LIGHT0, GL_AMBIENT, Float Ptr LightAmbient
	glLightfv GL_LIGHT0, GL_DIFFUSE, Float Ptr LightDiffuse
	glLightfv GL_LIGHT0, GL_POSITION, Float Ptr LightPosition
	glEnable GL_LIGHT0
End Function

Function DisplayLoop()

	Local x_m:Float; Local y_m:Float; Local z_m:Float; Local u_m:Float ; Local v_m:Float
	Local xtrans:Float; Local ztrans:Float; Local ytrans:Float
	Local sceneroty:Float
	Local loop_m:Int

	'
	' Blend mode
	If KeyHit(KEY_B)
		blend = Not blend
	EndIf
	If blend = 0 Then
		glDisable GL_BLEND
		glEnable GL_DEPTH_TEST
	Else
		glEnable GL_BLEND
		glDisable GL_DEPTH_TEST
	End If
	
	'
	' Lighting
	If KeyHit(KEY_L) 
		light = Not light
	EndIf
	If light=0
		glDisable(GL_LIGHTING)
	Else
		glEnable(GL_LIGHTING)
	EndIf
 
 	'
 	' Movement
	If KeyDown(KEY_UP) Or KeyDown(KEY_W)
		xpos = xpos - Float(Sin(heading)) * 0.01
		zpos = zpos - Float(Cos(heading)) * 0.01
	End If
	If KeyDown(KEY_DOWN) Or KeyDown(KEY_S)
		xpos = xpos + Float(Sin(heading)) * 0.01
		zpos = zpos + Float(Cos(heading)) * 0.01
	End If
	If KeyDown(KEY_LEFT) Or KeyDown(KEY_A)
		xpos = xpos - Float(Sin(heading+90)) * 0.01
		zpos = zpos - Float(Cos(heading+90)) * 0.01
	EndIf
	If KeyDown(KEY_RIGHT) Or KeyDown(KEY_D)
		xpos = xpos + Float(Sin(heading+90)) * 0.01
		zpos = zpos + Float(Cos(heading+90)) * 0.01
	EndIf
	
	yrot = heading
		
	xtrans=-xpos
	ztrans=-zpos
	ytrans= - 0.5
	sceneroty = 360.0 - yrot
	glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT

	lookupdown=lookupdown+(MouseY()-(ScreenHeight/2.0))/8
	heading=heading-(MouseX()-(Screenwidth/2.0))/8
	MoveMouse screenwidth/2,screenheight/2


	'
	' ---- Picking ----
	'
	glSelectBuffer(512,Varptr selectBuffer[0]);

	glRenderMode(GL_SELECT)	
	glInitNames();	
	glGetIntegerv(GL_VIEWPORT, viewport);

	glMatrixMode(GL_PROJECTION);			
	glPushMatrix();						
	glLoadIdentity();
	gluPickMatrix(ScreenWidth/2.0, ScreenHeight/2.0, 1, 1, viewport);

	gluPerspective(45.0,Float(ScreenWidth)/Float(ScreenHeight),0.1,100.0)
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity
	glRotatef lookupdown, 1.0, 0, 0
	glRotatef sceneroty, 0, 1.0, 0
	glTranslatef xtrans, ytrans, ztrans

	glBindTexture GL_TEXTURE_2D, Texname2

	Local i=1
	For Local e:odeent=EachIn OdeEntlist
		glPushName(i)
		i:+1
		glPushMatrix()
		SetTransformMat(e.geom)
		drawbox([e.size,e.size,e.size])	
		glPopName()
		glPopMatrix()
	Next
	
	glFlush();			
	hits=glRenderMode(GL_RENDER);

	glMatrixMode(GL_PROJECTION);			
	glPopMatrix();								
	glMatrixMode(GL_MODELVIEW);	
	glColor4f 1.0,1.0,1.0,1.0

	If hits>0 Then processhits(hits,Varptr selectBuffer[0])
	'
	' ---- End of picking ----
	'


	'
	' Render code
	glLoadIdentity
	glRotatef lookupdown, 1.0, 0, 0
	glRotatef sceneroty, 0, 1.0, 0
	glTranslatef xtrans, ytrans, ztrans
	glBindTexture GL_TEXTURE_2D, Texname2

	glColor4f 1.0,1.0,1.0,1.0

	'
	' ground - not rendered in pick selection render
	glDisable(GL_LIGHTING)
	glBegin(GL_QUADS)
	glNormal3f( 0.0, -1.0, 0.0)';// Normal Pointing Up
	glTexCoord2f(0.0, 0.0); glVertex3f(-10,  0, -10)';// Point 1 (Top)
	glTexCoord2f(0.0, 10); glVertex3f(-10,  0,  10)';// Point 2 (Top)
	glTexCoord2f(10, 10); glVertex3f( 10,  0,  10)';// Point 3 (Top)
	glTexCoord2f(10, 0.0); glVertex3f( 10,  0, -10)';// Point 4 (Top)
	glEnd()
	glEnable(GL_LIGHTING)

	glBindTexture GL_TEXTURE_2D, Texname

	'
	' boxes
	Local se:odeent
	glBindTexture GL_TEXTURE_2D, Texname
	For Local e:odeent=EachIn OdeEntlist

		glPushMatrix()
		SetTransformMat(e.geom)
		If selectedname=e.name Then 
			glDisable(GL_LIGHTING)
			glColor4f 1.0,0.0,0.0,1.0 
			se=e
		ElseIf e.state
			glDisable(GL_LIGHTING)
			glColor4f 0.0,1.0,0.0,1.0
		Else
			glColor4f 1.0,1.0,1.0,1.0
		EndIf

		drawbox([e.size,e.size,e.size])	

		If selectedname=e.name Or e.state=True Then 
			glEnable(GL_LIGHTING)
		EndIf

		glPopMatrix()
	Next
	
	'
	' Change selection
	If MouseHit(1) And lastspace Then 
		If lastselected
			lastselected.state=False
		EndIf
		If se
			se.state=Not se.state
			lastselected=se
			lastspace=False
			Local fx:Float = Sin(heading)* -1000.0
			Local fy:Float = 0.0
			Local fz:Float = Cos(heading)* -1000.0
			dbodyaddforce(se.body,fx,fy,fz)
		EndIf
	EndIf
	If Not MouseHit(1) Then lastspace=True
	selectedname=0

End Function

Function DrawBox(sides:Float[])
	
	Local lx:Float = sides[0]*0.5;
	Local ly:Float = sides[1]*0.5;
	Local lz:Float = sides[2]*0.5;

	glBegin(GL_QUADS);
		
		' Front Face
		glNormal3f( 0.0, 0.0, 1.0) ' Normal Pointing Towards Viewer
		glTexCoord2f(0.0, 0.0); glVertex3f(-lx, -ly,  lz) ' Point 1 (Front)
		glTexCoord2f(1.0, 0.0); glVertex3f( lx, -ly,  lz) ' Point 2 (Front)
		glTexCoord2f(1.0, 1.0); glVertex3f( lx,  ly,  lz) ' Point 3 (Front)
		glTexCoord2f(0.0, 1.0); glVertex3f(-lx,  ly,  lz) ' Point 4 (Front)
 		
 		' Back Face
		glNormal3f( 0.0, 0.0,-1.0) ' Normal Pointing Away From Viewer
		glTexCoord2f(1.0, 0.0); glVertex3f(-lx, -ly, -lz) ' Point 1 (Back)
		glTexCoord2f(1.0, 1.0); glVertex3f(-lx,  ly, -lz) ' Point 2 (Back)
		glTexCoord2f(0.0, 1.0); glVertex3f( lx,  ly, -lz) ' Point 3 (Back)
		glTexCoord2f(0.0, 0.0); glVertex3f( lx, -ly, -lz) ' Point 4 (Back)
		
		' Top Face
		glNormal3f( 0.0, 1.0, 0.0) ' Normal Pointing Up
		glTexCoord2f(0.0, 1.0); glVertex3f(-lx,  ly, -lz) ' Point 1 (Top)
		glTexCoord2f(0.0, 0.0); glVertex3f(-lx,  ly,  lz) ' Point 2 (Top)
		glTexCoord2f(1.0, 0.0); glVertex3f( lx,  ly,  lz) ' Point 3 (Top)
		glTexCoord2f(1.0, 1.0); glVertex3f( lx,  ly, -lz) ' Point 4 (Top)
		
		' Bottom Face
		glNormal3f( 0.0,-1.0, 0.0) ' Normal Pointing Down
		glTexCoord2f(1.0, 1.0); glVertex3f(-lx, -ly, -lz) ' Point 1 (Bottom)
		glTexCoord2f(0.0, 1.0); glVertex3f( lx, -ly, -lz) ' Point 2 (Bottom)
		glTexCoord2f(0.0, 0.0); glVertex3f( lx, -ly,  lz) ' Point 3 (Bottom)
		glTexCoord2f(1.0, 0.0); glVertex3f(-lx, -ly,  lz) ' Point 4 (Bottom)
		
		' Right face
		glNormal3f( 1.0, 0.0, 0.0) ' Normal Pointing Right
		glTexCoord2f(1.0, 0.0); glVertex3f( lx, -ly, -lz) ' Point 1 (Right)
		glTexCoord2f(1.0, 1.0); glVertex3f( lx,  ly, -lz) ' Point 2 (Right)
		glTexCoord2f(0.0, 1.0); glVertex3f( lx,  ly,  lz) ' Point 3 (Right)
		glTexCoord2f(0.0, 0.0); glVertex3f( lx, -ly,  lz) ' Point 4 (Right)
		
		' Left Face
		glNormal3f(-1.0, 0.0, 0.0) ' Normal Pointing Left
		glTexCoord2f(0.0, 0.0); glVertex3f(-lx, -ly, -lz) ' Point 1 (Left)
		glTexCoord2f(1.0, 0.0); glVertex3f(-lx, -ly,  lz) ' Point 2 (Left)
		glTexCoord2f(1.0, 1.0); glVertex3f(-lx,  ly,  lz) ' Point 3 (Left)
		glTexCoord2f(0.0, 1.0); glVertex3f(-lx,  ly, -lz) ' Point 4 (Left)
	glEnd() ' Done Drawing Quads
	
EndFunction

Function processhits:String(hits:Int,sb:Int Ptr)

	Local low:Float
	Local ply:Int=Var (sb+3)

	low=Var (sb+1)

	For Local x=0 To hits-1
		Local p=Var sb
		sb:+1
		Local d1:Float=Var sb
		sb:+1
		Local d2:Float=Var sb
		sb:+1
		If ((d1+d2)/2) < low Then 
			low=((d1+d2)/2)
			ply=Var sb
		End If
		For Local n=1 To p
			sb:+1
		Next
	Next

	selectedname=ply
	
End Function
It should work in debug mode now :) and clicking on a box will push it away from the camera.

Still, you should not run it in windowed mode, unless you use this fix: http://www.blitzbasic.com/Community/posts.php?topic=43206 or the view will be twirling like mad.