Car Physics

Blitz3D Forums/Blitz3D Programming/Car Physics

I have been making my own car physics for a game and came across a huge problem. My physics engine is a verlet based one that I made myself and I know it works. the problem occurs if you ram into something at high speeds, it will invert your car so the top acts like the wheels and the bottom acts like the top so you end up driving upside down. You will see what I mean because I made each verlet a transparnet sphere.

Here is the code. sorry if it is long and not very well commented.

Graphics3D 640,480,0,2
SeedRnd(MilliSecs())




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Temporary camera stuff;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cam = CreateCamera()
;CameraRange cam,.01,50
CameraZoom cam,2
TurnEntity cam,30,45,0
MoveEntity cam,0,0,-13

lit = CreateLight()
TurnEntity lit,90,0,0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




Global VerletType = 1					;Collision Types
Global RBodyType = 2
Global RigidBodyNum = 0
Global groundtype = 3
Global Wheeltype = 4

;Collisions VerletType,RBodyType,2,2  	;Sets Collision Types
;Collisions VerletType,VerletType,1,2
Collisions verletType,GroundType,2,2
Collisions Wheeltype,GroundType,2,2
Type Verlet								;Verlet type Contains:
	Field Active						;Determines if the verlet is an active verlet or a verlet used for orientation
	Field Mass#							;Gives the verlet a mass
	Field x#,y#,z#						;Gives the verlet an x,y,z cooridnate
	Field vx#,vy#,vz#					;Gives the verlet a velocity in 3d
	Field ox#,oy#,oz#					;Stores the old x,y,z coordinates to figure out the velocity of the verlet
	Field piv,ent						;Gives the verlet a pivot point and names the verlet's entity
	Field Col,ID,piv2,radius#			;Col tells if the verlet has collided yet and ID tells what entity and verlet group the verlet belongs to
End Type	

Type Constraint							;Constraints constrain the verlets to certain distances from eachother
	Field v1.verlet						;First verlet in constraint
	Field v2.verlet						;Second verlet in constraint
	Field length#						;Length of the constraint
End Type

Type Rigidbody										;Rigidbody is used as a reference for all of the verlets that belong to a mesh
	Field Ent										;Ent is the entity that is acting as the rigid body
	Field ID										;ID is the ID that all of the verlets in this mesh are attatched to
	Field x#,y#,z#									;X,Y,Z coordinates of the mesh
	Field Yaw#,pitch#,Roll#							;Yaw,Pitch,Roll coordinates of the mesh
	Field lf.verlet,lb.verlet,rf.verlet,rb.verlet	;The verlets that are inactive and are used to orient the mesh
	Field lfd.verlet,lbd.verlet,rfd.verlet,rbd.verlet;The verlets that are inactive and are used to orient the mesh	
	Field c.verlet,idl								;The central Verlet
	Field Verl.verlet[20],verlnum
End Type














Type Vehicle

	Field car
	Field lfwh.wheel,lbwh.wheel,rfwh.wheel,rbwh.wheel
	Field fliptimer
	Field r.rigidbody
	Field spin#

End Type



Type wheel
	Field x#,y#,z#,ent
End Type









SetBuffer BackBuffer()

car1.vehicle = MakeCar()
box = CreateCube()
;MoveEntity box,0,-3,0
ScaleEntity box,80,15,80
EntityColor box,0,255,0
EntityAlpha box,.5
mir = CreateMirror()
MoveEntity mir,0,-15,0

FlipMesh box

ApplyInactive(box)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Make obstacles;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cube = CreateCube()
MoveEntity cube,0,-14.95,20
ScaleEntity cube,3,3,3
TurnEntity cube,45,0,0

ApplyInactive(cube)


While Not KeyDown(1)
Cls
PointEntity cam,car1\car








spd# = 0

If KeyDown(200) Then
	
	spd# = .05
	
EndIf

If KeyDown(208) Then

	spd# = -.005
	
EndIf

trn = 0

If KeyDown(203) Then
	
	trn = -1
	
EndIf

If KeyDown(205) Then
	
	trn = 1
	
EndIf


