Physics engine

Blitz3D Forums/Blitz3D Beginners Area/Physics engine

I added a lot of comments and added some functions and gave the plane a collision type to test if it worked.

I think it would really help if you would step back a bit and try to get a more simple example working.


Just did that! :)

you will notice that it is kind of bouncy but I like it like that. It makes it look more homemade and that is good

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


cam = CreateCamera()
MoveEntity cam,0,0,-20
CameraZoom cam,2
CameraFogMode cam,1
CameraFogRange cam,20,100
CameraRange cam,.001,100
;CameraClsColor cam,100,100,100
;CameraFogColor cam,100,100,100

piv = CreatePivot()
EntityParent cam,piv
;TurnEntity piv,0,180,0
plane = CreatePlane()
EntityType plane,2
EntityPickMode plane,0
tex = CreateTexture(256,256)
SetBuffer TextureBuffer(tex)
Color 255,255,255
Rect 0,0,128,128,1
Rect 128,128,128,128
Color 0,225,0
Rect 0,128,128,128
Rect 128,0,128,128
Color 255,255,255

mir = CreateMirror()
MoveEntity mir,0,-4,0

SetBuffer BackBuffer()
EntityTexture plane,tex
MoveEntity plane,0,-4,0
ScaleTexture tex,10,10
EntityAlpha plane,.5

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



;Types

Type verlet
	Field x#,y#,z#
	Field vx#,vy#,vz#
	Field ox#,oy#,oz#
	Field ent,piv
	Field collided,ID,mass#
	Field surf,index
End Type


Type rigidbody
	Field x#,y#,z#,ent
	Field yaw#,pitch#,roll#
	Field v1.verlet,v2.verlet,v3.verlet,v4.verlet,v5.verlet,v6.verlet,v7.verlet,v8.verlet,cpiv
	Field ID
End Type


Type constraint
	Field p1.verlet
	Field p2.verlet
	Field ent
	Field length#
End Type

Global rigidbodynum = 0

Global cube = CreateCube()
EntityAlpha cube,1
Applyphysicscube(cube,10)


Collisions 1,2,2,1

;Global cube2 = CreateCube()
;MoveEntity cube2,0,3,0
;applyphysicscube(cube2,10)

SetBuffer BackBuffer()

tim = MilliSecs()


While Not KeyDown(1)
Cls

If KeyDown(200) Then MoveEntity cam,0,0,.1
If KeyDown(208) Then MoveEntity cam,0,0,-.1
If KeyDown(203) Then MoveEntity cam,-.1,0,0
If KeyDown(205) Then MoveEntity cam,.1,0,0

TurnEntity piv,0,1,0

updateverlets()

updateconstraints()

equalizeverlets()

drawstuff()

UpdateWorld()
RenderWorld()

cnt = 0
For v.verlet = Each verlet
	cnt = cnt + 1
Next
Text 1,20,"Verticies: "+cnt
Text 1,1,"FPS: "+1000/(MilliSecs()-tim)
tim = MilliSecs()

Flip

Wend

WaitKey()

End



