A place to discuss everything related to Newton Dynamics.
Moderators: Sascha Willems, walaber
by Leadwerks » Thu Dec 16, 2010 11:14 pm
This is BlitzMax code:
- Code: Select all
Rem
bbdoc:
EndRem
Function CreateVehicle:TVehicle(body:TBody)
Return TVehicle.Create(body)
EndFunction
Rem
bbdoc:
EndRem
Function AddVehicleTire:Int(vehicle:TVehicle,position:TVec3,radius:Float,suspensionlength:Float,springconstant:Float=70.0,springdamping:Float=150.0)
Return vehicle.addtire(position,radius,suspensionlength,springconstant,springdamping)
EndFunction
Rem
bbdoc:
EndRem
Function SetSteerAngle(vehicle:TVehicle,angle:Float,tireindex:Int)
vehicle.SetSteerAngle(angle,tireindex:Int)
EndFunction
Rem
bbdoc:
EndRem
Function AddTireTorque(vehicle:TVehicle,torque:Float,tireindex:Int=-1)
vehicle.AddTireTorque(torque,tireindex:Int)
EndFunction
Rem
bbdoc:
EndRem
Function GetTireMatrix:TMat4(vehicle:TVehicle,tireindex:Int)
Return vehicle.tire[tireindex].GetMatrix()
EndFunction
Rem
bbdoc:
EndRem
Type TVehicle Extends TJoint {expose}
Field tire:TTire[]
Field link:TLink {hidden}
Method Free()
For Local n:Int=0 To tire.length-1
tire[n].Free()
Next
tire=Null
If link
link.remove()
link=Null
EndIf
Super.free()
EndMethod
Method AddTire:Int(position:TVec3,radius:Float,suspensionlength:Float,springconstant:Float=70.0,springdamping:Float=150.0)
tire=tire[..tire.length+1]
tire[tire.length-1]=New TTire
tire[tire.length-1].radius=radius
tire[tire.length-1].position=position.copy()
tire[tire.length-1].vehicle=Self
If suspensionlength=0.0 suspensionlength = radius*0.5
tire[tire.length-1].suspensionlength=suspensionlength
tire[tire.length-1].springconstant=springconstant
tire[tire.length-1].springdamping=springdamping
Return tire.length-1
EndMethod
Method Update() {hidden}
If parent.getmass()>0.0
For Local n:Int=0 To tire.length-1
tire[n].Update(Self)
Next
EndIf
EndMethod
Method SetSteerAngle(angle:Float,tireindex:Int)
tire[tireindex].angle=angle
EndMethod
Method AddTireTorque(torque:Float,tireindex:Int=-1)
If tireindex=-1
For Local n:Int=0 To tire.length-1
tire[n].speed=torque
Next
Else
tire[tireindex].speed=torque
EndIf
EndMethod
Method GetTireMatrix:TMat4(tireindex:Int)
Return tire[tireindex].getmatrix()
EndMethod
Method GetTireCollisionEntity:TEntity(tireindex:Int)
Local pick:TPick=tire[tireindex].pick
If pick
Return pick.entity
Else
Return Null
EndIf
EndMethod
Method GetTire:TTire(tireindex:Int)
Return tire[tireindex]
EndMethod
Method TireIsAirborne:Int(tireindex)
Return tire[tireindex].airborne
EndMethod
Function Create:TVehicle(body:TBody)
Local vehicle:TVehicle=New TVehicle
vehicle.parent=body
vehicle.ConnectLinks()
vehicle.link=body.world.vehicles.addfirst(vehicle)
Return vehicle
EndFunction
EndType
Function TireIsAirborne:Int(vehicle:TVehicle, index:Int)
Return vehicle.TireIsAirborne(index)
EndFunction
Type TTire {expose}
Global ConvexCastCollisionType:Int
Global tempentity:TEntity {hidden}
Field position:TVec3=vec3(0)
Field angle:Float
Field radius:Float
Field airborne:Int {hidden}
Field compression:Float {hidden}
Field L_comp_prev:Float {hidden}
Field speed:Float {hidden}
Field vehicle:TVehicle {hidden}
Field rotation:Float {hidden}
Field lastposition:TVec3 {hidden}
Field brakes:Float {hidden}
Field ispowered:Int {hidden}
Field turnspeed:Float {hidden}
Field maxlateralforce:Float {hidden}
Field maxlongitudinalforce:Float {hidden}
Field brakeforce:Float {hidden}
Field suspensionlength:Float {hidden}
Field springconstant:Float {hidden}
Field springdamping:Float {hidden}
Field contactposition:TVec3 {hidden}
Field rotationfromtorque:Float {hidden}
Field rotationfromtorquespeed:Float {hidden}
Field laterialslippage:Float
Field longtudinalslippage:Float
Field pick:TPick
Field shape:Byte Ptr
Method Free()
vehicle=Null
If shape
NewtonReleaseCollision TWorld.Current.newtonWorld,shape
shape=Null
EndIf
EndMethod
Method GetMatrix:TMat4()
Local mat:TMat4
Local p:TEntity = CreatePivot(vehicle.parent)
p.SetRotation(vec3(0,angle,0))
p.SetPosition(position)
p.move(vec3(0,-suspensionlength-L_comp_prev,0))
p.turn(vec3(rotation+rotationfromtorque,0,0))
mat=p.mat.copy()
p.free()
Return mat
EndMethod
Method UpdateSuspension()
Local globaltireposition:TVec3=TFormPointm(position,vehicle.parent.nextmat,Null)
Local t0:TVec3=globaltireposition.minus(vehicle.parent.nextmat.j().scale(radius))
Local t1:TVec3=t0.minus(vehicle.parent.nextmat.j().scale(suspensionlength+0.1))
airborne=1
tempentity=vehicle.parent
Local pickradius#=0.1
Local mat:TMat4=TMat4.identity()
mat.ty = pickradius*0.5
If Not shape shape = NewtonCreateBox(TWorld.Current.newtonworld, pickradius, pickradius, pickradius, 0, mat)
MemCopy mat,vehicle.parent.nextmat,48
MemCopy Varptr mat.tx,t0,12
mat.ty:+radius
ConvexCastCollisionType=vehicle.parent.collisiontype
pick=ConvexCast(mat,t1,shape)
tempentity = Null
'Adjust suspension
If pick
airborne=0
RecordCollision(vehicle.parent,pick.entity,pick.position,pick.normal)
'pick.position=TFormPointm(Self.position,Self.vehicle.parent.nextmat,Null)
contactposition=pick.position.copy()
pick.position = TFormPointm(pick.position,Null,vehicle.parent.nextmat)
Local lt0:TVec3=TFormPointm( t0,Null,vehicle.parent.nextmat )
Local d#=lt0.y-pick.position.y
Local l_comp:Float=d-suspensionlength
Local k_susp:Float=springconstant
Local k_damp:Float=springdamping
Local F_spring:Float
Local F_damp:Float
d=Clamp(dot(pick.normal,vehicle.parent.nextmat.j()))
If d<0.5
l_comp=0.0
speed=0.0
Else
'd=(d-0.75)/0.75
speed:*d
l_comp:*d
EndIf
F_spring = L_comp * k_susp;
F_damp = (L_comp - L_comp_prev) * k_damp;
l_comp=Clamp(l_comp,-suspensionlength,0.0)
L_comp_prev=l_comp
Local euler:TVec3=vehicle.parent.nextquat.toeuler()
euler.x=0
euler.z=0
Local temp2:TMat4=TMat4.fromrotation(euler.toquat())
temp2.tx=vehicle.parent.nextmat.tx
temp2.ty=vehicle.parent.nextmat.ty
temp2.tz=vehicle.parent.nextmat.tz
Local force:TVec3=TFormVectorm(vec3(0,-(F_Spring+F_damp),0),vehicle.parent.nextmat,temp2)
If 90.0-ASin(pick.normal.y)<45.0
force.x=0
Else
airborne=1
EndIf
force = TFormVectorm(force,temp2,Null)
vehicle.parent.AddForceAtPoint( force, t0 )
Else
L_comp_prev = 0.0
EndIf
EndMethod
Method Update(vehicle:TVehicle)
Local globaltireposition:TVec3=TFormPoint(position,vehicle.parent,Null)
UpdateSuspension()
'Tire traction
If Not airborne
Local q:TQuat=vec3(0,angle,0).toquat().times(vehicle.parent.nextmat.rotation().normalize()).normalize()
q=TFormQuatm(vec3(0,angle,0).toquat(),vehicle.parent.nextmat,Null)
Local p:TMat4=TMat4.FromRotation(q)
Local v:TVec3
Local dv:TVec3
Local temp:Float
p.tx=vehicle.parent.nextmat.tx+position.x
p.ty=vehicle.parent.nextmat.tx+position.y
p.tz=vehicle.parent.nextmat.tx+position.z
contactposition=TFormPointm(Self.position,Self.vehicle.parent.nextmat,Null)
v=vehicle.parent.GetVelocityAtPoint(contactposition)
v=TFormVectorm(v,Null,p)
'v.x=0.0
v.x:*-1.0*vehicle.parent.mass
If maxlateralforce<>0.0
temp = v.x
v.x = Min(maxlateralforce,Abs(v.x)) * Sgn(v.x)
laterialslippage=Abs(temp)-Abs(v.x)
EndIf
v.y=0.0
v.z=speed
v=TFormVectorm(v,p,Null)
vehicle.parent.AddForceAtPoint(v, contactposition)
EndIf
'Tire rotation
Local dist#
Local c#=2.0*Pi*radius
If (airborne<>0 Or longtudinalslippage<>0.0)
turnspeed :+ (speed / c * 360.0/60.0) * 0.03
turnspeed = turnspeed * 0.995 + 0.05 * 0.0
lastposition=Null
Else
If lastposition
lastposition=tformpointm(lastposition,Null,vehicle.parent.nextmat)
dist = position.z - lastposition.z
turnspeed = dist / c * 360.0
EndIf
EndIf
rotation :+ turnspeed
lastposition=TFormPointm(position,vehicle.parent.nextmat,Null)
EndMethod
Function ConvexCast:TPick(mat:TMat4,b:TVec3,shape:Byte Ptr) {hidden}
Const maxContactsCount:Int=100
Global contactdata:Byte[maxContactsCount*SizeOf(New TNewtonWorldConvexCastReturnInfoTag)]
Global hitParam:Float[maxContactsCount]
Local tag:TNewtonWorldConvexCastReturnInfoTag=New TNewtonWorldConvexCastReturnInfoTag
Local result:TPick
Local contacts:Int
Local n:Int
Local maxhitparam:Float
Local newtonbody:Byte Ptr
Local entity:TEntity
Local bias:Float
contacts=NewtonWorldConvexCast(currentworld().newtonWorld,mat,b,shape,hitParam,Null,PreFilter,contactData,maxContactsCount,0)
For n=0 To contacts-1
MemCopy tag,Varptr contactdata[n*(SizeOf(tag))],SizeOf(tag)
newtonbody=tag.m_hitBody
entity=TEntity(NewtonBodyGetUserData(newtonbody))
If entity
If entity.getclass()=ENTITY_TERRAIN
If Not TTerrain(entity).getvisibilityatpoint(tag.point0,tag.point2) Continue
EndIf
If hitParam[n]<maxhitparam Or n=0
maxhitparam = hitParam[n]
If Not result result=New TPick
result.entity=entity
result.position.x=tag.point0
result.position.y=tag.point1
result.position.z=tag.point2
result.normal.x=tag.normal0
result.normal.y=tag.normal1
result.normal.z=tag.normal2
EndIf
EndIf
Next
Return result
EndFunction
Function PreFilter:Int(newtonbody:Byte Ptr,newtoncollision:Byte Ptr,userData:Byte Ptr)
Local entity:TEntity=TEntity(NewtonBodyGetUserData(newtonbody))
If entity
If entity=tempentity Return 0
If Not entity.hidden()
If GetCollisionResponse(entity.collisiontype,ConvexCastCollisionType)=1
Return 1
EndIf
EndIf
EndIf
Return 0
EndFunction
EndType
-

