JV-ODE Physics Thread 11

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

Hmm, I noticed a few problems.

If you examine the x/y/z components during runtime you will see that they don't reflect the angle of the wheels globally, therefore the friction direction will be wrong most of the time. If you drive in circles, what you should see is the x and z components rise and fall depending on the global angle of the wheel.

I've created a quick demo using your code snippet with the following changes...
* Added World Contact / Mu2 / Slip settings (in addition to the geom contact settings)
* Removed the car angle code (not needed)
* Changed the wheel angle to use the yaw value (the hinge2 angle is local and it needs to be global)
* The friction values are exaggerated for testing, I think Mu and Mu2 are mixed up though, this might be because the yaw is perpendicular to the wheel.

I haven't adjusted the slip settings so they might be interfering with the friction (hence the 20000 value).

It seems to be working correctly, but needs much more tweaking and testing with those friction / slip values.

Anyway, here it is...
; ###################################################################################################
; #                                        JV-ODE Car Demo                                          #
; #                                  Code by Jim Williams (VIP3R)                                   #
; #                              Devious Codeworks - Copyright © 2008                               #
; ###################################################################################################

Include "JV-ODE.bb"

AppTitle "JV-ODE Car Demo"

Graphics3D 800,600,0,2

Global CMass#=200.0				; ### Car Mass
Global WMass#=14.0				; ### Wheel Mass

Global WorldERP#=1.0			; ### World Error Correction
Global WorldFriction#=70.0		; ### World Friction

Global Torque#=24.0				; ### Joint Torque
Global SuspensionHS#=0.01		; ### Suspension Hardness/Softness (Higher=Softer - Lower=Harder)

Global Force#=0.0
Global Steer#=0.0

Global Car
Global CGeom
Global CMesh

Global CarStartY=20

Global x_component#=0.0	; <<<< Here
Global y_component#=0.0	; <<<< Here
Global z_component#=0.0	; <<<< Here

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

Type ODEGeom
	Field body
	Field geom
	Field mesh
End Type

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

; ### Setup ODE

dInitODE()

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

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

dContactSetMode(dContactFDir1+dContactSlip1)	; <<<< Here
dContactSetMu(WorldFriction)
dContactSetMu2(1.0)	; <<<< Here
dContactSetFDir1(1.0,1.0,1.0)	; <<<< Here
dContactSetSlip1(0.005)	; <<<< Here
dContactSetSlip2(0.005)	; <<<< Here

; ### Create Car Body

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

; ### Create Wheels

For count=1 To 4
	ode.ODEGeom=New ODEGeom
	ode\body=dBodyCreate(World)
	Wheel(count)=ode\body
	dBodySetPosition(ode\body,0,0,0)
	dBodySetRotation(ode\body,0,0,90)
	mass=dMassCreate()
	dMassSetSphereTotal(mass,WMass,0.7)
	dBodySetMass(ode\body,mass)
	dMassDestroy(mass)
	ode\geom=dCreateSphere(Space,0.7)
	WGeom(count)=ode\geom
	dGeomSetBody(ode\geom,ode\body)
	ode\mesh=CreateCylinder()
	ScaleMesh ode\mesh,0.7,0.25,0.7
	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 Objects

SeedRnd MilliSecs()

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

For capsules=1 To 20
	ode.ODEGeom=New ODEGeom
	ode\body=dBodyCreate(World)
	dBodySetPosition(ode\body,Rand(-100,100),30,Rand(-100,100))
	dBodySetRotation(ode\body,90,0,0)
	ode\geom=dCreateCapsule(Space,1,8)
	dGeomSetBody(ode\geom,ode\body)
	ode\mesh=CreateCylinder()
	ScaleMesh ode\mesh,1,5,1
	RotateMesh ode\mesh,90,0,0	; ### Align Blitz3D Cylinder To ODE Capsule
	EntityColor ode\mesh,Rand(0,255),Rand(0,255),Rand(0,255)
	EntityShininess ode\mesh,0.7
