Ok, here it is...(messy & badly commented, the Sweenie way!)
Const FPS=90
Type vector
Field x#
Field y#
Field z#
End Type
Global CProd.vector=New vector
Type csys
Field cx#,cy#,cz#
Field mx#,my#,sps
End Type
Graphics3D 800,600,0,2
SetBuffer BackBuffer()
camera = CreateCamera()
PositionEntity camera,10,8,-5
WireFrame False
TOKSIM_CreateSimulator(0,-9.0,0)
TOKSIM_SetMaterial 0,0.0,0.6
ColBank=CreateBank(104*10)
TOKSIM_SetCInfoBank ColBank
TOKSIM_SetCollisionResponse -1,1,3 ; Impulse & Feedback
TOKSIM_SetCollisionResponse -1,2,0 ; No Impulse Or Feedback
tex = LoadTexture("track.bmp")
Terrain = LoadMesh("track.3ds")
ScaleMesh Terrain,25.0,25.0,25.0
RotateMesh Terrain,-90,0,0
EntityTexture terrain,tex
MakeTokCollider(Terrain)
SeedRnd MilliSecs()
Global Body_Mesh = LoadMesh("truck_body.b3d")
ScaleMesh Body_Mesh,0.3,0.3,0.3
PositionMesh Body_Mesh,0.0,-2.1,0.0
RotateMesh Body_Mesh,0,180,0
Global Body_RB = TOKRB_Create()
TOKRB_AddBox Body_RB,2.0,1.0,3.0
TOKRB_SetPosition Body_RB,0,5,0
TOKRB_SetMass Body_RB,1.0
TOKRB_SetBoxInertiaTensor Body_RB,2.0,1.0,3.0,1.0
ExtraWeight = TOKRB_Create()
TOKRB_SetCollisionID ExtraWeight,2
TOKRB_SetMass ExtraWeight,0.4
TOKRB_SetSphereInertiaTensor ExtraWeight,0.5,0.4
TOKRB_SetPosition ExtraWeight,0,5,1.5
ConnJoint = TOKJOINT_Create(2,ExtraWeight,Body_RB)
TOKJOINT_SetType ConnJoint,1
TOKJOINT_SetPositionAndRotationWorld ConnJoint,0,5.0,1.5,0,0,0
TOKJOINT_Enable ConnJoint,True
Global RR_Spr_RB = TOKRB_Create()
TOKRB_AddSphere RR_Spr_RB,1.0
TOKRB_SetPosition RR_Spr_RB,1.2,3.0,-1.50
TOKRB_SetMass RR_Spr_RB,1.0
TOKRB_SetSphereInertiaTensor RR_Spr_RB,1.0,1.0
TOKRB_SetCollisionID RR_Spr_RB,1
RR_SprJoint = TOKJOINT_Create(2,RR_Spr_RB,Body_RB)
TOKJOINT_SetType RR_SprJoint,4 ; Slidejoint
TOKJOINT_SetPositionAndRotationWorld RR_SprJoint,1.2,3.0,-1.50,0,0,0
TOKJOINT_Enable RR_SprJoint,True
Global RL_Spr_RB = TOKRB_Create()
TOKRB_AddSphere RL_Spr_RB,1.0
TOKRB_SetPosition RL_Spr_RB,-1.2,3.0,-1.5
TOKRB_SetMass RL_Spr_RB,1.0
TOKRB_SetSphereInertiaTensor RL_Spr_RB,1.0,1.0
TOKRB_SetCollisionID RL_Spr_RB,1
RL_SprJoint = TOKJOINT_Create(2,RL_Spr_RB,Body_RB)
TOKJOINT_SetType RL_SprJoint,4 ; Slidejoint
TOKJOINT_SetPositionAndRotationWorld RL_SprJoint,-1.2,3.0,-1.5,0,0,0
TOKJOINT_Enable RL_SprJoint,True
Global FR_Spr_RB = TOKRB_Create()
TOKRB_AddSphere FR_Spr_RB,1.0
TOKRB_SetPosition FR_Spr_RB,1.2,3.0,1.65
TOKRB_SetMass FR_Spr_RB,1.0
TOKRB_SetSphereInertiaTensor FR_Spr_RB,1.0,1.0
TOKRB_SetCollisionID FR_Spr_RB,1
FR_SprJoint = TOKJOINT_Create(2,FR_Spr_RB,Body_RB)
TOKJOINT_SetType FR_SprJoint,4 ; Slidejoint
TOKJOINT_SetPositionAndRotationWorld FR_SprJoint,1.2,3.0,1.65,0,0,0
TOKJOINT_Enable FR_SprJoint,True
Global FL_Spr_RB = TOKRB_Create()
TOKRB_AddSphere FL_Spr_RB,1.0
TOKRB_SetPosition FL_Spr_RB,-1.2,3.0,1.65
TOKRB_SetMass FL_Spr_RB,1.0
TOKRB_SetSphereInertiaTensor FL_Spr_RB,1.0,1.0
TOKRB_SetCollisionID FL_Spr_RB,1
FL_SprJoint = TOKJOINT_Create(2,FL_Spr_RB,Body_RB)
TOKJOINT_SetType FL_SprJoint,4 ; Slidejoint
TOKJOINT_SetPositionAndRotationWorld FL_SprJoint,-1.2,3.0,1.65,0,0,0
TOKJOINT_Enable FL_SprJoint,True
FR_Wheel=LoadMesh("truck_wheel.b3d")
ScaleMesh FR_Wheel,0.3,0.3,0.3
FL_Wheel=LoadMesh("truck_wheel.b3d")
ScaleMesh FL_Wheel,0.3,0.3,0.3
RR_Wheel=LoadMesh("truck_wheel.b3d")
ScaleMesh RR_Wheel,0.3,0.3,0.3
RL_Wheel=LoadMesh("truck_wheel.b3d")
ScaleMesh RL_Wheel,0.3,0.3,0.3
CamPoint = TOKRB_Create()
TOKRB_SetMass CamPoint,1.0
TOKRB_SetSphereInertiaTensor FR_Spr_RB,1.0,1.0
TOKRB_SetLinearDamping CamPoint,0.01
Centerpivot = CreatePivot()
CamTargetPivot=CreatePivot()
Global speed#=0
GripFactor#=0.2
light=CreateLight()
LightColor light,128,128,128
PositionEntity light,255,255,-255
PointEntity light,Centerpivot
period=1000/FPS
time=MilliSecs()-period
Global timestep#=1.5/FPS
; MainLoop
While Not KeyHit(1)
Repeat
elapsed=MilliSecs()-time
Until elapsed
ticks=elapsed/period
tween#=Float(elapsed Mod period)/Float(period)
For k=1 To ticks
time=time+period
If k=ticks Then CaptureWorld
TOKSIM_Advance(1.5/FPS,1)
UpdateWorld
PlaceMesh Body_Mesh,Body_RB
PositionEntity FR_Wheel,TOKRB_GetX#(FR_Spr_RB),TOKRB_GetY#(FR_Spr_RB),TOKRB_GetZ#(FR_Spr_RB)
RotateEntity FR_Wheel,EntityPitch#(Body_Mesh),EntityYaw#(Body_Mesh),EntityRoll#(Body_Mesh)
TurnEntity FR_Wheel,0,Turn#,0
PositionEntity FL_Wheel,TOKRB_GetX#(FL_Spr_RB),TOKRB_GetY#(FL_Spr_RB),TOKRB_GetZ#(FL_Spr_RB)
RotateEntity FL_Wheel,EntityPitch#(Body_Mesh),EntityYaw#(Body_Mesh),EntityRoll#(Body_Mesh)
TurnEntity FL_Wheel,0,Turn#,0
PositionEntity RR_Wheel,TOKRB_GetX#(RR_Spr_RB),TOKRB_GetY#(RR_Spr_RB),TOKRB_GetZ#(RR_Spr_RB)
RotateEntity RR_Wheel,EntityPitch#(Body_Mesh),EntityYaw#(Body_Mesh),EntityRoll#(Body_Mesh)
PositionEntity RL_Wheel,TOKRB_GetX#(RL_Spr_RB),TOKRB_GetY#(RL_Spr_RB),TOKRB_GetZ#(RL_Spr_RB)
RotateEntity RL_Wheel,EntityPitch#(Body_Mesh),EntityYaw#(Body_Mesh),EntityRoll#(Body_Mesh)
PointEntity camera,Body_Mesh
UpdateSpring 1.2,-0.5,-1.5,RR_Spr_RB,50,6.0,1.1
UpdateSpring -1.2,-0.5,-1.5,RL_Spr_RB,50,6.0,1.1
UpdateSpring 1.2,-0.5,1.65,FR_Spr_RB,50,6.0,1.1
UpdateSpring -1.2,-0.5,1.65,FL_Spr_RB,50,6.0,1.1
RRColl=False
RLColl=False
FRColl=False
FLColl=False
;Check Colliders
If TOKSIM_GetCollisionCount()>0 Then
For c=0 To TOKSIM_GetCollisionCount()-1
If PeekInt(ColBank,0+(c*104))=RR_Spr_RB Then RRColl=True
If PeekInt(ColBank,0+(c*104))=RL_Spr_RB Then RLColl=True
If PeekInt(ColBank,0+(c*104))=FR_Spr_RB Then FRColl=True
If PeekInt(ColBank,0+(c*104))=FL_Spr_RB Then FLColl=True
Next
EndIf
;Driving-force
If KeyDown(200) Then
Acc#=Acc#+1.0
If Acc#>11 Then Acc#=11
ElseIf KeyDown(208) Then
Acc#=Acc#-1.0
If Acc#<6.0 Then Acc#=-6.0
Else
Acc#=Acc#*0.95
If Acc#>-0.01 And Acc#<0.01 Then Acc#=0.0
EndIf
TFormVector 0,0,1,Body_Mesh,0
vx#=TFormedX#()
vy#=TFormedY#()
vz#=TFormedZ#()
If RRColl=True Then
TOKRB_ApplyImpulse RR_Spr_RB,vx#*acc#*timestep#,vy#*acc#*timestep#,vz#*acc#*timestep#
EndIf
If RLColl=True Then
TOKRB_ApplyImpulse RL_Spr_RB,vx#*acc#*timestep#,vy#*acc#*timestep#,vz#*acc#*timestep#
EndIf
CarVelx#=TOKRB_GetVelocityX#(Body_RB)
CarVely#=TOKRB_GetVelocityY#(Body_RB)
CarVelz#=TOKRB_GetVelocityZ#(Body_RB)
TFormNormal 0,0,1,Body_Mesh,0
CarVel#=Abs(DotProduct#(TFormedX#(),TFormedY#(),TFormedZ#(),CarVelx#,CarVely#,CarVelz#))
TurnFactor#=1.0-((1.0/35.0)*CarVel#)
MaxTurn#=27.0
CurrTurn#=MaxTurn#*TurnFactor#
If KeyDown(205) Then
Turn#=Turn#-0.7
If Turn#<-MaxTurn#*TurnFactor# Then Turn#=-MaxTurn#*TurnFactor#
ElseIf KeyDown(203) Then
Turn#=Turn#+0.7
If Turn#>MaxTurn#*TurnFactor# Then Turn#=MaxTurn#*TurnFactor#
Else
Turn=Turn*0.95
If Turn#>-0.1 And Turn#<0.1 Then Turn#=0.0
EndIf
AngVelx#=TOKRB_GetAngularVelocityX#(Body_RB)
AngVely#=TOKRB_GetAngularVelocityY#(Body_RB)
AngVelz#=TOKRB_GetAngularVelocityZ#(Body_RB)
TFormNormal 0,1,0,Body_Mesh,0
AngVel#=Abs(DotProduct#(TFormedX#(),TFormedY#(),TFormedZ#(),AngVelx#,AngVely#,AngVelz#))
If KeyHit(57) Or (AngVel#>1.0 And CarVel#>12.0) Then
Slip=True
EndIf
If Slip=True Then
GripFactor#=0.99
EndIf
If AngVel#<0.7 And Slip=True Then
GripFactor#=0.98
;Slip=False
EndIf
If AngVel#<0.5 And Slip=True Then
GripFactor#=0.97
;Slip=False
EndIf
If AngVel#<0.3 And Slip=True Then
GripFactor#=0.9
Slip=False
EndIf
If KeyHit(16) Then
Slip=True
TOKRB_ApplyTwist Body_RB,0,50,0
EndIf
;Friction
;Find sideslip-speed for RightRearWheel
Vx#=TOKRB_GetVelocityX#(RR_Spr_RB)
Vy#=TOKRB_GetVelocityY#(RR_Spr_RB)
Vz#=TOKRB_GetVelocityZ#(RR_Spr_RB)
TFormVector Vx#,Vy#,Vz#,0,Body_Mesh
TFormVector TFormedX#()*GripFactor#,TFormedY#(),TFormedZ#(),Body_Mesh,0
If RRColl=True Then
TOKRB_SetVelocity RR_Spr_RB,TFormedX#(),TFormedY#(),TFormedZ#()
EndIf
;Find sideslip-speed for LeftRearWheel
Vx#=TOKRB_GetVelocityX#(RL_Spr_RB)
Vy#=TOKRB_GetVelocityY#(RL_Spr_RB)
Vz#=TOKRB_GetVelocityZ#(RL_Spr_RB)
TFormVector Vx#,Vy#,Vz#,0,Body_Mesh
TFormVector TFormedX#()*GripFactor#,TFormedY#(),TFormedZ#(),Body_Mesh,0
If RLColl=True Then
TOKRB_SetVelocity RL_Spr_RB,TFormedX#(),TFormedY#(),TFormedZ#()
EndIf
;Find sideslip-speed for RightFrontWheel
Vx#=TOKRB_GetVelocityX#(FR_Spr_RB)
Vy#=TOKRB_GetVelocityY#(FR_Spr_RB)
Vz#=TOKRB_GetVelocityZ#(FR_Spr_RB)
TFormVector Vx#,Vy#,Vz#,0,FR_Wheel
TFormVector TFormedX#()*GripFactor#,TFormedY#(),TFormedZ#(),FR_Wheel,0
If FRColl=True Then
TOKRB_SetVelocity FR_Spr_RB,TFormedX#(),TFormedY#(),TFormedZ#()
EndIf
;Find sideslip-speed for LeftFrontWheel
Vx#=TOKRB_GetVelocityX#(FL_Spr_RB)
Vy#=TOKRB_GetVelocityY#(FL_Spr_RB)
Vz#=TOKRB_GetVelocityZ#(FL_Spr_RB)
TFormVector Vx#,Vy#,Vz#,0,FL_Wheel
TFormVector TFormedX#()*GripFactor#,TFormedY#(),TFormedZ#(),FL_Wheel,0
If FLColl=True Then
TOKRB_SetVelocity FL_Spr_RB,TFormedX#(),TFormedY#(),TFormedZ#()
EndIf
;Drag
TFormNormal 0,0,-1,Body_Mesh,0
dragConstant# = 1.1
velX#=TOKRB_GetVelocityX#(Body_RB)
velY#=TOKRB_GetVelocityY#(Body_RB)
velZ#=TOKRB_GetVelocityZ#(Body_RB)
dot#=DotProduct#(TFormedX#(),TFormedY#(),TFormedZ#(),velX#,velY#,velZ#)
dragX#=dot#*TFormedX#()*-dragConstant#
dragY#=dot#*TFormedY#()*-dragConstant#
dragZ#=dot#*TFormedZ#()*-dragConstant#
TOKRB_ApplyImpulse Body_RB,dragX#*timestep#,dragY#*timestep#,dragZ#*timestep#
;Camera
PositionEntity camtargetpivot,EntityX#(Body_Mesh),EntityY#(Body_Mesh),EntityZ#(Body_Mesh)
RotateEntity camtargetpivot,EntityPitch#(Body_Mesh),EntityYaw#(Body_Mesh),EntityRoll#(Body_Mesh)
MoveEntity camtargetpivot,0,3,-7
UpdateCamera Camera,camtargetpivot,0.02
Next
RenderWorld tween
Flip False
Wend
TOKSIM_DestroySimulator()
End
Function UpdateSpring(px#,py#,pz#,Wheel_RB,Stiffness#,Damping#,SpringLength#)
;Add spring force
TFormPoint px#,py#,pz#,Body_Mesh,0
wpx#=TFormedX#()
wpy#=TFormedY#()
wpz#=TFormedZ#()
diffX#=wpx# - TOKRB_GetX#(Wheel_RB)
diffY#=wpy# - TOKRB_GetY#(Wheel_RB)
diffZ#=wpz# - TOKRB_GetZ#(Wheel_RB)
diffLen#=Sqr(diffX#*diffX#+diffY#*diffY#+diffZ#*diffZ#)
Displacement#=diffLen#-SpringLength#
nx#=diffx#/diffLen#
ny#=diffy#/diffLen#
nz#=diffz#/diffLen#
fx#=nx#*(Displacement#*Stiffness#)
fy#=ny#*(Displacement#*Stiffness#)
fz#=nz#*(Displacement#*Stiffness#)
;Add damping force
GetPointVel Body_RB,wpx#,wpy#,wpz#
Vx#=CProd\x#-TOKRB_GetVelocityX#(Wheel_RB)
Vy#=CProd\y#-TOKRB_GetVelocityY#(Wheel_RB)
Vz#=CProd\z#-TOKRB_GetVelocityZ#(Wheel_RB)
speed#=DotProduct#(nx#,ny#,nz#,Vx#,Vy#,Vz#)
dampX#=nx#*speed#*Damping#
dampY#=ny#*speed#*Damping#
dampZ#=nz#*speed#*Damping#
fx#=fx#+dampX#
fy#=fy#+dampY#
fz#=fz#+dampZ#
TOKRB_ApplyImpulse2 Body_RB,-fx#*timestep#,-fy#*timestep#,-fz#*timestep#,wpx#,wpy#,wpz#
TOKRB_ApplyImpulse Wheel_RB,fx#*timestep#,fy#*timestep#,fz#*timestep#
End Function
Function PlaceMesh(Mesh,RB)
PositionEntity Mesh,TOKRB_GetX#(RB),TOKRB_GetY#(RB),TOKRB_GetZ#(RB)
RotateEntity Mesh,TOKRB_GetPitch#(RB),TOKRB_GetYaw#(RB),TOKRB_GetRoll#(RB),False
End Function
Function DotProduct#(x1#,y1#,z1#,x2#,y2#,z2#)
DProd#=((x1#*x2#)+(y1#*y2#)+(z1#*z2#))
Return DProd#
End Function
Function CrossProduct(x1#,y1#,z1#,x2#,y2#,z2#)
CProd\x#=(y1#*z2#)-(z1#*y2#)
CProd\y#=(z1#*x2#)-(x1#*z2#)
CProd\z#=(x1#*y2#)-(y1#*x2#)
End Function
Function GetPointVel(RB,px#,py#,pz#)
vx#=TOKRB_GetVelocityX#(RB)
vy#=TOKRB_GetVelocityY#(RB)
vz#=TOKRB_GetVelocityZ#(RB)
avx#=TOKRB_GetAngularVelocityX#(RB)
avy#=TOKRB_GetAngularVelocityY#(RB)
avz#=TOKRB_GetAngularVelocityZ#(RB)
CrossProduct avx#,avy#,avz#,px#-TOKRB_GetX#(RB),py#-TOKRB_GetY#(RB),pz#-TOKRB_GetZ#(RB)
CProd\x#=CProd\x#+vx#
CProd\y#=CProd\y#+vy#
CProd\z#=CProd\z#+vz#
End Function
Function MakeTokCollider(mesh)
scount=CountSurfaces(mesh)
For ind=1 To scount
surface=GetSurface(mesh,ind)
ttltris=ttltris+CountTriangles(surface)
ttlvert=ttlvert+CountVertices(surface)
Next
vertices=CreateBank(16*ttlvert)
triangles=CreateBank(24*ttltris)
offsetv=0
offsett=0
For ind=1 To scount
surface = GetSurface(mesh,ind)
ctr=CountTriangles(surface)
tric=tric+cvt
cvt=CountVertices(surface)
;fill bank with vertices
For v=0 To cvt-1
PokeFloat vertices,offsetv,VertexX#(surface,v)
PokeFloat vertices,offsetv+4,VertexY#(surface,v)
PokeFloat vertices,offsetv+8,VertexZ#(surface,v)
PokeFloat vertices,offsetv+12,0.0
offsetv=offsetv+16
Next
;fill bank with triangles
For v=0 To ctr-1
PokeInt triangles,offsett,tric+TriangleVertex(surface,v,0)
PokeInt triangles,offsett+4,tric+TriangleVertex(surface,v,1)
PokeInt triangles,offsett+8,tric+TriangleVertex(surface,v,2)
PokeInt triangles,offsett+12,2 ; Material ID
PokeInt triangles,offsett+16,0
PokeInt triangles,offsett+20,0
offsett=offsett+24
Next
Next
;Hand over the terrain data to Tokamak
TOKSIM_SetStaticMesh vertices,ttlvert,triangles,ttltris
; Now we can free the banks as Tokamak has copied all data
FreeBank vertices
FreeBank triangles
End Function
Function RemoveComponent(x1#,y1#,z1#,x2#,y2#,z2#)
tmpdot# = DotProduct#(x1#,y1#,z1#,x2#,y2#,z2#)
CProd\x#=x1#-x2#*tmpdot#
CProd\y#=y1#-y2#*tmpdot#
CProd\z#=z1#-z2#*tmpdot#
End Function
Function GripFactor#(Vel#)
If Vel#>=0.0 And Vel<3.0 Then
GripFactor#=0.50
EndIf
If Vel#>=3.0 And Vel<6.0 Then
GripFactor#=0.95
EndIf
If Vel#>=6.0 And Vel<10.0 Then
GripFactor#=0.97
EndIf
If Vel#>=10.0 And Vel<15.0 Then
GripFactor#=0.98
EndIf
If Vel#>=15.0 Then
GripFactor#=0.99
EndIf
Return 0.999
Return GripFactor#
End Function
Function UpdateCamera(Camera,Target,Rate#)
CamX#=EntityX#(Camera)
CamY#=EntityY#(Camera)
CamZ#=EntityZ#(Camera)
DiffX#=EntityX#(Target)-CamX#
DiffY#=EntityY#(Target)-CamY#
DiffZ#=EntityZ#(Target)-CamZ#
TranslateEntity Camera,DiffX#*Rate#,DiffY#*Rate#,DiffZ#*Rate#
End Function