Function Applyphysicscube(ent,mass#,idle = 0,siz# = 5)

rigidbodynum = rigidbodynum + 1

alph = 0


;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,1000-r\ID
EntityPickMode r\ent,2

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






;Loops through all surfaces and verticies
For k = 1 To CountSurfaces(ent)
	surf = GetSurface(ent,k)
	For index = 0 To CountVertices(surf)-1
		CreateVerlet(ent,surf,index,mass#)   ;Creates a verlet for every vertice  Later it deletes duplicate verlets for the sake of stability.
	Next
Next

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






;The following code creates collisions for the rigidbodies and their verlets
;For i = 1 To rigidbodynum
;	If i <> rigidbodynum Then
;		Collisions rigidbodynum,1000-i,2,1
;	EndIf
;Next

;For i = 1 To rigidbodynum
;	If i <> rigidbodynum Then
;		Collisions i,1000-rigidbodynum,2,1
;	EndIf
;Next
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




;This code makes the bounding box vertices which are used to orient the object when it is given rotational velocity
r\v1.verlet = New verlet
r\v1\id = rigidbodynum
r\v1\x# = r\x#-MeshWidth(r\ent)/2
r\v1\y# = r\y#-MeshHeight(r\ent)/2
r\v1\z# = r\z#+MeshDepth(r\ent)/2
r\v1\ox# = r\x#-MeshWidth(r\ent)/2
r\v1\oy# = r\y#-MeshHeight(r\ent)/2
r\v1\oz# = r\z#+MeshDepth(r\ent)/2
r\v1\ent = r\ent
r\v1\mass# = 0
r\v1\piv = CreatePivot()
;EntityAlpha r\v1\piv,alph
PositionEntity r\v1\piv,r\v1\x#,r\v1\y#,r\v1\z#

r\v2.verlet = New verlet
r\v2\id = rigidbodynum
r\v2\x# = r\x#+MeshWidth(r\ent)/2
r\v2\y# = r\y#-MeshHeight(r\ent)/2
r\v2\z# = r\z#+MeshDepth(r\ent)/2
r\v2\ox# = r\x#+MeshWidth(r\ent)/2
r\v2\oy# = r\y#-MeshHeight(r\ent)/2
r\v2\oz# = r\z#+MeshDepth(r\ent)/2
r\v2\ent = r\ent
r\v2\mass# = 0
r\v2\piv = CreatePivot()
;EntityAlpha r\v2\piv,alph
PositionEntity r\v2\piv,r\v2\x#,r\v2\y#,r\v2\z#

r\v3.verlet = New verlet
r\v3\id = rigidbodynum
r\v3\x# = r\x#+MeshWidth(r\ent)/2
r\v3\y# = r\y#-MeshHeight(r\ent)/2
r\v3\z# = r\z#-MeshDepth(r\ent)/2
r\v3\ox# = r\x#+MeshWidth(r\ent)/2
r\v3\oy# = r\y#-MeshHeight(r\ent)/2
r\v3\oz# = r\z#-MeshDepth(r\ent)/2
r\v3\ent = r\ent
r\v3\mass# = 0
r\v3\piv = CreatePivot()
;EntityAlpha r\v3\piv,alph
PositionEntity r\v3\piv,r\v3\x#,r\v3\y#,r\v3\z#

r\v4.verlet = New verlet
r\v4\id = rigidbodynum
r\v4\x# = r\x#-MeshWidth(r\ent)/2
r\v4\y# = r\y#-MeshHeight(r\ent)/2
r\v4\z# = r\z#-MeshDepth(r\ent)/2
r\v4\ox# = r\x#-MeshWidth(r\ent)/2
r\v4\oy# = r\y#-MeshHeight(r\ent)/2
r\v4\oz# = r\z#-MeshDepth(r\ent)/2
r\v4\ent = r\ent
r\v4\mass# = 0
r\v4\piv = CreatePivot()
;EntityAlpha r\v4\piv,alph
PositionEntity r\v4\piv,r\v4\x#,r\v4\y#,r\v4\z#

r\v5.verlet = New verlet
r\v5\id = rigidbodynum
r\v5\x# = r\x#-MeshWidth(r\ent)/2
r\v5\y# = r\y#+MeshHeight(r\ent)/2
r\v5\z# = r\z#+MeshDepth(r\ent)/2
r\v5\ox# = r\x#-MeshWidth(r\ent)/2
r\v5\oy# = r\y#+MeshHeight(r\ent)/2
r\v5\oz# = r\z#+MeshDepth(r\ent)/2-.5
r\v5\ent = r\ent
r\v5\mass# = 0
r\v5\piv = CreatePivot()
;EntityAlpha r\v5\piv,alph
PositionEntity r\v5\piv,r\v5\x#,r\v5\y#,r\v5\z#

r\v6.verlet = New verlet
r\v6\id = rigidbodynum
r\v6\x# = r\x#+MeshWidth(r\ent)/2
r\v6\y# = r\y#+MeshHeight(r\ent)/2
r\v6\z# = r\z#+MeshDepth(r\ent)/2
r\v6\ox# = r\x#+MeshWidth(r\ent)/2
r\v6\oy# = r\y#+MeshHeight(r\ent)/2
r\v6\oz# = r\z#+MeshDepth(r\ent)/2
r\v6\ent = r\ent
r\v6\mass# = 0
r\v6\piv = CreatePivot()
;EntityAlpha r\v6\piv,alph
PositionEntity r\v6\piv,r\v6\x#,r\v6\y#,r\v6\z#

r\v7.verlet = New verlet
r\v7\id = rigidbodynum
r\v7\x# = r\x#+MeshWidth(r\ent)/2
r\v7\y# = r\y#+MeshHeight(r\ent)/2
r\v7\z# = r\z#-MeshDepth(r\ent)/2
r\v7\ox# = r\x#+MeshWidth(r\ent)/2
r\v7\oy# = r\y#+MeshHeight(r\ent)/2
r\v7\oz# = r\z#-MeshDepth(r\ent)/2
r\v7\ent = r\ent
r\v7\mass# = 0
r\v7\piv = CreatePivot()
;EntityAlpha r\v7\piv,alph
PositionEntity r\v7\piv,r\v7\x#,r\v7\y#,r\v7\z#

r\v8.verlet = New verlet
r\v8\id = rigidbodynum
r\v8\x# = r\x#-MeshWidth(r\ent)/2
r\v8\y# = r\y#+MeshHeight(r\ent)/2
r\v8\z# = r\z#-MeshDepth(r\ent)/2
r\v8\ox# = r\x#-MeshWidth(r\ent)/2
r\v8\oy# = r\y#+MeshHeight(r\ent)/2
r\v8\oz# = r\z#-MeshDepth(r\ent)/2
r\v8\ent = r\ent
r\v8\mass# = 0
r\v8\piv = CreatePivot()
;EntityAlpha r\v8\piv,alph
PositionEntity r\v8\piv,r\v8\x#,r\v8\y#,r\v8\z#

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






r\cpiv = CreatePivot()
PositionEntity r\cpiv,r\x#,r\y#,r\z#





;Deletes Duplicate verlets so that the meshes are more stable

For v.verlet = Each verlet
	For vv.verlet = Each verlet
		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
				Delete vv.verlet
			EndIf
		EndIf
	Next
Next

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







;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 idle = 0 Then
			For vv.verlet = Each verlet
				If vv\id = rigidbodynum Then
					If vv\piv <> v\piv
						If vv\mass# = 0 And v\mass > 0 Then
							c.constraint = New constraint
							c\p1.verlet = v.verlet
							c\p2.verlet = vv.verlet
							dx# = c\p1\x# - c\p2\x#
							dy# = c\p1\y# - c\p2\y#
							dz# = c\p1\z# - c\p2\z#
							c\length# = Sqr(dx#*dx# + dy#*dy# + dz#*dz#)
							c\ent = c\p1\ent
						EndIf
					EndIf
				EndIf
			Next
		EndIf
	EndIf
Next
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;








;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\p1\piv = cc\p1\piv And c\p2\piv = c\p1\piv Then
			Delete cc.constraint
		EndIf
	Next
Next


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





End Function





















Function updateverlets()


For v.verlet = Each verlet
		v\collided = False
		v\vx# = (v\x# - v\ox#)*.98 ; Get the velocities of the verlet,...add a bit of decay to simulate friction
		v\vy# = (v\y# - v\oy#)*.98
		v\vz# = (v\z# - v\oz#)*.98
		
		If v\vx# > -.001 And v\vx# < .001 Then
			If v\vy# > -.001 And v\vy# < .001 Then
				If v\vz# > -.001 And v\vz# < .001 Then
					v\vx# = 0
					v\vy# = 0
					v\vz# = 0
				EndIf
			EndIf
		EndIf
		v\ox# = v\x# ; store position in "old"
		v\oy# = v\y#
		v\oz# = v\z#
		
	;	If v\collided = False Then
			v\x# = v\x# + v\vx# ;store new postion based on velocity
		
			v\y# = v\y# + v\vy# - .007
		
			v\z# = v\z# + v\vz#
	;	EndIf
		
	;	If v\mass > 0 Then
	;		;check screen bounds
	;		If v\y#	< -4 ;ground collision
	;			v\y# = -4
	;			v\collided = True
	;			v\vy# = -v\vy#
	;		EndIf
	;	EndIf
Next

End Function
























Function drawstuff()
	;For v.verlet = Each verlet
		;VertexCoords v\surf,v\index,v\x#,v\y#,v\z#
	;Next
	
	For r.rigidbody = Each rigidbody
		cnt = 0
		avgx# = 0
		avgy# = 0
		avgz# = 0
		For v.verlet = Each verlet
			If v\ent = r\ent
				cnt = cnt + 1
				avgx# = avgx# + v\x#
				avgy# = avgy# + v\y#
				avgz# = avgz# + v\z#
				PositionEntity v\piv,v\x#,v\y#,v\z#
			EndIf
		Next
		avgx# = avgx#/cnt
		avgy# = avgy#/cnt
		avgz# = avgz#/cnt
		
		r\x# = avgx#
		r\y# = avgy#
		r\z# = avgz#
		
		RotateEntity r\ent,0,0,0
		PositionEntity r\ent,avgx#,avgy#,avgz#
		
		cnt = 0
		avgyaw =0
		avgpitch = 0
		avgroll = 0
		
		
		;this computes the orientation of the verticies using stevie g's code  Thnx Stevie G!!!
			
			;align mesh to verlet cage
			
			x# = EntityX( r\v6\piv ) - EntityX( r\v5\piv ) + EntityX( r\v7\piv ) - EntityX( r\v8\piv )
			y# = EntityY( r\v6\piv ) - EntityY( r\v5\piv ) + EntityY( r\v7\piv ) - EntityY( r\v8\piv )
			z# = EntityZ( r\v6\piv ) - EntityZ( r\v5\piv ) + EntityZ( r\v7\piv ) - EntityZ( r\v8\piv )
			AlignToVector r\ent, x#,y#,z#,1  
			x# = EntityX( r\v6\piv ) - EntityX( r\v7\piv ) + EntityX( r\v5\piv ) - EntityX( r\v8\piv )
			y# = EntityY( r\v6\piv ) - EntityY( r\v7\piv ) + EntityY( r\v5\piv ) - EntityY( r\v8\piv )
			z# = EntityZ( r\v6\piv ) - EntityZ( r\v7\piv ) + EntityZ( r\v5\piv ) - EntityZ( r\v8\piv )
			AlignToVector r\ent, x#,y#,z#, 3
		;	x# = EntityX( r\v4\piv ) - EntityX( r\v1\piv )   ;align to a third vector
		;	y# = EntityY( r\v4\piv ) - EntityY( r\v1\piv )
		;	z# = EntityZ( r\v4\piv ) - EntityZ( r\v1\piv )
		;	AlignToVector r\ent, X#,y#,z#, 2
	Next
	UpdateWorld()
	For v.verlet = Each verlet
		If v\mass# > 0 Then
			If EntityX(v\piv) <> v\x# Or EntityY(v\piv) <> v\y# Or EntityZ(v\piv) <> v\z# Then
				v\collided = True
				v\x# = EntityX(v\piv)
				v\y# = EntityY(v\piv)
				v\z# = EntityZ(v\piv)
			EndIf
		EndIf
	Next

End Function


















;Updates the constraints and deals a little with collisions


Function updateconstraints()

For a = 1 To 10
	For c.constraint = Each constraint
		dx#=c\p2\x#	-	c\p1\x#
		dy#=c\p2\y#	-	c\p1\y#
		dz#=c\p2\z#	-	c\p1\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
		Else
			diff# = 0
		EndIf

		dx# = dx# * .5 ;find the midpoint
		dy# = dy# * .5
		dz# = dz# * .5
		
		If c\p1\collided = 0 Or a > 8 Then
			c\p1\x# = c\p1\x# + diff# * dx# 
			c\p1\y# = c\p1\y# + diff# * dy#
			c\p1\z# = c\p1\z# + diff# * dz#
		EndIf
		If c\p2\collided = 0 Or a > 8 Then
			c\p2\x# = c\p2\x# - diff# * dx#
			c\p2\y# = c\p2\y# - diff# * dy#
			c\p2\z# = c\p2\z# - diff# * dz#
		EndIf
	Next  ;constraints
Next


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


End Function





















Function equalizeverlets()

;For c.constraint = Each constraint
;	If c\length# = 0 Then
;		dx#=c\p2\x#	+	c\p1\x#
;		dy#=c\p2\y#	+	c\p1\y#
;		dz#=c\p2\z#	+	c\p1\z#
;		
;		dx# = dx# * .5 ;find the midpoint                ;This function, I have found could be useful for other projects but not for this one so I saved the code
;		dy# = dy# * .5
;		dz# = dz# * .5
;		
;		c\p2\x# = dx#
;		c\p2\y# = dy#
;		c\p2\z# = dz#
;		
;		c\p1\x# = dx#
;		c\p1\y# = dy#
;		c\p1\z# = dz#
;		
;	EndIf
;Next

End Function

























;Soon to be code that rotates the verlets of a rigidbody as well as the entity.
Function rotatephysicsentity(ent)

For r.rigidbody = Each rigidbody
	If r\ent = ent Then
		tmppiv = CreatePivot()
		PositionEntity tmppiv,r\x#,r\y#,r\z#
	EndIf
Next

End Function


























;Creates a Verlet  Duh  :)
Function CreateVerlet(ent,surf,index,mass#)

		TFormPoint VertexX(surf,index), VertexY(surf, index),VertexZ(surf, index), ent, 0
		v.verlet = New verlet
		v\piv = CreatePivot()
		v\x# = TFormedX()
		v\y# = TFormedY()
		v\z# = TFormedZ()
		PositionEntity v\piv,v\x#,v\y#,v\z#
		v\ox# = v\x#
		v\oy# = v\y#
		v\oz# = v\z#
		v\ent = ent
		v\surf = surf
		v\index = index
		v\collided =0
		v\ID = rigidbodynum
		v\mass# = mass#/(CountSurfaces(ent)*CountVertices(surf))
		EntityType v\piv,v\ID
	
		EntityRadius v\piv,.1


End Function



Pongo, how is your code? have you changed it recently or gotten 3d meshes to align themselves to you verlet cage? I would like to see how far you have gotten

@Stevie G. and Pongo
You have both been a great help so far thanks for all of the great advice and advising me on how to create a physics engine. I would have given up a long time ago if it wasn't for you