Next

; ### Create Light

Global Light=CreateLight()
RotateEntity Light,50,-50,0
LightColor Light,255,255,255
AmbientLight 130,130,130

; ### Create Camera

Global CameraPivot=CreatePivot()

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

; ### Create Plane

dCreatePlane(Space,0,1,0,0)

Global Plane=CreatePlane()
EntityAlpha Plane,0.8

EntityTexture Plane,PlaneTexture()

CreateMirror()

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

; ### Blitz3D Static Object (White)

Global Blitz3DObject=CreateCube()
ScaleMesh Blitz3DObject,1,4,20
PositionEntity Blitz3DObject,10,5,40
RotateEntity Blitz3DObject,-10,8,4
EntityColor Blitz3DObject,255,255,255

; ### ODE Static Object (Blue)

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

; ### ODE Static Object (Red)

ode.ODEGeom=New ODEGeom
ode\geom=dCreateBox(Space,18,0.2,40)
dGeomSetPosition(ode\geom,-20,4.9,40)
dGeomSetRotation(ode\geom,-14,0,0)
ode\mesh=CreateCube()
ScaleMesh ode\mesh,9,0.1,20
EntityColor ode\mesh,200,0,100

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

SetupCar()

While Not KeyHit(1)

	UpdateKeys()

	UpdateCar()

	UpdateGeoms()

	PTime=MilliSecs()

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

	PhysicsTime#=MilliSecs()-PTime

	UpdateCam()

	RenderWorld

	Text 0,0,"JV-ODE Version "+dGetVersion()
	Text 0,15,"Physics Time:"+PhysicsTime
	Text 0,50,"Force:"+Force
	Text 0,65,"Torque:"+Torque
	Text 640,0,"A - Accelerate"
	Text 640,15,"Z - Brake/Reverse"
	Text 640,30,"Arrows - Steering"
	Text 640,45,"Space - Reset Car"

	Text 0,100,"X:"+x_component#
	Text 0,120,"Y:"+y_component#
	Text 0,140,"Z:"+z_component#

	Flip 1

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

	dGeomContactSetMode(WGeom(count),dContactFDir1+dContactSlip1)	; <<<< Here
Next

End Function

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

Function UpdateKeys()

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

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

If KeyDown(30)=0 And KeyDown(44)=0 Then Force=Force*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.0
	End If

If KeyHit(57)=1
	Force=0.0
	dBodySetRotation(Car,dGeomGetPitch(CGeom),dGeomGetYaw(CGeom),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,Force)
	dJointSetHinge2Param(Joint(count),dParamFMax2,Torque)
Next

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

; Here >>>>
For count=1 To 4
	wheel_angle#=dGeomGetYaw(WGeom(count))
	x_component#=Sin(wheel_angle#)*-1.0 
	y_component#=0.0
	z_component#=Sin(wheel_angle#+90.0)

	dGeomContactSetMu(WGeom(count),30)
	dGeomContactSetMu2(WGeom(count),20000)

	dGeomContactSetFDir1(WGeom(count),x_component#,y_component#,z_component#)

	dGeomContactSetSlip1(WGeom(count),0.005)

	spin#=dJointGetHinge2Angle2Rate(joint(count))
	dGeomContactSetSlip2(WGeom(count),0.005+(Abs(spin#)/100))
Next
; <<<< Here

End Function

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

Function UpdateCam()

PositionEntity Camera,0,3,-12

PivotX#=Cos(EntityYaw(CMesh)-90)+EntityX(CMesh)
PivotY#=EntityY(CMesh)
PivotZ#=Sin(EntityYaw(CMesh)-90)+EntityZ(CMesh)

PositionEntity CameraPivot,PivotX,PivotY,PivotZ

PointEntity CameraPivot,CMesh

End Function

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

Function UpdateGeoms()

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

End Function

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


I've marked the new areas of code with the tag '<<<< Here'.

Hope this helps, let me know if you need anymore info ;)