JV-ODE Physics Thread 3

Blitz3D Forums/Blitz3D Userlibs/JV-ODE Physics Thread 3

JV-ODE Version 1.06 Released

Please check your inbox :)

New functions have been added to get detailed collision information of sub-space geoms when using multiple spaces. The existing detailed collision functions still work the same way and are used for single space simulations. To retrieve detailed collision information for multiple space simulations, use both the existing functions and the new sub-space functions.

Here is a modified car demo to demonstrate the new functions in use...
; ###################################################################################################
; #										  JV-ODE Car Demo											#
; #									Code by Jim Williams (VIP3R)									#		#
; #						Feel free to use this code, any credit appreciated							#
; ###################################################################################################

AppTitle "JV-ODE Car Demo"

Include "JV-ODE.bb"

Graphics3D 800,600,0,2

Global CMass#=200			; ### Car Mass
Global WMass#=8				; ### Wheel Mass

Global WorldERP#=1			; ### World Error Correction
Global WorldFriction#=64	; ### World Friction
Global HingeTorque#=24		; ### Hinge Torque
Global SuspensionHS#=0.01	; ### Hinge Suspension Hardness/Softness (Higher=Softer - Lower=Harder)

Global Speed#=0
Global Steer#=0

Global Car
Global CGeom
Global CMesh

Global CarStartY=20

Global SpaceInfo=0

Global Pointer

Global RampGeom
Global BlueGeom
Global PlaneGeom

Global GeomX$
Global GeomY$
Global GeomZ$
Global GeomGeom$
Global GeomID$
Global GeomFlash

Global SubGeomX$
Global SubGeomY$
Global SubGeomZ$
Global SubGeomGeom$
Global SubGeomID$

Dim WGeomID$(4)
Dim SubWGeomID$(4)

Dim SphereGeom(20)
Dim CCylinderGeom(20)

Dim Wheel(4)
Dim WGeom(4)
Dim Joint(4)

Type ODEGeom
	Field body
	Field geom
	Field mesh
End Type

; ###################################################################################################

; ### Setup ODE

Global World=dWorldCreate()
Global Space=dHashSpaceCreate(0)
Global CarSpace=dHashSpaceCreate(Space)
Global ObjSpace=dHashSpaceCreate(Space)
Global ContactGroup=dJointGroupCreate(0)

dWorldSetAutoDisableFlag(World,1)
dWorldSetGravity(World,0,-0.98,0)
dWorldSetERP(World,WorldERP)

dContactSetMode(dContactSlip1)
dContactSetMu(WorldFriction)

; ### Create car body

ode.ODEGeom=New ODEGeom
ode\body=dBodyCreate(World)
Car=ode\body
dBodySetRotation(ode\body,0,0,0)
dBodySetPosition(ode\body,0,CarStartY,0)
mass=dMassCreate()
dMassSetBox(mass,1,3,1,5)
dMassSetBoxTotal(mass,CMass,3,1,5)
dMassTranslate(mass,0,-1,0)
dBodySetMass(ode\body,mass)
dMassDestroy(mass)
ode\geom=dCreateBox(CarSpace,3,1,5)
CGeom=ode\geom
dGeomSetBody(ode\geom,ode\body)
ode\mesh=CreateCube()
CMesh=ode\mesh
ScaleMesh ode\mesh,1.5,0.5,2.5
RotateMesh ode\mesh,0,0,0
PositionMesh ode\mesh,0,0,0
EntityColor ode\mesh,40,80,255
EntityAlpha ode\mesh,0.5

; ### Create wheels

For count=1 To 4
	ode.ODEGeom=New ODEGeom
	ode\body=dBodyCreate(World)
	Wheel(count)=ode\body
	dBodySetRotation(ode\body,0,0,0)
	dBodySetPosition(ode\body,0,0,0)
	mass=dMassCreate()
	dMassSetSphere(mass,1,0.7)
	dMassSetSphereTotal(mass,WMass,0.7)
	dBodySetMass(ode\body,mass)
	dMassDestroy(mass)
	ode\geom=dCreateSphere(CarSpace,0.7)
	WGeom(count)=ode\geom
	dGeomSetBody(ode\geom,ode\body)
	ode\mesh=CreateCylinder(8)
	ScaleMesh ode\mesh,0.7,0.25,0.7
	RotateMesh ode\mesh,0,0,90
	PositionMesh ode\mesh,0,0,0
	EntityColor ode\mesh,255,255,255
