Verlet Help

Blitz3D Forums/Blitz3D Beginners Area/Verlet Help

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Verlets are simply a system of doing physics that work by linking several points with constraints. Each loop through the constraints are satisfied several times.

There is a good explanation of how things work here:
http://www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml


Here is a simple b3d example

Global screen_w = 1024
Global screen_h = 768
Global gravity# = .25

Graphics3D screen_w,screen_h,0,2
SetBuffer BackBuffer()

SeedRnd MilliSecs()
timer = CreateTimer (60) ; lock game fps to this

Type vector3
	Field x#
	Field y#
	Field z#
End Type

Type Verlet
	Field pos.vector3	; verlet position
	Field vel.vector3	; verlet velocity
	Field old.vector3 ; store the previous pos here
	Field radius ; size of verlet
	Field id ;use to identify groups
	Field collide ; is this colliding?
	Field pivot ; pivot for operations
End Type

Type constraint
	Field p1.verlet
	Field p2.verlet
	Field length#
	Field mesh ; display line
End Type 

campivot = CreatePivot()
cam = CreateCamera(campivot)
CameraZoom cam,2
MoveEntity cam,0,200,500
PointEntity cam,campivot

light = CreateLight()
;PositionEntity light,0,100,-50
RotateEntity light,90,0,0

Global arenabounds = 200

wall1 = CreateCube()
PositionEntity wall1,-arenabounds,0,0
ScaleEntity wall1,1,1,arenabounds
wall2 = CreateCube()
PositionEntity wall2,arenabounds,0,0
ScaleEntity wall2,1,1,arenabounds
wall3 = CreateCube()
PositionEntity wall3,0,0,arenabounds
ScaleEntity wall3,arenabounds,1,1
wall4 = CreateCube()
PositionEntity wall4,0,0,-arenabounds
ScaleEntity wall4,arenabounds,1,1

ground = CreatePlane()
EntityColor ground,32,32,64
EntityAlpha ground, .9
mirror = CreateMirror()

definePyramid()

;CreateVerlet.verlet (xpos,ypos,size,id)
Global v1.verlet = CreateVerlet (10,0,10,8,1)
Global v2.verlet = CreateVerlet(10,0,-10,8,1)
Global v3.verlet = CreateVerlet (-10,0,10,8,1)
Global v4.verlet = CreateVerlet(-10,0,-10,8,1)
Global v5.verlet = CreateVerlet(0,20,0,8,1)

ConstrainVerlet (v1,v2)
ConstrainVerlet(v2,v3)
ConstrainVerlet(v1,v3)
ConstrainVerlet(v1,v4)
ConstrainVerlet(v2,v4)
ConstrainVerlet(v3,v4)
ConstrainVerlet(v1,v5)
ConstrainVerlet(v2,v5)
ConstrainVerlet(v3,v5)
ConstrainVerlet(v4,v5)

EntityColor v1\pivot,160,32,32

While Not KeyHit(1)
	WaitTimer(Timer) ; Pause until the timer reaches 60 (caps the game framerate on faster systems)

	; move verlet 1 based on arrow keys
	v1\pos\z =	v1\pos\z + (KeyDown(208) - KeyDown(200) ) * .8
	v1\pos\x =	v1\pos\x + (KeyDown(203) - KeyDown(205) ) * .8
	v1\pos\y =  	v1\pos\y + KeyDown(57) * 2

	UpdateVerlets()
	UpdateConstraints()
	positionstuff()

	UpdateWorld()
	RenderWorld()

	Text 20,20,"use arrow keys and space bar to move verlet cage"

	Flip()
	Cls()
Wend

End 


Function definePyramid()
;CreateVerlet.verlet (xpos,ypos,size,id)
v11.verlet = CreateVerlet (10,20,10,8,2)
v12.verlet = CreateVerlet(10,20,-10,8,2)
v13.verlet = CreateVerlet (-10,20,10,8,2)
v14.verlet = CreateVerlet(-10,20,-10,8,2)
v15.verlet = CreateVerlet(0,40,0,8,2)

ConstrainVerlet (v11,v12)
ConstrainVerlet(v12,v13)
ConstrainVerlet(v11,v13)
ConstrainVerlet(v11,v14)
ConstrainVerlet(v12,v14)
ConstrainVerlet(v13,v14)
ConstrainVerlet(v11,v15)
ConstrainVerlet(v12,v15)
ConstrainVerlet(v13,v15)
ConstrainVerlet(v14,v15)
End Function

Function CreateVerlet.verlet (xpos,ypos,zpos,size,id)
	v.verlet=New verlet
	v\pos = New vector3
	v\pos\x = xpos
	v\pos\y = ypos
	v\pos\z = zpos
	v\vel = New vector3
	v\vel\x = 0
	v\vel\y = 0
	v\vel\z = 0
	v\old = New vector3
	v\old\x = xpos
	v\old\y = ypos
	v\old\z = zpos
	v\radius = size
	v\id = id

	v\pivot = CreateSphere()
	ScaleEntity v\pivot,size,size,size
	Return v