ApplyDriverForce(car1.vehicle,spd#,trn)









UpdatePhysics()
RenderWorld()
Flip
Wend














Function UpdateCars()
End Function










Function ApplyDriverForce(cartmp.vehicle,speed#,turndir = -1)
	
	If CountCollisions(cartmp\r\lb\piv) = True And CountCollisions(cartmp\r\rb\piv) Then
		dx# = cartmp\r\lf\x# - cartmp\r\lb\x#
		dy# = cartmp\r\lf\y# - cartmp\r\lb\y#
		dz# = cartmp\r\lf\z# - cartmp\r\lb\z#
		
		dist# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
		
		dx# = dx# / dist#
		dy# = dy# / dist#
		dz# = dz# / dist#
		
		dx# = dx# * speed#
		dy# = dy# * speed#
		dz# = dz# * speed#
		
		cartmp\r\lb\ox# = cartmp\r\lb\ox# - dx#
		cartmp\r\lb\oy# = cartmp\r\lb\oy# - dy#
		cartmp\r\lb\oz# = cartmp\r\lb\oz# - dz#
		
		cartmp\r\rb\ox# = cartmp\r\rb\ox# - dx#
		cartmp\r\rb\oy# = cartmp\r\rb\oy# - dy#
		cartmp\r\rb\oz# = cartmp\r\rb\oz# - dz#
		
		
		If turndir = 1 Then
			dx# = cartmp\r\lf\x# - cartmp\r\rf\x#
			dy# = cartmp\r\lf\y# - cartmp\r\rf\y#
			dz# = cartmp\r\lf\z# - cartmp\r\rf\z#
			
			dist1# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
			
			dx# = dx# / dist1#
			dy# = dy# / dist1#
			dz# = dz# / dist1#
			
			dx# = dx# * speed# / 4
			dy# = dy# * speed# / 4
			dz# = dz# * speed# / 4
			
			cartmp\r\rf\ox# = cartmp\r\rf\ox# + dx#
			cartmp\r\rf\oy# = cartmp\r\rf\oy# + dy#
			cartmp\r\rf\oz# = cartmp\r\rf\oz# + dz#
			
		ElseIf turndir = -1 Then

			dx# = cartmp\r\lf\x# - cartmp\r\rf\x#
			dy# = cartmp\r\lf\y# - cartmp\r\rf\y#
			dz# = cartmp\r\lf\z# - cartmp\r\rf\z#
			
			dist1# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
			
			dx# = dx# / dist1#
			dy# = dy# / dist1#
			dz# = dz# / dist1#
			
			dx# = dx# * speed# / 4
			dy# = dy# * speed# / 4
			dz# = dz# * speed# / 4
			
			cartmp\r\lf\ox# = cartmp\r\lf\ox# - dx#
			cartmp\r\lf\oy# = cartmp\r\lf\oy# - dy#
			cartmp\r\lf\oz# = cartmp\r\lf\oz# - dz#

		EndIf
	EndIf	
End Function















Function MakeCar.vehicle()

Ve.vehicle = New vehicle

tmpcar = CreateCube()
ScaleEntity tmpcar,1,.1,2
EntityColor tmpcar,20,100,255

tmpfrnt = CreateCube()
EntityColor tmpfrnt,20,100,255
ScaleEntity tmpfrnt,1,.6,.7
MoveEntity tmpfrnt,0,.6,.5
EntityParent tmpfrnt,tmpcar

tmpwheel = CreateCylinder(8)
RotateMesh tmpwheel,0,0,90
ScaleEntity tmpwheel,.2,.3,.3
EntityColor tmpwheel,255,0,0
EntityRadius tmpwheel,.3
MoveEntity tmpwheel,0,-.7,0

fr1 = CopyEntity(tmpwheel)
fl1 = CopyEntity(tmpwheel)
br1 = CopyEntity(tmpwheel)
bl1 = CopyEntity(tmpwheel)

FreeEntity tmpwheel

MoveEntity fr1,-.8,0,1.6
MoveEntity fl1,.8,0,1.6
MoveEntity br1,-.8,0,-1.6
MoveEntity bl1,.8,0,-1.6


;EntityType fr1,wheeltype
;EntityType fl1,wheeltype
;EntityType br1,wheeltype
;EntityType bl1,wheeltype

Ve\lfwh.wheel = New wheel
Ve\lbwh.wheel = New wheel
Ve\rfwh.wheel = New wheel
Ve\rbwh.wheel = New wheel


Ve\lfwh\ent = fl1
Ve\lbwh\ent = bl1
Ve\rfwh\ent = fr1
Ve\rbwh\ent = br1

EntityParent fr1,tmpcar
EntityParent fl1,tmpcar
EntityParent br1,tmpcar
EntityParent bl1,tmpcar



rigidbodynum = rigidbodynum + 1


;Creates the Rigidbody that all of the verlets are linked to

r.rigidbody = New rigidbody
r\id = rigidbodynum
r\ent = tmpcar
r\x# = EntityX(r\ent)
r\y# = EntityY(r\ent)
r\z# = EntityZ(r\ent)
r\yaw# = EntityYaw(r\ent)
r\pitch# = EntityPitch(r\ent)
r\roll# = EntityRoll(r\ent)
EntityType r\ent,RBodyType
r\idl = 0

r\lf.verlet = createverlet(-.5,-.3,1.3,1,tmpcar,r\id,True,.65)
r\lb.verlet = createverlet(-.5,-.3,-1.3,1,tmpcar,r\id,True,.65)
r\rf.verlet = createverlet(.5,-.3,1.3,1,tmpcar,r\id,True,.65)
r\rb.verlet = createverlet(.5,-.3,-1.3,1,tmpcar,r\id,True,.65)
r\c.verlet = createverlet(0,0,0,1,tmpcar,r\id,True,.6)

r\verlnum = 5
r\Verl.verlet[0] = r\c.verlet
r\Verl.verlet[1] = r\lf.verlet
r\Verl.verlet[2] = r\rf.verlet
r\Verl.verlet[3] = r\lb.verlet
r\Verl.verlet[4] = r\rb.verlet


r\verl.verlet[5] = createverlet(0,-.7,0,1,tmpcar,r\id,True,.25)





CreateConstraint(r\lf.verlet,r\c.verlet)
createconstraint(r\lb.verlet,r\c.verlet)
createconstraint(r\rf.verlet,r\c.verlet)
createconstraint(r\rb.verlet,r\c.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)
createconstraint(r\lf.verlet,r\rf.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\rf.verlet)


createconstraint(r\rf.verlet,r\rb.verlet)
createconstraint(r\rf.verlet,r\lf.verlet)
createconstraint(r\rf.verlet,r\lb.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\lf.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)


createconstraint(r\verl.verlet[5],r\c.verlet)

createconstraint(r\verl.verlet[5],r\lb.verlet)
createconstraint(r\verl.verlet[5],r\lf.verlet)
createconstraint(r\verl.verlet[5],r\rb.verlet)
createconstraint(r\verl.verlet[5],r\rf.verlet)
createconstraint(r\verl.verlet[5],r\c.verlet)


Ve\car = tmpcar
Ve\r.rigidbody = r.rigidbody

Return ve.vehicle

End Function






























Function UpdatePhysics()

UpdateVerlets()

UpdateConstraints()

DrawVerlets()

UpdateWorld()
detectcollisions()

drawverlets()

positionPhysicsEntity()

RenderWorld()

End Function

















Function ApplyInactive(ent)

EntityType ent,3

End Function

















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Creates a verlet bounding box & creates verlets;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function ApplyPhysics(ent,mass#,stationary,Verlr# = .3)

rigidbodynum = rigidbodynum + 1


;Creates the Rigidbody that all of the verlets are linked to

r.rigidbody = New rigidbody
r\id = rigidbodynum
r\ent = ent
r\x# = EntityX(r\ent)
r\y# = EntityY(r\ent)
r\z# = EntityZ(r\ent)
r\yaw# = EntityYaw(r\ent)
r\pitch# = EntityPitch(r\ent)
r\roll# = EntityRoll(r\ent)
EntityType r\ent,RBodyType
r\idl = stationary

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;






;Loops through all surfaces and verticies
For k = 1 To CountSurfaces(ent)
	surf = GetSurface(ent,k)
	For index = 0 To CountVertices(surf)-1
		TFormPoint VertexX(surf,index), VertexY(surf, index),VertexZ(surf, index), ent, 0
		CreateVerlet(TFormedX(),TFormedY(),TFormedZ(),mass#,ent,r\ID,True,verlr#)   ;Creates a verlet for every vertice  Later it deletes duplicate verlets for the sake of stability.
	Next
Next

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Creates the bounding box verlets that don't react with anything but are used to orient the mesh

r\lf.verlet = CreateVerlet(r\x# - .5 , r\y# - .5, r\z# + .5, 1 , ent , r\ID , False)

r\lb.verlet = CreateVerlet(r\x# - .5 , r\y# - .5, r\z# - .5, 1 , ent , r\ID , False)

r\rf.verlet = CreateVerlet(r\x# + .5 , r\y# - .5, r\z# + .5, 1 , ent , r\ID , False)

r\rb.verlet = CreateVerlet(r\x# + .5 , r\y# - .5, r\z# - .5, 1 , ent , r\ID , False)

r\lfd.verlet = CreateVerlet(r\x# - .5 , r\y# + .5, r\z# + .5, 1 , ent , r\ID , False)

r\lbd.verlet = CreateVerlet(r\x# - .5 , r\y# + .5, r\z# - .5, 1 , ent , r\ID , False)

r\rfd.verlet = CreateVerlet(r\x# + .5 , r\y# + .5, r\z# + .5, 1 , ent , r\ID , False)

r\rbd.verlet = CreateVerlet(r\x# + .5 , r\y# + .5, r\z# - .5, 1 , ent , r\ID , False)

r\c.verlet = CreateVerlet(r\x# , r\y# , r\z#, 1 , ent , r\ID , False)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;Deletes Duplicate verlets so that the meshes are more stable

For v.verlet = Each verlet
	For vv.verlet = Each verlet
		If vv\ID = v\ID Then
			If vv\piv <> v\piv Then
				If v\x# = vv\x# And v\y# = vv\y# And v\z# = vv\z# And vv\mass <> 0 And v\mass <> 0 Then
					FreeEntity vv\piv
					Delete vv.verlet
				EndIf
			EndIf
		EndIf
	Next
Next

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




cnt = 0
For v.verlet = Each verlet
	If V\ent = ent And V\Active = True Then
		R\Verl.verlet[cnt] = v.verlet
		cnt = cnt + 1
	EndIf
Next

r\Verlnum = cnt - 1


;This code makes constraints which it links every inside verlet to all eight of the outside verlets but no others

For v.verlet = Each verlet
	If v\ID = rigidbodynum Then
		If r\idl = False Then
			If v\active = True Then
				Createconstraint(v.verlet,r\rf.verlet)              ;Creates constraint
				Createconstraint(v.verlet,r\rb.verlet)
				Createconstraint(v.verlet,r\lf.verlet)
				Createconstraint(v.verlet,r\lb.verlet)
				Createconstraint(v.verlet,r\rfd.verlet)              ;Creates constraint
				Createconstraint(v.verlet,r\rbd.verlet)
				Createconstraint(v.verlet,r\lfd.verlet)
				Createconstraint(v.verlet,r\lbd.verlet)
				Createconstraint(v.verlet,r\c.verlet)
				
			EndIf
		EndIf
	EndIf
Next
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




createconstraint(r\rf.verlet,r\c.verlet)
createconstraint(r\rb.verlet,r\c.verlet)
createconstraint(r\lf.verlet,r\c.verlet)
createconstraint(r\lb.verlet,r\c.verlet)
createconstraint(r\rfd.verlet,r\c.verlet)
createconstraint(r\rbd.verlet,r\c.verlet)
createconstraint(r\lfd.verlet,r\c.verlet)
createconstraint(r\lbd.verlet,r\c.verlet)

createconstraint(r\rf.verlet,r\rb.verlet)
createconstraint(r\rf.verlet,r\lf.verlet)
createconstraint(r\rf.verlet,r\lb.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\lf.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)


createconstraint(r\rfd.verlet,r\rbd.verlet)
createconstraint(r\rfd.verlet,r\lfd.verlet)
createconstraint(r\rfd.verlet,r\lbd.verlet)

createconstraint(r\rbd.verlet,r\lbd.verlet)
createconstraint(r\rbd.verlet,r\lfd.verlet)

createconstraint(r\lfd.verlet,r\lbd.verlet)


createconstraint(r\rf.verlet,r\rfd.verlet)
createconstraint(r\lf.verlet,r\lfd.verlet)
createconstraint(r\rb.verlet,r\rbd.verlet)
createconstraint(r\lb.verlet,r\lbd.verlet)

;Deletes duplicate Or reversed constraints  This speeds up the constraint loops very much

For c.constraint = Each constraint
	For cc.constraint = Each constraint
		If c\v1\piv = cc\v1\piv And c\v2\piv = c\v1\piv Then
			Delete cc.constraint
		EndIf
	Next
Next


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;





End Function































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Creates a verlet at the given x,y,z coordinate;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function createverlet.verlet(x#,y#,z#,mass#,ent,ID,Active,radius# = .1)

	v.Verlet = New Verlet
	v\x# = x#
	v\y# = y#
	v\z# = z#
	v\ox# = v\x#
	v\oy# = v\y#
	v\oz# = v\z#
	v\vx# = 0
	v\vy# = 0
	v\vz# = 0
	v\ent = ent
	v\ID = ID
	v\active = Active
	v\mass# = mass#
	v\radius# = radius#
	
	v\piv = CreateSphere()
;	v\piv2 = CreatePivot()
	ScaleEntity v\piv,radius#,radius#,radius#
	EntityAlpha v\piv,.4
	PositionEntity v\piv,v\x#,v\y#,v\z#
	
	If active = True Then
		EntityType v\piv,VerletType
		EntityRadius v\piv,radius#
	EndIf
	
	Return v
End Function































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Constrains two verlets together;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function CreateConstraint(v1.verlet,v2.verlet)

	c.constraint = New constraint
	c\v1.verlet = v1.verlet
	c\v2.verlet = v2.verlet
	c\length# = Sqr((c\v1\x#-c\v2\x#)^2 + (c\v1\y#-c\v2\y#)^2 + (c\v1\z#-c\v2\z#)^2)

End Function






































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;goes through every verlet and updates it;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Updateverlets()

For v.verlet = Each verlet
	
	If v\col = True Then
		v\col = False
		fric# = .99
	Else
		fric# = 1
	EndIf
	
	v\vx# = (v\x# - v\ox#)*fric#
	v\vy# = (v\y# - v\oy#)*fric#
	v\vz# = (v\z# - v\oz#)*fric#
	
	v\ox# = v\x#
	v\oy# = v\y#
	v\oz# = v\z#
	
	v\x# = v\x# + v\vx#
	v\y# = v\y# + v\vy# - .004
	v\z# = v\z# + v\vz#
	
	
	For vv.verlet = Each verlet
			If v <> vv And v\id <> vv\id; if not the same verlet or group
				dx# = v\x# - vv\x#
				dy# = v\y# - vv\y#
				dz# = v\z# - vv\z#
				dist# = Sqr ( dx#*dx# + dy#*dy# + dz#*dz# )		
				totalr# = v\radius# + vv\radius#
				If dist# < totalr# Then
				
					
					Diffx# = ( dist# - totalr# ) * ( dx# / dist# )
					Diffy# = ( dist# - totalr# ) * ( dy# / dist# )
					Diffz# = ( dist# - totalr# ) * ( dz# / dist# )

					v\x# = v\x# - Diffx# ;* .5
					v\y# = v\y# - Diffy# ;* .5
					v\z# = v\z# - Diffz# ;* .5

					vv\x# = vv\x# + Diffx# ;* .5
					vv\y# = vv\y# + Diffy# ;* .5
					vv\z# = vv\z# + Diffz# ;* .5
				EndIf 				
			EndIf
		Next 

;	If v\y# < 0 Then
;		v\y# = 0
;		v\col = True
;	EndIf
	
Next

End Function






















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;goes through every constraint and updates it;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function UpdateConstraints()

For i = 1 To 8

	For c.constraint = Each constraint
		mx# = ( c\v1\x# - c\v2\x# )
		my# = ( c\v1\y# - c\v2\y# )
		mz# = ( c\v1\z# - c\v2\z# )
		
		dist# = Sqr( (mx)^2 + (my)^2 + (mz)^2 )
		
		mx# = mx# / 2
		my# = my# / 2
		mz# = mz# / 2
		
		If dist# <> 0  Then
			dif# = (dist# - c\length#) / dist# * .7
		EndIf
		
	;	If c\v1\col = False Or i > 5 Then
			c\v1\x# = c\v1\x# - dif# * mx#
			c\v1\y# = c\v1\y# - dif# * my#
			c\v1\z# = c\v1\z# - dif# * mz#
	;	EndIf
	;	If c\v2\col = False Or i > 5 Then
			c\v2\x# = c\v2\x# + dif# * mx#
			c\v2\y# = c\v2\y# + dif# * my#
			c\v2\z# = c\v2\z# + dif# * mz#
	;	EndIf
	Next

Next

End Function





























;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;positions all verlets;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Drawverlets()

For v.verlet = Each verlet
	
	PositionEntity v\piv,v\x#,v\y#,v\z#
	
Next

End Function


















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;positions all meshes;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function PositionPhysicsEntity()

For r.rigidbody = Each rigidbody
	PositionEntity r\ent,EntityX(r\c\piv),EntityY(r\c\piv),EntityZ(r\c\piv)
	
	;align mesh to verlet cage
	x# = EntityX( r\rf\piv ) - EntityX( r\rb\piv ) + EntityX( r\lf\piv ) - EntityX( r\lb\piv )
	y# = EntityY( r\rf\piv ) - EntityY( r\rb\piv ) + EntityY( r\lf\piv ) - EntityY( r\lb\piv )
	z# = EntityZ( r\rf\piv ) - EntityZ( r\rb\piv ) + EntityZ( r\lf\piv ) - EntityZ( r\lb\piv )
	AlignToVector r\ent, x#,y#,z#, 3
	x# = EntityX( r\rf\piv ) - EntityX( r\lf\piv ) + EntityX( r\rb\piv ) - EntityX( r\lb\piv )
	y# = EntityY( r\rf\piv ) - EntityY( r\lf\piv ) + EntityY( r\rb\piv ) - EntityY( r\lb\piv )
	z# = EntityZ( r\rf\piv ) - EntityZ( r\lf\piv ) + EntityZ( r\rb\piv ) - EntityZ( r\lb\piv )
	AlignToVector r\ent, x#,y#,z#,1
Next

End Function





































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;tests all verlets for collisions;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Detectcollisions()

For v.verlet = Each verlet
	If EntityX(v\piv) <> v\x# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\x# = EntityX(v\piv)
	EndIf
	If EntityY(v\piv) <> v\y# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\y# = EntityY(v\piv)
	EndIf
	If EntityZ(v\piv) <> v\z# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\z# = EntityZ(v\piv)
	EndIf
Next

End Function




































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;applies a force to given object;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function PApplyForce(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\Verlnum
			r\verl[i]\ox# = r\verl[i]\ox# - x#
			r\verl[i]\oy# = r\verl[i]\oy# - y#
			r\verl[i]\oz# = r\verl[i]\oz# - z#
		Next
	EndIf
Next

End Function



Function PMoveEntity(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\verlnum
			r\verl[cnt]\ox# = r\verl[cnt]\ox# + x#
			r\verl[cnt]\oy# = r\verl[cnt]\oy# + y#
			r\verl[cnt]\oz# = r\verl[cnt]\oz# + z#
			r\verl[cnt]\x# = r\verl[cnt]\x# + x#
			r\verl[cnt]\y# = r\verl[cnt]\y# + y#
			r\verl[cnt]\z# = r\verl[cnt]\z# + z#
		Next
	EndIf
Next

End Function



Function PPositionEntity(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\verlnum
			r\verl[cnt]\ox# = r\verl[cnt]\ox# + (r\verl[cnt]\ox# - x#)
			r\verl[cnt]\oy# = r\verl[cnt]\oy# + (r\verl[cnt]\oy# - y#)
			r\verl[cnt]\oz# = r\verl[cnt]\oz# + (r\verl[cnt]\oz# - z#)
			r\verl[cnt]\x# = r\verl[cnt]\x# + (r\verl[cnt]\x# - x#)
			r\verl[cnt]\y# = r\verl[cnt]\y# + (r\verl[cnt]\y# - y#)
			r\verl[cnt]\z# = r\verl[cnt]\z# + (r\verl[cnt]\z# - z#)
		Next
	EndIf
Next

End Function



Please does anyone know what is happening and why? I have no clue

This is something that can happen with verlet physics.

What happens is that one of your verlets has moved too far, and a different solution has been found.

Imagine a pyramid. If the top point is moved down too far, the solution found may be an upside down pyramid. This is still a valid solution for all the constraint lengths, just not the one you want. Generally speaking, the more complex the verlet cage, the easier it is to "break" like this. Another bad situation happens when the constraints end up competing for each other and can't satisfy the proper lengths. This results in the verlet group going crazy and usually spinning wildly out of control.

What you need to do is one or several of the following.
- take smaller simulation steps
- move things slower
- create a more solid cage that cannot break as easily. More constraints is not necessarily the answer,... they have to be in the correct places. My most stable cages are made of triangles and tetrahedrons. I have several variations that I cannot break within the limits of my game engine.

That is what I was thinking but I wasn't sure. The speed required to make the cages invert was not my intended game speed but I was just curious. I don't think this will be a problem later on considering there won't be much to run into at that high a speed.

IMO, if you're using a verlet integration method for physics then it's a must that you have functions to detect the inversion and correct it before it's visible to the user. You can pretty much guarantee that it will happen at some point, especially when you start to simulate body/body collisions correctly.

For example, imagine 2 vehicles racing at full speed and hitting each other head on. Even if they are travelling at a slow speed their relative speed will likely be large enough for them to interpentrate and cause inversion ro worse still entaglement.

Ok I will try to do that it looks as though this will take longer than I expected thanks :)

I have been messing with the car wheel physics and ran into a big problem. There is something wrong with parenting the wheels to the car and then rotating them. you'll see what I mean if you run this code.

Graphics3D 640,480,0,2
SeedRnd(MilliSecs())




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Temporary camera stuff;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cam = CreateCamera()
;CameraRange cam,.01,50
CameraZoom cam,2
TurnEntity cam,30,45,0
MoveEntity cam,0,0,-13

lit = CreateLight()
TurnEntity lit,90,0,0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




Global VerletType = 1					;Collision Types
Global RBodyType = 2
Global RigidBodyNum = 0
Global groundtype = 3
Global Wheeltype = 4

;Collisions VerletType,RBodyType,2,2  	;Sets Collision Types
;Collisions VerletType,VerletType,1,2
Collisions verletType,GroundType,2,2
Collisions Wheeltype,GroundType,2,2
Type Verlet								;Verlet type Contains:
	Field Active						;Determines if the verlet is an active verlet or a verlet used for orientation
	Field Mass#							;Gives the verlet a mass
	Field x#,y#,z#						;Gives the verlet an x,y,z cooridnate
	Field vx#,vy#,vz#					;Gives the verlet a velocity in 3d
	Field ox#,oy#,oz#					;Stores the old x,y,z coordinates to figure out the velocity of the verlet
	Field piv,ent,fric#					;Gives the verlet a pivot point and names the verlet's entity
	Field Col,ID,piv2,radius#			;Col tells if the verlet has collided yet and ID tells what entity and verlet group the verlet belongs to
End Type	

Type Constraint							;Constraints constrain the verlets to certain distances from eachother
	Field v1.verlet						;First verlet in constraint
	Field v2.verlet						;Second verlet in constraint
	Field length#						;Length of the constraint
End Type

Type Rigidbody										;Rigidbody is used as a reference for all of the verlets that belong to a mesh
	Field Ent										;Ent is the entity that is acting as the rigid body
	Field ID										;ID is the ID that all of the verlets in this mesh are attatched to
	Field x#,y#,z#									;X,Y,Z coordinates of the mesh
	Field Yaw#,pitch#,Roll#							;Yaw,Pitch,Roll coordinates of the mesh
	Field lf.verlet,lb.verlet,rf.verlet,rb.verlet	;The verlets that are inactive and are used to orient the mesh
	Field lfd.verlet,lbd.verlet,rfd.verlet,rbd.verlet;The verlets that are inactive and are used to orient the mesh	
	Field c.verlet,idl								;The central Verlet
	Field Verl.verlet[20],verlnum
End Type














Type Vehicle

	Field car
	Field lfwh.wheel,lbwh.wheel,rfwh.wheel,rbwh.wheel
	Field fliptimer
	Field r.rigidbody
	Field spin#,turndir
	Field roll#

End Type



Type wheel
	Field x#,y#,z#,ent
End Type









SetBuffer BackBuffer()

car1.vehicle = MakeCar()
box = CreateCube()
;MoveEntity box,0,-3,0
ScaleEntity box,80,15,80
EntityColor box,0,255,0
EntityAlpha box,.3
mir = CreateMirror()
MoveEntity mir,0,-15,0

FlipMesh box

ApplyInactive(box)

Global glbspin#
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Make obstacles;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cube = CreateCube()
MoveEntity cube,0,-14.95,20
ScaleEntity cube,3,3,3
TurnEntity cube,45,0,0

ApplyInactive(cube)


sphere = CreateSphere()
MoveEntity sphere,50,-14.95,10
ScaleEntity sphere,5,2,5

ApplyInactive(sphere)


box = CreateCube()
MoveEntity box,-20,-14.95,-60
ScaleMesh box,7,7,7

ApplyInactive(box)

While Not KeyDown(1)
Cls
PointEntity cam,car1\car





;TurnEntity box,0,1,0


spd# = 0

If KeyDown(200) Then
	
	spd# = .08
	
EndIf

If KeyDown(208) Then

	spd# = -.01
	
EndIf

trn = 0

If KeyDown(203) Then
	
	trn = -1
	
EndIf

If KeyDown(205) Then
	
	trn = 1
	
EndIf


ApplyDriverForce(car1.vehicle,spd#,trn)



Updatecars()





UpdatePhysics()
RenderWorld()


Text 1,1,glbspin#
Flip
Wend














Function UpdateCars()

For v.vehicle = Each vehicle
	
	speed# = Sqr(  (v\r\c\x#-v\r\c\ox#)^2  +  (v\r\c\y#-v\r\c\oy#)^2  +  (v\r\c\z#-v\r\c\oz#)^2)
	If speed# > .1 Then
		
		dx# = v\r\lf\x# - v\r\lb\x#
	;	dy# = v\r\lf\y# - v\r\lb\y#
		dz# = v\r\lf\z# - v\r\lb\z#
		
		dx1# = v\r\c\x#-v\r\c\ox#
		dz1# = v\r\c\z#-v\r\c\oz#
		
		at1# = ATan2(dx#,dz#)
		at2# = ATan2(dx1#,dz1#)
		
	;	fric# = 1.0 - (Abs(at1#-at2#)/100)
		
		If Abs(at1# - at2#) > 20 Then
			fric# = .93
		Else
			fric# = .97
		EndIf
		
		v\r\lf\fric# = fric#
		v\r\lb\fric# = fric#
		v\r\rf\fric# = fric#
		v\r\rb\fric# = fric#
		
	Else
		fric# = .99
		
		v\r\lf\fric# = fric#
		v\r\lb\fric# = fric#
		v\r\rf\fric# = fric#
		v\r\rb\fric# = fric#

	EndIf
	
	v\roll# = v\roll#+v\spin#
	
	glbspin# = v\spin#
	
	TurnEntity v\lfwh\ent,v\spin#,0,0
	TurnEntity v\lbwh\ent,v\spin#,0,0
	TurnEntity v\rfwh\ent,v\spin#,0,0
	TurnEntity v\rbwh\ent,v\spin#,0,0
	
Next

End Function










Function ApplyDriverForce(cartmp.vehicle,speed#,turndir = 0)
	
	cartmp\turndir = turndir
	
	If speed# < 0 Then
		turndir = - turndir
	EndIf
	If CountCollisions(cartmp\r\lb\piv) = True And CountCollisions(cartmp\r\rb\piv) Then
		dx# = cartmp\r\lf\x# - cartmp\r\lb\x#
		dy# = cartmp\r\lf\y# - cartmp\r\lb\y#
		dz# = cartmp\r\lf\z# - cartmp\r\lb\z#
		
		dist# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
		
		dx# = dx# / dist#
		dy# = dy# / dist#
		dz# = dz# / dist#
		
		dx# = dx# * speed#
		dy# = dy# * speed#
		dz# = dz# * speed#
		
		cartmp\r\lb\ox# = cartmp\r\lb\ox# - dx#
		cartmp\r\lb\oy# = cartmp\r\lb\oy# - dy#
		cartmp\r\lb\oz# = cartmp\r\lb\oz# - dz#
		
		cartmp\r\rb\ox# = cartmp\r\rb\ox# - dx#
		cartmp\r\rb\oy# = cartmp\r\rb\oy# - dy#
		cartmp\r\rb\oz# = cartmp\r\rb\oz# - dz#
		
		
		If turndir = 1 Then
			dx# = cartmp\r\lf\x# - cartmp\r\rf\x#
			dy# = cartmp\r\lf\y# - cartmp\r\rf\y#
			dz# = cartmp\r\lf\z# - cartmp\r\rf\z#
			
			dist1# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
			
			dx# = dx# / dist1#
			dy# = dy# / dist1#
			dz# = dz# / dist1#
			
			speed# = Sqr(  (cartmp\r\c\x#-cartmp\r\c\ox#)^2  +  (cartmp\r\c\y#-cartmp\r\c\oy#)^2  +  (cartmp\r\c\z#-cartmp\r\c\oz#)^2)
			
			dx# = dx# * speed# / 80
			dy# = dy# * speed# / 80
			dz# = dz# * speed# / 80
			
			cartmp\r\rf\ox# = cartmp\r\rf\ox# + dx#
			cartmp\r\rf\oy# = cartmp\r\rf\oy# + dy#
			cartmp\r\rf\oz# = cartmp\r\rf\oz# + dz#
			
		ElseIf turndir = -1 Then

			dx# = cartmp\r\lf\x# - cartmp\r\rf\x#
			dy# = cartmp\r\lf\y# - cartmp\r\rf\y#
			dz# = cartmp\r\lf\z# - cartmp\r\rf\z#
			
			dist1# = Sqr( dx#*dx# + dy#*dy# + dz#*dz# )
			
			dx# = dx# / dist1#
			dy# = dy# / dist1#
			dz# = dz# / dist1#
			
			speed# = Sqr(  (cartmp\r\c\x#-cartmp\r\c\ox#)^2  +  (cartmp\r\c\y#-cartmp\r\c\oy#)^2  +  (cartmp\r\c\z#-cartmp\r\c\oz#)^2)
			
			dx# = dx# * speed# / 80
			dy# = dy# * speed# / 80
			dz# = dz# * speed# / 80
			
			cartmp\r\lf\ox# = cartmp\r\lf\ox# - dx#
			cartmp\r\lf\oy# = cartmp\r\lf\oy# - dy#
			cartmp\r\lf\oz# = cartmp\r\lf\oz# - dz#

		EndIf
	EndIf
	
	
	speed# = Sqr#(  (cartmp\r\c\x#-cartmp\r\c\ox#)^2  +  (cartmp\r\c\z#-cartmp\r\c\oz#)^2)	
	
	cartmp\spin# = speed# * 20
End Function















Function MakeCar.vehicle()

Ve.vehicle = New vehicle

tmpcar = CreateCube()
ScaleEntity tmpcar,1,.1,2
EntityColor tmpcar,20,100,255

tmpfrnt = CreateCube()
EntityColor tmpfrnt,20,100,255
ScaleEntity tmpfrnt,1,.6,.7
MoveEntity tmpfrnt,0,.6,.5
EntityParent tmpfrnt,tmpcar

tmpwheel = CreateCylinder(5)
RotateMesh tmpwheel,0,0,90
ScaleEntity tmpwheel,.2,.4,.4
EntityColor tmpwheel,10,10,10
EntityRadius tmpwheel,.3
MoveEntity tmpwheel,0,-.7,0

fr1 = CopyEntity(tmpwheel)
fl1 = CopyEntity(tmpwheel)
br1 = CopyEntity(tmpwheel)
bl1 = CopyEntity(tmpwheel)

FreeEntity tmpwheel

MoveEntity fr1,-.8,0,1.6
MoveEntity fl1,.8,0,1.6
MoveEntity br1,-.8,0,-1.6
MoveEntity bl1,.8,0,-1.6


;EntityType fr1,wheeltype
;EntityType fl1,wheeltype
;EntityType br1,wheeltype
;EntityType bl1,wheeltype

Ve\lfwh.wheel = New wheel
Ve\lbwh.wheel = New wheel
Ve\rfwh.wheel = New wheel
Ve\rbwh.wheel = New wheel


Ve\lfwh\ent = fl1
Ve\lbwh\ent = bl1
Ve\rfwh\ent = fr1
Ve\rbwh\ent = br1

EntityParent fr1,tmpcar
EntityParent fl1,tmpcar
EntityParent br1,tmpcar
EntityParent bl1,tmpcar



rigidbodynum = rigidbodynum + 1


;Creates the Rigidbody that all of the verlets are linked to

r.rigidbody = New rigidbody
r\id = rigidbodynum
r\ent = tmpcar
r\x# = EntityX(r\ent)
r\y# = EntityY(r\ent)
r\z# = EntityZ(r\ent)
r\yaw# = EntityYaw(r\ent)
r\pitch# = EntityPitch(r\ent)
r\roll# = EntityRoll(r\ent)
EntityType r\ent,RBodyType
r\idl = 0

r\lf.verlet = createverlet(-.5,-.3,1.3,1,tmpcar,r\id,True,.65)
r\lb.verlet = createverlet(-.5,-.3,-1.3,1,tmpcar,r\id,True,.65)
r\rf.verlet = createverlet(.5,-.3,1.3,1,tmpcar,r\id,True,.65)
r\rb.verlet = createverlet(.5,-.3,-1.3,1,tmpcar,r\id,True,.65)
r\c.verlet = createverlet(0,0,0,1,tmpcar,r\id,True,.8)

r\verlnum = 5
r\Verl.verlet[0] = r\c.verlet
r\Verl.verlet[1] = r\lf.verlet
r\Verl.verlet[2] = r\rf.verlet
r\Verl.verlet[3] = r\lb.verlet
r\Verl.verlet[4] = r\rb.verlet


r\verl.verlet[5] = createverlet(0,-.7,0,1,tmpcar,r\id,True,.25)





CreateConstraint(r\lf.verlet,r\c.verlet)
createconstraint(r\lb.verlet,r\c.verlet)
createconstraint(r\rf.verlet,r\c.verlet)
createconstraint(r\rb.verlet,r\c.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)
createconstraint(r\lf.verlet,r\rf.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\rf.verlet)


createconstraint(r\rf.verlet,r\rb.verlet)
createconstraint(r\rf.verlet,r\lf.verlet)
createconstraint(r\rf.verlet,r\lb.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\lf.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)


createconstraint(r\verl.verlet[5],r\c.verlet)

createconstraint(r\verl.verlet[5],r\lb.verlet)
createconstraint(r\verl.verlet[5],r\lf.verlet)
createconstraint(r\verl.verlet[5],r\rb.verlet)
createconstraint(r\verl.verlet[5],r\rf.verlet)
createconstraint(r\verl.verlet[5],r\c.verlet)


Ve\car = tmpcar
Ve\r.rigidbody = r.rigidbody

Return ve.vehicle

End Function






























Function UpdatePhysics()

UpdateVerlets()

UpdateConstraints()

DrawVerlets()

UpdateWorld()
detectcollisions()

drawverlets()

positionPhysicsEntity()

RenderWorld()

End Function

















Function ApplyInactive(ent)

EntityType ent,3

End Function

















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Creates a verlet bounding box & creates verlets;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function ApplyPhysics(ent,mass#,stationary,Verlr# = .3)

rigidbodynum = rigidbodynum + 1


;Creates the Rigidbody that all of the verlets are linked to

r.rigidbody = New rigidbody
r\id = rigidbodynum
r\ent = ent
r\x# = EntityX(r\ent)
r\y# = EntityY(r\ent)
r\z# = EntityZ(r\ent)
r\yaw# = EntityYaw(r\ent)
r\pitch# = EntityPitch(r\ent)
r\roll# = EntityRoll(r\ent)
EntityType r\ent,RBodyType
r\idl = stationary

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;






;Loops through all surfaces and verticies
For k = 1 To CountSurfaces(ent)
	surf = GetSurface(ent,k)
	For index = 0 To CountVertices(surf)-1
		TFormPoint VertexX(surf,index), VertexY(surf, index),VertexZ(surf, index), ent, 0
		CreateVerlet(TFormedX(),TFormedY(),TFormedZ(),mass#,ent,r\ID,True,verlr#)   ;Creates a verlet for every vertice  Later it deletes duplicate verlets for the sake of stability.
	Next
Next

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Creates the bounding box verlets that don't react with anything but are used to orient the mesh

r\lf.verlet = CreateVerlet(r\x# - .5 , r\y# - .5, r\z# + .5, 1 , ent , r\ID , False)

r\lb.verlet = CreateVerlet(r\x# - .5 , r\y# - .5, r\z# - .5, 1 , ent , r\ID , False)

r\rf.verlet = CreateVerlet(r\x# + .5 , r\y# - .5, r\z# + .5, 1 , ent , r\ID , False)

r\rb.verlet = CreateVerlet(r\x# + .5 , r\y# - .5, r\z# - .5, 1 , ent , r\ID , False)

r\lfd.verlet = CreateVerlet(r\x# - .5 , r\y# + .5, r\z# + .5, 1 , ent , r\ID , False)

r\lbd.verlet = CreateVerlet(r\x# - .5 , r\y# + .5, r\z# - .5, 1 , ent , r\ID , False)

r\rfd.verlet = CreateVerlet(r\x# + .5 , r\y# + .5, r\z# + .5, 1 , ent , r\ID , False)

r\rbd.verlet = CreateVerlet(r\x# + .5 , r\y# + .5, r\z# - .5, 1 , ent , r\ID , False)

r\c.verlet = CreateVerlet(r\x# , r\y# , r\z#, 1 , ent , r\ID , False)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;Deletes Duplicate verlets so that the meshes are more stable

For v.verlet = Each verlet
	For vv.verlet = Each verlet
		If vv\ID = v\ID Then
			If vv\piv <> v\piv Then
				If v\x# = vv\x# And v\y# = vv\y# And v\z# = vv\z# And vv\mass <> 0 And v\mass <> 0 Then
					FreeEntity vv\piv
					Delete vv.verlet
				EndIf
			EndIf
		EndIf
	Next
Next

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




cnt = 0
For v.verlet = Each verlet
	If V\ent = ent And V\Active = True Then
		R\Verl.verlet[cnt] = v.verlet
		cnt = cnt + 1
	EndIf
Next

r\Verlnum = cnt - 1


;This code makes constraints which it links every inside verlet to all eight of the outside verlets but no others

For v.verlet = Each verlet
	If v\ID = rigidbodynum Then
		If r\idl = False Then
			If v\active = True Then
				Createconstraint(v.verlet,r\rf.verlet)              ;Creates constraint
				Createconstraint(v.verlet,r\rb.verlet)
				Createconstraint(v.verlet,r\lf.verlet)
				Createconstraint(v.verlet,r\lb.verlet)
				Createconstraint(v.verlet,r\rfd.verlet)              ;Creates constraint
				Createconstraint(v.verlet,r\rbd.verlet)
				Createconstraint(v.verlet,r\lfd.verlet)
				Createconstraint(v.verlet,r\lbd.verlet)
				Createconstraint(v.verlet,r\c.verlet)
				
			EndIf
		EndIf
	EndIf
Next
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




createconstraint(r\rf.verlet,r\c.verlet)
createconstraint(r\rb.verlet,r\c.verlet)
createconstraint(r\lf.verlet,r\c.verlet)
createconstraint(r\lb.verlet,r\c.verlet)
createconstraint(r\rfd.verlet,r\c.verlet)
createconstraint(r\rbd.verlet,r\c.verlet)
createconstraint(r\lfd.verlet,r\c.verlet)
createconstraint(r\lbd.verlet,r\c.verlet)

createconstraint(r\rf.verlet,r\rb.verlet)
createconstraint(r\rf.verlet,r\lf.verlet)
createconstraint(r\rf.verlet,r\lb.verlet)

createconstraint(r\rb.verlet,r\lb.verlet)
createconstraint(r\rb.verlet,r\lf.verlet)

createconstraint(r\lf.verlet,r\lb.verlet)


createconstraint(r\rfd.verlet,r\rbd.verlet)
createconstraint(r\rfd.verlet,r\lfd.verlet)
createconstraint(r\rfd.verlet,r\lbd.verlet)

createconstraint(r\rbd.verlet,r\lbd.verlet)
createconstraint(r\rbd.verlet,r\lfd.verlet)

createconstraint(r\lfd.verlet,r\lbd.verlet)


createconstraint(r\rf.verlet,r\rfd.verlet)
createconstraint(r\lf.verlet,r\lfd.verlet)
createconstraint(r\rb.verlet,r\rbd.verlet)
createconstraint(r\lb.verlet,r\lbd.verlet)

;Deletes duplicate Or reversed constraints  This speeds up the constraint loops very much

For c.constraint = Each constraint
	For cc.constraint = Each constraint
		If c\v1\piv = cc\v1\piv And c\v2\piv = c\v1\piv Then
			Delete cc.constraint
		EndIf
	Next
Next


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;





End Function































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Creates a verlet at the given x,y,z coordinate;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function createverlet.verlet(x#,y#,z#,mass#,ent,ID,Active,radius# = .1)

	v.Verlet = New Verlet
	v\x# = x#
	v\y# = y#
	v\z# = z#
	v\ox# = v\x#
	v\oy# = v\y#
	v\oz# = v\z#
	v\vx# = 0
	v\vy# = 0
	v\vz# = 0
	v\ent = ent
	v\ID = ID
	v\active = Active
	v\mass# = mass#
	v\radius# = radius#
	v\fric# = .99
	
	v\piv = CreateSphere()
;	v\piv2 = CreatePivot()
	ScaleEntity v\piv,radius#,radius#,radius#
	EntityAlpha v\piv,0
	PositionEntity v\piv,v\x#,v\y#,v\z#
	
	If active = True Then
		EntityType v\piv,VerletType
		EntityRadius v\piv,radius#
	EndIf
	
	Return v
End Function































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;Constrains two verlets together;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function CreateConstraint(v1.verlet,v2.verlet)

	c.constraint = New constraint
	c\v1.verlet = v1.verlet
	c\v2.verlet = v2.verlet
	c\length# = Sqr((c\v1\x#-c\v2\x#)^2 + (c\v1\y#-c\v2\y#)^2 + (c\v1\z#-c\v2\z#)^2)

End Function






































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;goes through every verlet and updates it;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Updateverlets()

For v.verlet = Each verlet
	
	If v\col = True Then
		v\col = False
		fric# = v\fric#
	Else
		fric# = 1
	EndIf
	
	v\vx# = (v\x# - v\ox#)*fric#
	v\vy# = (v\y# - v\oy#)*fric#
	v\vz# = (v\z# - v\oz#)*fric#
	
	v\ox# = v\x#
	v\oy# = v\y#
	v\oz# = v\z#
	
	v\x# = v\x# + v\vx#
	v\y# = v\y# + v\vy# - .004
	v\z# = v\z# + v\vz#
	
	
	For vv.verlet = Each verlet
			If v <> vv And v\id <> vv\id; if not the same verlet or group
				dx# = v\x# - vv\x#
				dy# = v\y# - vv\y#
				dz# = v\z# - vv\z#
				dist# = Sqr ( dx#*dx# + dy#*dy# + dz#*dz# )		
				totalr# = v\radius# + vv\radius#
				If dist# < totalr# Then
				
					
					Diffx# = ( dist# - totalr# ) * ( dx# / dist# )
					Diffy# = ( dist# - totalr# ) * ( dy# / dist# )
					Diffz# = ( dist# - totalr# ) * ( dz# / dist# )

					v\x# = v\x# - Diffx# ;* .5
					v\y# = v\y# - Diffy# ;* .5
					v\z# = v\z# - Diffz# ;* .5

					vv\x# = vv\x# + Diffx# ;* .5
					vv\y# = vv\y# + Diffy# ;* .5
					vv\z# = vv\z# + Diffz# ;* .5
				EndIf 				
			EndIf
		Next 

;	If v\y# < 0 Then
;		v\y# = 0
;		v\col = True
;	EndIf
	
Next

End Function






















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;goes through every constraint and updates it;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function UpdateConstraints()

For i = 1 To 8

	For c.constraint = Each constraint
		mx# = ( c\v1\x# - c\v2\x# )
		my# = ( c\v1\y# - c\v2\y# )
		mz# = ( c\v1\z# - c\v2\z# )
		
		dist# = Sqr( (mx)^2 + (my)^2 + (mz)^2 )
		
		mx# = mx# / 2
		my# = my# / 2
		mz# = mz# / 2
		
		If dist# <> 0  Then
			dif# = (dist# - c\length#) / dist# * .7
		EndIf
		
	;	If c\v1\col = False Or i > 5 Then
			c\v1\x# = c\v1\x# - dif# * mx#
			c\v1\y# = c\v1\y# - dif# * my#
			c\v1\z# = c\v1\z# - dif# * mz#
	;	EndIf
	;	If c\v2\col = False Or i > 5 Then
			c\v2\x# = c\v2\x# + dif# * mx#
			c\v2\y# = c\v2\y# + dif# * my#
			c\v2\z# = c\v2\z# + dif# * mz#
	;	EndIf
	Next

Next

End Function





























;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;positions all verlets;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Drawverlets()

For v.verlet = Each verlet
	
	PositionEntity v\piv,v\x#,v\y#,v\z#
	
Next

End Function


















;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;positions all meshes;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function PositionPhysicsEntity()

For r.rigidbody = Each rigidbody
	PositionEntity r\ent,EntityX(r\c\piv),EntityY(r\c\piv),EntityZ(r\c\piv)
	
	;align mesh to verlet cage
	x# = EntityX( r\rf\piv ) - EntityX( r\rb\piv ) + EntityX( r\lf\piv ) - EntityX( r\lb\piv )
	y# = EntityY( r\rf\piv ) - EntityY( r\rb\piv ) + EntityY( r\lf\piv ) - EntityY( r\lb\piv )
	z# = EntityZ( r\rf\piv ) - EntityZ( r\rb\piv ) + EntityZ( r\lf\piv ) - EntityZ( r\lb\piv )
	AlignToVector r\ent, x#,y#,z#, 3
	x# = EntityX( r\rf\piv ) - EntityX( r\lf\piv ) + EntityX( r\rb\piv ) - EntityX( r\lb\piv )
	y# = EntityY( r\rf\piv ) - EntityY( r\lf\piv ) + EntityY( r\rb\piv ) - EntityY( r\lb\piv )
	z# = EntityZ( r\rf\piv ) - EntityZ( r\lf\piv ) + EntityZ( r\rb\piv ) - EntityZ( r\lb\piv )
	AlignToVector r\ent, x#,y#,z#,1
Next

End Function





































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;tests all verlets for collisions;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function Detectcollisions()

For v.verlet = Each verlet
	If EntityX(v\piv) <> v\x# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\x# = EntityX(v\piv)
	EndIf
	If EntityY(v\piv) <> v\y# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\y# = EntityY(v\piv)
	EndIf
	If EntityZ(v\piv) <> v\z# Then
		If EntityCollided(v\piv,3) Then
			v\col = True
		EndIf
		v\z# = EntityZ(v\piv)
	EndIf
Next

End Function




































;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;applies a force to given object;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Function PApplyForce(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\Verlnum
			r\verl[i]\ox# = r\verl[i]\ox# - x#
			r\verl[i]\oy# = r\verl[i]\oy# - y#
			r\verl[i]\oz# = r\verl[i]\oz# - z#
		Next
	EndIf
Next

End Function



Function PMoveEntity(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\verlnum
			r\verl[cnt]\ox# = r\verl[cnt]\ox# + x#
			r\verl[cnt]\oy# = r\verl[cnt]\oy# + y#
			r\verl[cnt]\oz# = r\verl[cnt]\oz# + z#
			r\verl[cnt]\x# = r\verl[cnt]\x# + x#
			r\verl[cnt]\y# = r\verl[cnt]\y# + y#
			r\verl[cnt]\z# = r\verl[cnt]\z# + z#
		Next
	EndIf
Next

End Function



Function PPositionEntity(ent,x#,y#,z#)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		For i = 0 To r\verlnum
			r\verl[cnt]\ox# = r\verl[cnt]\ox# + (r\verl[cnt]\ox# - x#)
			r\verl[cnt]\oy# = r\verl[cnt]\oy# + (r\verl[cnt]\oy# - y#)
			r\verl[cnt]\oz# = r\verl[cnt]\oz# + (r\verl[cnt]\oz# - z#)
			r\verl[cnt]\x# = r\verl[cnt]\x# + (r\verl[cnt]\x# - x#)
			r\verl[cnt]\y# = r\verl[cnt]\y# + (r\verl[cnt]\y# - y#)
			r\verl[cnt]\z# = r\verl[cnt]\z# + (r\verl[cnt]\z# - z#)
		Next
	EndIf
Next

End Function


Use scalemesh instead of scaleentity

tmpcar = CreateCube()
ScaleMesh tmpcar,1,.1,2
EntityColor tmpcar,20,100,255


As soon as you parent something to a scaled entity it adopts that scale

Also do this ..

tmpwheel = CreateCylinder(5)
RotateMesh tmpwheel,0,0,90
ScaleMesh tmpwheel,.2,.4,.4
EntityColor tmpwheel,10,10,10
EntityRadius tmpwheel,.3
MoveEntity tmpwheel,0,-.7,0


thnx stevie g it worked.

So what would the best method for detecting inversion in a verlet system be? I've seen lots of places where people say that's what needs to be done but none which say how to do it (efficiently)