Next

dBodySetPosition(Wheel(1),-2,CarStartY-0.5,+2)
dBodySetPosition(Wheel(2),+2,CarStartY-0.5,+2)
dBodySetPosition(Wheel(3),-2,CarStartY-0.5,-2)
dBodySetPosition(Wheel(4),+2,CarStartY-0.5,-2)

; ### Create some objects

SeedRnd MilliSecs()

For spheres=1 To 20
	ode.ODEGeom=New ODEGeom
	ode\body=dBodyCreate(World)
	dBodySetRotation(ode\body,0,0,0)
	dBodySetPosition(ode\body,Rnd(-100,100),30,Rnd(-100,100))
	ode\geom=dCreateSphere(Space,4)
	SphereGeom(spheres)=ode\geom
	dGeomSetBody(ode\geom,ode\body)
	ode\mesh=CreateSphere()
	ScaleMesh ode\mesh,4,4,4
	RotateMesh ode\mesh,0,0,0
	PositionMesh ode\mesh,0,0,0
	EntityColor ode\mesh,Rnd(255),Rnd(255),Rnd(255)
	EntityAlpha ode\mesh,1
	EntityShininess ode\mesh,0.7
Next

For cylinders=1 To 20
	ode.ODEGeom=New ODEGeom
	ode\body=dBodyCreate(World)
	dBodySetRotation(ode\body,90,0,0)
	dBodySetPosition(ode\body,Rnd(-100,100),30,Rnd(-100,100))
	ode\geom=dCreateCCylinder(ObjSpace,1,8)
	CCylinderGeom(cylinders)=ode\geom
	dGeomSetBody(ode\geom,ode\body)
	ode\mesh=CreateCylinder(8)
	ScaleMesh ode\mesh,1,5,1
	RotateMesh ode\mesh,90,0,0	; <<< Mesh X-Axis must be rotated 90 degrees to fix cylinder alignment
	PositionMesh ode\mesh,0,0,0
	EntityColor ode\mesh,Rnd(255),Rnd(255),Rnd(255)
	EntityAlpha ode\mesh,1
	EntityShininess ode\mesh,0.7
Next

; ### Create light

Global Light=CreateLight()

RotateEntity Light,45,-90,0
LightColor Light,255,255,255
AmbientLight 130,130,130

; ### Create camera

Global CameraPivot=CreatePivot(CMesh)
PositionEntity CameraPivot,0,2,-7

Global Camera=CreateCamera()
CameraClsColor Camera,0,0,0
CameraRange Camera,1,1000

; ### Create plane

PlaneGeom=dCreatePlane(Space,0,1,0,0)

Plane=CreatePlane()

EntityAlpha Plane,0.8

PlaneTexture=CreateTexture(128,128,9)

ClsColor 0,200,80
Cls

Color 255,255,255

Rect 0,0,64,64,1
Rect 64,64,64,64,1

CopyRect 0,0,128,128,0,0,BackBuffer(),TextureBuffer(PlaneTexture)
ScaleTexture PlaneTexture,20,20
EntityTexture Plane,PlaneTexture,0,0

Mirror=CreateMirror()

; ###################################################################################################

; ### ODE STATIC OBJECT (Blue)

ode.ODEGeom=New ODEGeom
ode\geom=dCreateBox(Space,2,8,40)
dGeomSetRotation(ode\geom,-10,8,4)
dGeomSetPosition(ode\geom,20,5,40)
BlueGeom=ode\geom
ode\mesh=CreateCube()
ScaleMesh ode\mesh,1,4,20
RotateMesh ode\mesh,0,0,0
PositionMesh ode\mesh,0,0,0

EntityColor ode\mesh,0,100,200
EntityAlpha ode\mesh,1

; ### ODE STATIC OBJECT (Red)

