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...
I've marked the new areas of code with the tag '<<<< Here'.
Hope this helps, let me know if you need anymore info ;)
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 ;)