Jedive ODE Wrapper

Blitz3D Forums/Blitz3D Userlibs/Jedive ODE Wrapper

FIXED ROTATION/POSITIONING & ORIENTATION!!! :)

Well, my head hurts a lot but I've managed to pinpoint and correct the errors with the rotation/positioning and orientation issues. I've also managed to increase stability in the physics.

As I suspected the (Euler<>Quaternion) conversions were not at fault as far as I can tell.

The problems were in the following areas:
maxcontacts (changed internal integer for stability)
dBodySetRotation (corrected yaw)
dBodyGetYaw (corrected yaw)
dGeomSetRotation (corrected yaw)
dGeomGetYaw (corrected yaw)
dCreateBox (corrected orientation)

My main objective was to use the same orientation for ODE entity positioning/rotation as Blitz itself uses. So if you create a cube in Blitz, and then create another using the ODE wrapper they would have identical orientation properties. It's worth noting that Arkons wrapper does NOT have the same orientation as Blitz's entities, which leads to confusion when creating and positioning ODE/non-ODE objects.

The reason it was so confusing to figure out what was wrong with the wrapper, was due to the fact I was using a Blitz cube and an ODE box to figure out alignment issues. As soon as I realised the ODE box was being setup incorrectly, it was a simple process to correct everything.

With the fixed ODE.dll you can now create objects and expect them to be orientated as they would be using Blitz's own entities - and of course everything rotates/collides correctly now.

I've tested this on the (corrected) Car Demo and it works fine.

I'll send Jedive the new source with all of the corrections so that he can add it to the next update.

In the mean time, try this car demo code below, it contains all of the corrections (via blitz) so that you can test it with the current dll. The only thing it doesn't correct is the stability (which is internal to the dll).
; ###################################################################################################
; #										 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
FIXdBodySetRotation(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=FIXdCreateBox(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
	FIXdBodySetRotation(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

; ### Create some objects

SeedRnd MilliSecs()

For balls=1 To 20
	g.ODEGeom=New ODEGeom
	g\body=dBodyCreate(World)
	FIXdBodySetRotation(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)
	FIXdBodySetRotation(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()

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

; ### BLITZ TEST OBJECT (White)

blitzobject=CreateCube()
ScaleMesh blitzobject,1,4,20
RotateMesh blitzobject,-10,8,4
PositionMesh blitzobject,10,5,10

EntityColor blitzobject,255,255,255
EntityAlpha blitzobject,1

; ### ODE STATIC TEST OBJECT (Blue)

g.ODEGeom=New ODEGeom
g\geom=FIXdCreateBox(Space,2,8,40)
FIXdGeomSetRotation(g\geom,-10,8,4)
dGeomSetPosition(g\geom,20,5,10)
g\mesh=CreateCube()
ScaleMesh g\mesh,1,4,20
RotateMesh g\mesh,0,0,0
PositionMesh g\mesh,0,0,0

EntityColor g\mesh,0,100,200
EntityAlpha g\mesh,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,"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"

	Flip

Wend

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

End

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

Function SetupCar()

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)

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
	FIXdBodySetRotation(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 FIXdBodySetRotation(body,rx,ry,rz)

dBodySetRotation(body,rx,ry+90,rz)

End Function

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

Function FIXdGeomSetRotation(geom,rx,ry,rz)

dGeomSetRotation(geom,rx,ry+90,rz)

End Function

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

Function FIXdCreateBox(sp,w,h,d)

Return dCreateBox(sp,d,h,w)

End Function

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

Function UpdateGeoms()

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

End Function

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

The white rectangle is a standard Blitz entity and the blue one is an ODE entity, as you can see they are correctly orientated to each other.

Btw, the ODE box dimensions still need to be double that of the Blitz entity dimensions, this is easily fixed within the wrapper too. I'll check the dimensions of the ODE objects against Blitz entities next and see if I can correct those before I send Jedive the updated source.

Let me know if you find any problems.