ode.ODEGeom=New ODEGeom
ode\geom=dCreateBox(ObjSpace,18,0.2,40)
dGeomSetRotation(ode\geom,-14,0,0)
dGeomSetPosition(ode\geom,-20,4.9,40)
RampGeom=ode\geom
ode\mesh=CreateCube()
ScaleMesh ode\mesh,9,0.1,20
RotateMesh ode\mesh,0,0,0
PositionMesh ode\mesh,0,0,0

EntityColor ode\mesh,200,0,100
EntityAlpha ode\mesh,1

; ### BLITZ COLLISION OBJECT (Yellow)

Pointer=CreateSphere()
ScaleMesh Pointer,0.5,0.5,0.5

EntityColor Pointer,255,255,100
EntityAlpha Pointer,1

; ###################################################################################################

SetupCar()

While Not KeyHit(1)

	UpdateKeys()

	PTime=MilliSecs()

	UpdateCar()

	UpdateGeoms()

	dSpaceCollide(Space,World,ContactGroup)
	dWorldQuickStep(World,0.1)
	dJointGroupEmpty(ContactGroup)

	PhysicsTime#=MilliSecs()-PTime

	UpdateCam()

	UpdateWorld

	RenderWorld

	Text 0,0,"JV-ODE Version "+dGetVersion()
	Text 0,15,"Physics Time:"+PhysicsTime
	Text 0,30,"Car Speed:"+Speed

	Text 220,0,"F1 - Toggle Collision Info (Space - SubSpace)"

	If SpaceInfo=0
		ShowCollisionInfo()
		Else
		ShowSubCollisionInfo()
		End If

	Text 0,480,"Top Level Space (Space):"
	Text 0,495,"Ground Plane - Blue Block - Spheres"

	Text 0,520,"Sub-Space (CarSpace):"
	Text 0,535,"Car Body - Car Wheels"

	Text 0,560,"Sub-Space (ObjSpace):"
	Text 0,575,"Red Ramp - CCylinders"

	Text 640,0,"A - Accelerate"
	Text 640,15,"Z - Brake/Reverse"
	Text 640,30,"Arrows - Steering"
	Text 640,45,"Space - Reset Car"

	Flip

Wend

dJointGroupDestroy(ContactGroup)
dSpaceDestroy(Space)
dWorldDestroy(World)
dCloseODE()

End

; ###################################################################################################

Function SetupCar()

For count=1 To 4
	Joint(count)=dJointCreateHinge2(World,0)
	dJointAttach(Joint(count),Car,Wheel(count))
	dJointSetHinge2Anchor(Joint(count),dBodyGetPositionX(Wheel(count)),dBodyGetPositionY(Wheel(count)),dBodyGetPositionZ(Wheel(count)))
	dJointSetHinge2Axis1(Joint(count),0,1,0)
	dJointSetHinge2Axis2(Joint(count),-1,0,0)
	dJointSetHinge2Param(Joint(count),dParamSuspensionERP,0.8)
	dJointSetHinge2Param(Joint(count),dParamSuspensionCFM,SuspensionHS)
	If count>2
		dJointSetHinge2Param(Joint(count),dParamLoStop,0)
		dJointSetHinge2Param(Joint(count),dParamHiStop,0)
		End If
Next

Speed=0

End Function

; ###################################################################################################

Function ShowCollisionInfo()

If dGeomCountCollisions(CGeom)>0
	GeomX$=dGeomCollisionX#(CGeom,1)
	GeomY$=dGeomCollisionY#(CGeom,1)
	GeomZ$=dGeomCollisionZ#(CGeom,1)
	GeomGeom$=dGeomCollisionGeom(CGeom,1)
	If dGeomCollisionGeom(CGeom,1)=PlaneGeom Then GeomID$=" - Ground Plane"
	If dGeomCollisionGeom(CGeom,1)=RampGeom Then GeomID$=" - Red Ramp"
	If dGeomCollisionGeom(CGeom,1)=BlueGeom Then GeomID$=" - Blue Block"
	For count=1 To 20
		If dGeomCollisionGeom(CGeom,1)=SphereGeom(count) Then GeomID$=" - Sphere "+count
		If dGeomCollisionGeom(CGeom,1)=CCylinderGeom(count) Then GeomID$=" - Capped Cylinder "+count
	Next
	PositionEntity Pointer,dGeomCollisionX#(CGeom,1),dGeomCollisionY#(CGeom,1),dGeomCollisionZ#(CGeom,1)
	End If