End Function 

Function ConstrainVerlet.constraint (head.verlet,	tail.verlet)
	Local dx#,dy#,dz#

	;this creates a new constraint and sets the length equal to the current distance between the verlets
	c.constraint = New constraint
	c\p1.verlet = head.verlet
	c\p2.verlet = tail.verlet

	dx = c\p1\pos\x - c\p2\pos\x
	dy = c\p1\pos\y - c\p2\pos\y
	dz = c\p1\pos\z - c\p2\pos\z
	c\length = Sqr ( dx*dx + dy*dy + dz*dz )
	
	c\mesh = CreateCube()
	ScaleEntity c\mesh,.2,.2,c\length * .5
	PositionMesh c\mesh,0,0,1
	;DebugLog c\length
	Return c
End Function

Function UpdateVerlets()
	Local dx#,dy#,dz#,dist#
	For v.verlet = Each verlet
		v\collide = False
		v\vel\x = (v\pos\x - v\old\x)*.985 ; Get the velocities of the verlet,...add a bit of decay to simulate friction
		v\vel\y = (v\pos\y - v\old\y)*.985
		v\vel\z = (v\pos\z - v\old\z)*.985

		v\old\x = v\pos\x ; store position in "old"
		v\old\y = v\pos\y
		v\old\z = v\pos\z
		
		v\pos\x = v\pos\x + v\vel\x ;store new postion based on velocity
		v\pos\y = v\pos\y + v\vel\y - gravity
		v\pos\z = v\pos\z + v\vel\z


For vv.verlet = Each verlet
			If v <> vv And v\id <> vv\id; if not the same verlet or group
				dx = v\pos\x - vv\pos\x
				dy = v\pos\y - vv\pos\y
				dz = v\pos\z - vv\pos\z
				dist = Sqr ( dx*dx + dy*dy + dz*dz)
				TotalRadius# = v\radius + vv\radius		
				If dist < Totalradius
				
					
					Diffx# = ( dist - TotalRadius ) * ( dx / dist )
					Diffy# = ( dist - TotalRadius ) * ( dy / dist )
					Diffz# = ( dist - TotalRadius ) * ( dz / dist )

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

					vv\pos\x = vv\pos\x + Diffx ;* .5
					vv\pos\y = vv\pos\y + Diffy ;* .5
					vv\pos\z = vv\pos\z - Diffz ;* .5

					v\collide = True
				EndIf 				
			EndIf
		Next 


		;check screen bounds
		If v\pos\y	<	v\radius ;ground collision
			v\pos\y=	v\radius
			v\collide = True
		EndIf

		If v\pos\x >arenabounds Then v\pos\x = arenabounds
		If v\pos\x < -arenabounds Then v\pos\x = -arenabounds
		If v\pos\z >arenabounds Then v\pos\z = arenabounds
		If v\pos\z < -arenabounds Then v\pos\z = -arenabounds
		
	Next
End Function

Function UpdateConstraints()
	Local dx#,dy#,dz#,length#,diff#

	For loop = 1 To 5 ;iterations
		For c.constraint = Each constraint
			dx=c\p2\pos\x	-	c\p1\pos\x
			dy=c\p2\pos\y	-	c\p1\pos\y
			dz=c\p2\pos\z	-	c\p1\pos\z
					
			length=Sqr(dx*dx + dy*dy + dz*dz) ; distance between p1 and p2
	
			If length<>0 ;avoid divide by 0, then normalize the vector
				diff = (length - c\length) / length ; vector length minus constraint length
			EndIf
	
			dx = dx * .5 ;find the midpoint
			dy = dy * .5
			dz = dz * .5
	
			c\p1\pos\x = c\p1\pos\x + diff * dx 
			c\p1\pos\y = c\p1\pos\y + diff * dy
			c\p1\pos\z = c\p1\pos\z + diff * dz

			c\p2\pos\x = c\p2\pos\x - diff * dx
			c\p2\pos\y = c\p2\pos\y - diff * dy
			c\p2\pos\z = c\p2\pos\z - diff * dz

		Next  ;constraints
	Next ;iterations
End Function 

Function positionstuff()
		For v.verlet = Each verlet
			EntityColor v\pivot,255,255,255
			If v\collide = True Then	EntityColor v\pivot,128,0,0
			PositionEntity v\pivot, v\pos\x, v\pos\y, v\pos\z
		Next

		For c.constraint = Each constraint
			PositionEntity c\mesh, c\p1\pos\x, c\p1\pos\y, c\p1\pos\z
			PointEntity c\mesh ,c\p2\pivot
		Next
End Function