Jedive ODE Wrapper

Blitz3D Forums/Blitz3D Userlibs/Jedive ODE Wrapper

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.

BUG FIX NOTES: Please Read

I wasn't convinced by the -90 degree rotation solution I suggested so I looked closer at the problem, sure enough it hasn't fixed it properly. Halo's solution doesn't seem to help fix it either.

The dVectorY#()-90 fix appears to correct the rotation of moving objects but it DOESN'T fix the rotation problem, instead it throws everything else out by -90 degrees. This may give Jedive a clue as to what needs tweaking though.

I've recreated the JediveODE Car Demo below with identical settings to the BlitzODE Car Demo to see if this helps show up the incorrect physics. The reason it was so tricky to get working when I converted it was due to a number of problems which may explain the weird rotation issues. Other possible problems have also been highlighted and are as follows:

Accelerate/Reverse - backwards (Z Position reversed?)
Steering Left/Right - backwards
The car 'rolls' when it should 'pitch' and vice-versa. Swapping the pitch and roll in the UpdateGeoms() function partly fixes the issues, it corrects the wheel rotation and roll/pitch - but the roll is backwards so you have to add a minus to correct it (see the UpdateGeoms() function in the demo below).

Jedive, here is the JediveODE Car Demo with the BlitzODE Car Demo settings. It shows all of the errors described above and should work correctly if the problems are identified/fixed within the wrapper. Hopefully it may help you when you get chance to take a look at the wrapper code.
; ###################################################################################################
; #										 JediveODE Car Demo											#
; #									Code by Jim Williams (VIP3R)									#		#
; #						Feel free to use this code, any credit appreciated							#
; ###################################################################################################

AppTitle "JediveODE Car Demo"

Include "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

Const dParamVel2=258
Const dParamFMax2=259

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 ContactGroup=dJointGroupCreate(0)

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

dContactSetMode(dContactSlip1)
dContactSetMu(WorldFriction)

; ### Create car body

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

; ### Create wheels

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

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

; ### Create some objects

SeedRnd MilliSecs()

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

For cylinders=1 To 20
	g.ODEGeom=New ODEGeom
	g\body=dBodyCreate(World)
	dBodySetRotation(g\body,0,0,0)
	dBodySetPosition(g\body,Rnd(-50,50),30,Rnd(-50,50))
	g\geom=dCreateCCylinder(Space,2,3)
	dGeomSetBody(g\geom,g\body)
	g\mesh=CreateCylinder(8)
	ScaleMesh g\mesh,2,3,2
	RotateMesh g\mesh,0,0,0
	PositionMesh g\mesh,0,0,0
	EntityColor g\mesh,Rnd(255),Rnd(255),Rnd(255)
	EntityAlpha g\mesh,1
	EntityShininess g\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

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()

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

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,"Physics Time:"+PhysicsTime
	Text 0,15,"Car Speed:"+Speed
	Text 640,0,"A - Accelerate"
	Text 640,15,"Z - Brake/Reverse"
	Text 640,30,"Arrows - Steering"
	Text 640,45,"Space - Reset Car"
	Text 0,40,"XPos: "+EntityX(CMesh)
	Text 0,60,"YPos: "+EntityY(CMesh)
	Text 0,80,"ZPos: "+EntityZ(CMesh)
	Text 0,120,"Pitch: "+EntityPitch(CMesh)
	Text 0,140,"Yaw: "+EntityYaw(CMesh)
	Text 0,160,"Roll: "+EntityRoll(CMesh)

	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 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

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 g.ODEGeom=Each ODEGeom
	RotateEntity g\mesh,dGeomGetPitch#(g\geom),dGeomGetYaw#(g\geom),dGeomGetRoll#(g\geom)
;	RotateEntity g\mesh,dGeomGetRoll#(g\geom),dGeomGetYaw#(g\geom),-dGeomGetPitch#(g\geom)	; <<< Corrects roll/pitch issue
	PositionEntity g\mesh,dGeomGetPositionX#(g\geom),dGeomGetPositionY#(g\geom),dGeomGetPositionZ#(g\geom)
Next

End Function

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

Also, it would be better to use the Geom functions in the UpdateEntities()/UpdateGeoms() function instead of the Body functions, as this will allow you to build static objects (which don't require a 'body' to be assigned to them).