Leadwerks
-
- Posts: 569
- Joined: Fri Oct 27, 2006 2:54 pm
by ledahut » Mon Feb 14, 2011 12:02 pm
Thank you for this code it helped me a lot. (I use delphi/pascal language).
But I still don't understand how you add friction on tire side.
I think its here
- Code: Select all
v=vehicle.parent.GetVelocityAtPoint(contactposition)
v=TFormVectorm(v,Null,p)
'v.x=0.0
v.x:*-1.0*vehicle.parent.mass
If maxlateralforce<>0.0
temp = v.x
v.x = Min(maxlateralforce,Abs(v.x)) * Sgn(v.x)
laterialslippage=Abs(temp)-Abs(v.x)
EndIf
v.y=0.0
v.z=speed
v=TFormVectorm(v,p,Null)
vehicle.parent.AddForceAtPoint(v, contactposition)
-First you get global velocity in parent coordinate system (VX become lateral velocity, VZ become front velocity).
-Then you scale VX by -1*CarMass
-After you get a minimum and save 'laterialslippage'
-Finnaly the code is clear.
Where do you use laterialslippage after that?
-
ledahut
-
- Posts: 98
- Joined: Mon Jun 21, 2010 8:03 am
- Location: France
by ledahut » Tue Feb 15, 2011 6:58 am
Ok lateral friction work nice.
I was using bad local/global space in my code.
I see that 'longitudinalslippage' allow you set tire rotation (visual representation). Where do you set its value?
- Code: Select all
'Tire rotation
Local dist#
Local c#=2.0*Pi*radius
If (airborne<>0 Or longtudinalslippage<>0.0)
turnspeed :+ (speed / c * 360.0/60.0) * 0.03
turnspeed = turnspeed * 0.995 + 0.05 * 0.0
lastposition=Null
Else
If lastposition
lastposition=tformpointm(lastposition,Null,vehicle.parent.nextmat)
dist = position.z - lastposition.z
turnspeed = dist / c * 360.0
EndIf
EndIf
rotation :+ turnspeed
lastposition=TFormPointm(position,vehicle.parent.nextmat,Null)
Where can I use laterialslippage value from my first post?
-
ledahut
-
- Posts: 98
- Joined: Mon Jun 21, 2010 8:03 am
- Location: France
Return to General Discussion
Who is online
Users browsing this forum: No registered users and 1 guest