For count=1 To 4
	WGeomID$(count)=""
	If dGeomCountCollisions(WGeom(count))>0
		If dGeomCollisionGeom(WGeom(count),1)=PlaneGeom Then WGeomID$(count)=" - Ground Plane"
		If dGeomCollisionGeom(WGeom(count),1)=RampGeom Then WGeomID$(count)=" - Red Ramp"
		If dGeomCollisionGeom(WGeom(count),1)=BlueGeom Then WGeomID$(count)=" - Blue Block"
		For count2=1 To 20
			If dGeomCollisionGeom(WGeom(count),1)=SphereGeom(count2) Then WGeomID$(count)=" - Sphere "+count2
			If dGeomCollisionGeom(WGeom(count),1)=CCylinderGeom(count2) Then WGeomID$(count)=" - Capped Cylinder "+count2
		Next
		End If
Next

GeomFlash=GeomFlash+1
If GeomFlash>100 Then GeomFlash=0
If GeomFlash<30 Then EntityAlpha Pointer,GeomFlash*0.1
If GeomFlash>70 Then EntityAlpha Pointer,(100-GeomFlash)*0.1
ScaleEntity Pointer,0.5+(GeomFlash*0.01),0.5+(GeomFlash*0.01),0.5+(GeomFlash*0.01)
EntityColor Pointer,255,255-(GeomFlash*2),100

Text 0,80,"Car Body Collision Info (CGeom) - Top Level Space"
Text 0,100,"GeomCollisionX:"+GeomX$
Text 0,115,"GeomCollisionY:"+GeomY$
Text 0,130,"GeomCollisionZ:"+GeomZ$
Text 0,150,"GeomCollisionGeom:"+GeomGeom$+GeomID$

Text 0,295,"Car Wheel Collision Info (WGeom) - Top Level Space"
Text 0,315,"Wheel 1 (F/L)"+WGeomID$(1)
Text 0,330,"Wheel 2 (F/R)"+WGeomID$(2)
Text 0,345,"Wheel 3 (R/L)"+WGeomID$(3)
Text 0,360,"Wheel 4 (R/R)"+WGeomID$(4)

End Function

; ###################################################################################################

Function ShowSubCollisionInfo()

If dSubGeomCountCollisions(CGeom)>0
	SubGeomX$=dSubGeomCollisionX#(CGeom,1)
	SubGeomY$=dSubGeomCollisionY#(CGeom,1)
	SubGeomZ$=dSubGeomCollisionZ#(CGeom,1)
	SubGeomGeom$=dSubGeomCollisionGeom(CGeom,1)
	If dSubGeomCollisionGeom(CGeom,1)=PlaneGeom Then SubGeomID$=" - Ground Plane"
	If dSubGeomCollisionGeom(CGeom,1)=RampGeom Then SubGeomID$=" - Red Ramp"
	If dSubGeomCollisionGeom(CGeom,1)=BlueGeom Then SubGeomID$=" - Blue Block"
	For count=1 To 20
		If dSubGeomCollisionGeom(CGeom,1)=SphereGeom(count) Then SubGeomID$=" - Sphere "+count
		If dSubGeomCollisionGeom(CGeom,1)=CCylinderGeom(count) Then SubGeomID$=" - Capped Cylinder "+count
	Next
	PositionEntity Pointer,dSubGeomCollisionX#(CGeom,1),dSubGeomCollisionY#(CGeom,1),dSubGeomCollisionZ#(CGeom,1)
	End If

For count=1 To 4
	SubWGeomID$(count)=""
	If dSubGeomCountCollisions(WGeom(count))>0
		If dSubGeomCollisionGeom(WGeom(count),1)=PlaneGeom Then SubWGeomID$(count)=" - Ground Plane"
		If dSubGeomCollisionGeom(WGeom(count),1)=RampGeom Then SubWGeomID$(count)=" - Red Ramp"
		If dSubGeomCollisionGeom(WGeom(count),1)=BlueGeom Then SubWGeomID$(count)=" - Blue Block"
		For count2=1 To 20
			If dSubGeomCollisionGeom(WGeom(count),1)=SphereGeom(count2) Then SubWGeomID$(count)=" - Sphere "+count2
			If dSubGeomCollisionGeom(WGeom(count),1)=CCylinderGeom(count2) Then SubWGeomID$(count)=" - Capped Cylinder "+count2
		Next
		End If
Next

GeomFlash=GeomFlash+1
If GeomFlash>100 Then GeomFlash=0
If GeomFlash<30 Then EntityAlpha Pointer,GeomFlash*0.1
If GeomFlash>70 Then EntityAlpha Pointer,(100-GeomFlash)*0.1
ScaleEntity Pointer,0.5+(GeomFlash*0.01),0.5+(GeomFlash*0.01),0.5+(GeomFlash*0.01)
EntityColor Pointer,255,255-(GeomFlash*2),100

Text 0,80,"Car Body Collision Info (CGeom) - Sub Space"
Text 0,100,"SubGeomCollisionX:"+SubGeomX$
Text 0,115,"SubGeomCollisionY:"+SubGeomY$
Text 0,130,"SubGeomCollisionZ:"+SubGeomZ$
Text 0,150,"SubGeomCollisionGeom:"+SubGeomGeom$+SubGeomID$

Text 0,295,"Car Wheel Collision Info (WGeom) - Sub Space"
Text 0,315,"Wheel 1 (F/L)"+SubWGeomID$(1)
Text 0,330,"Wheel 2 (F/R)"+SubWGeomID$(2)
Text 0,345,"Wheel 3 (R/L)"+SubWGeomID$(3)
Text 0,360,"Wheel 4 (R/R)"+SubWGeomID$(4)

End Function

; ###################################################################################################

Function UpdateKeys()

If KeyDown(30)=1
	Speed=Speed+0.08
	If Speed>30 Then Speed=30
	End If

If KeyDown(44)=1
	Speed=Speed-0.1
	If Speed<-10 Then Speed=-10
	If Speed>0 Then Speed=Speed*0.97
	End If

If KeyDown(30)=0 And KeyDown(44)=0 Then Speed=Speed*0.99

If KeyDown(203)=1 Or KeyDown(205)=1
	If KeyDown(203)=1
		Steer=0.5
		Else
		Steer=-0.5
		End If
	Else
	Steer=0
	End If

If KeyHit(57)=1
	Speed=0
	dBodySetRotation(Car,0,0,0)
	End If

If KeyHit(59) Then SpaceInfo=Not SpaceInfo

End Function

; ###################################################################################################

Function UpdateCar()

For count=1 To 4
	dBodyEnable(Wheel(count))
Next

dBodyEnable(Car)

For count=1 To 4
	dJointSetHinge2Param(Joint(count),dParamVel2,Speed)
	dJointSetHinge2Param(Joint(count),dParamFMax2,HingeTorque)
Next

For count=1 To 2
	angle#=Steer-dJointGetHinge2Angle1(Joint(count))
	dJointSetHinge2Param(Joint(count),dParamVel,angle)
	dJointSetHinge2Param(Joint(count),dParamFMax,400)
Next

End Function

; ###################################################################################################

Function UpdateCam()

PositionEntity CameraPivot,0,3,-12

camx#=EntityX(CameraPivot,1)-EntityX(Camera)
camy#=EntityY(CameraPivot,1)-EntityY(Camera)
camz#=EntityZ(CameraPivot,1)-EntityZ(Camera)

TranslateEntity Camera,camx*0.5,camy*0.5,camz*0.5

PointEntity Camera,CMesh

End Function

; ###################################################################################################

Function UpdateGeoms()

For ode.ODEGeom=Each ODEGeom
	RotateEntity ode\mesh,dGeomGetPitch#(ode\geom),dGeomGetYaw#(ode\geom),dGeomGetRoll#(ode\geom)
	PositionEntity ode\mesh,dGeomGetPositionX#(ode\geom),dGeomGetPositionY#(ode\geom),dGeomGetPositionZ#(ode\geom)
Next

End Function

; ###################################################################################################

New joint parameters have also been added to the include file.

Let me know if you have any questions regarding this update.

Have fun :)