Try these physics.

Blitz3D Forums/Blitz3D Programming/Try these physics.

JoshK(Posted 2003) [#1]
This is a wonderful collision and velocity routine that is easy to plug into an existing program. All you do is create a physics type for your entity, then call UpdatePhysics every loop instead of UpdateWorld.

The collision uses Blitz's collision, but manages to overcome a few of the weaknesses. Sliding, bouncing collisions will occur, depending on the elasticity you give the physics type.

This should be very useful as a base for more advanced physics.

Graphics3D 800,600,16,2
SetBuffer BackBuffer()

cam=CreateCamera()
MoveEntity cam,0,15,-20
TurnEntity cam,35,0,0

g=CreateCube()
ScaleMesh g,10,10,10
FlipMesh g

EntityType g,2

r=2
m=CreateSphere()
EntityShininess m,1
EntityType m,1
EntityRadius m,r
ScaleEntity m,r,r,r
EntityColor m,255,0,0

Collisions 1,2,2,2
Collisions 1,1,2,2

RotateEntity CreateLight(),25,45,0

Type physics
Field mesh
Field velocity#[5]
Field position#[5]
Field elasticity#
End Type

balls=3

For n=1 To balls
	ph.physics=New physics
	ph\mesh=CopyEntity(m)
	ph\velocity[0]=Rnd(-.5,.5)
	ph\velocity[1]=Rnd(-1,1)
	ph\velocity[2]=Rnd(-.5,.5)	
	;PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8)
	ResetEntity ph\mesh
	ph\elasticity#=0.95
	EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
	Next

HideEntity m

period=1000/60
time=MilliSecs()-period

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 KeyHit(28)
			ph.physics=New physics
			ph\mesh=CopyEntity(m)
			ph\velocity[0]=Rnd(-.5,.5)
			ph\velocity[1]=Rnd(-1,1)
			ph\velocity[2]=Rnd(-.5,.5)	
			;PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8)
			ScaleEntity ph\mesh,r,r,r
			EntityRadius ph\mesh,r
			ResetEntity ph\mesh
			ph\elasticity#=0.95
			EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
			balls=balls+1
			EndIf
			
		If KeyHit(57)
			For ph.physics=Each physics
				ph\velocity[0]=Rnd(-.5,.5)
				ph\velocity[1]=Rnd(-2,2)
				ph\velocity[2]=Rnd(-.5,.5)
				Next
			EndIf
		
		UpdatePhysics
		
		Next
		
	RenderWorld
	Text 0,0,fps()
	Text 0,20,"Press space to reset balls."
	Text 0,40,"Press enter to add a ball."
	Text 0,60,balls+" balls exist."
	Flip
	
	Wend
	
Function UpdatePhysics()

friction#=0.99;sliding friction
staticfriction#=0.0001;minimum velocity before an objects starts sticking

For ph.physics=Each physics
		
	ph\position[0]=EntityX(ph\mesh,1)
	ph\position[1]=EntityY(ph\mesh,1)
	ph\position[2]=EntityZ(ph\mesh,1)
	
	;gravity	
	ph\velocity[1]=ph\velocity[1]-0.03
	
	;carry out velocity
	TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1	

	ph\position[3]=EntityX(ph\mesh,1)
	ph\position[4]=EntityY(ph\mesh,1)
	ph\position[5]=EntityZ(ph\mesh,1)

	Next

UpdateWorld

;correct velocity
For ph.physics=Each physics

	ax#=(EntityX(ph\mesh,1)-ph\position[3])
	ay#=(EntityY(ph\mesh,1)-ph\position[4])
	az#=(EntityZ(ph\mesh,1)-ph\position[5])
	
	PositionEntity ph\mesh,ph\position[3],ph\position[4],ph\position[5],1

	ph\velocity[0]=(EntityX(ph\mesh,1)-ph\position[0]+ax*ph\elasticity)
	ph\velocity[1]=(EntityY(ph\mesh,1)-ph\position[1]+ay*ph\elasticity)
	ph\velocity[2]=(EntityZ(ph\mesh,1)-ph\position[2]+az*ph\elasticity)

	TranslateEntity ph\mesh,ax*(1.0-ph\elasticity),ay*(1.0-ph\elasticity),az*(1.0-ph\elasticity)
				
	Next

;transfer inertia
For ph.physics=Each physics
	For c=1 To CountCollisions(ph\mesh)
		If GetEntityType(CollisionEntity(ph\mesh,c))=1

			;lose some energy as heat for each collision
			ph\velocity[0]=ph\velocity[0]*.98
			ph\velocity[1]=ph\velocity[1]*.98
			ph\velocity[2]=ph\velocity[2]*.98

			;hmmm...should the collision normals be absolute value or not?
			nx#=Abs(CollisionNX(ph\mesh,c))
			ny#=Abs(CollisionNY(ph\mesh,c))
			nz#=Abs(CollisionNZ(ph\mesh,c))
			ph2.physics=findphysics(CollisionEntity(ph\mesh,c))
			ph2\velocity[0]=ph2\velocity[0]+(nx)*ph\velocity[0]/2.0
			ph2\velocity[1]=ph2\velocity[1]+(ny)*ph\velocity[1]/2.0
			ph2\velocity[2]=ph2\velocity[2]+(nz)*ph\velocity[2]/2.0
			ph\velocity[0]=ph\velocity[0]-(nx)*ph\velocity[0]/2.0
			ph\velocity[1]=ph\velocity[1]-(ny)*ph\velocity[1]/2.0
			ph\velocity[2]=ph\velocity[2]-(nz)*ph\velocity[2]/2.0
			EndIf
		Next
	Next	

;add friction
For ph.physics=Each physics
	If EntityCollided(ph\mesh,2)
		;sliding friction
		ph\velocity[0]=ph\velocity[0]*friction
		ph\velocity[1]=ph\velocity[1]*friction
		ph\velocity[2]=ph\velocity[2]*friction
		;static friction
		If Abs(ph\velocity[0])<staticfriction# ph\velocity[0]=0.0
		If Abs(ph\velocity[1])<staticfriction# ph\velocity[1]=0.0
		If Abs(ph\velocity[2])<staticfriction# ph\velocity[2]=0.0
		EndIf
	Next

End Function

Function FindPhysics.physics(e)
For ph.physics=Each physics
	If ph\mesh=e Return ph
	Next
Return Null
End Function

Global FPS_fpstime

Function FPS()
oldtime=FPS_fpstime
FPS_fpstime=MilliSecs()
elapsed=FPS_fpstime-oldtime
If Not elapsed elapsed=1
FPS_fps=1000/elapsed
Return FPS_FPS
End Function



Physt(Posted 2003) [#2]
Interesting! Nice work.

I had the same problem with my phyics routine and what I ended up doing was stuffing the handle of the type into the name of the mesh.

Function FindPhysics.physics(e)
For ph.physics=Each physics
	If ph\mesh=e Return ph
	Next
Return Null
End Function


   NameEntity someMesh, str(handle(SomeType))


then I retrieve it by
 object.SomeType EntityName(someMesh)


Handle and Object are unsupported but it does save the search.

I also added an active flag so that object that were resting on the floor and had no velocity would not need to be updated each tic.

I used my code to add pushable object to a 3d platform game but still have issues with the player being able to sometime push his way into objects. It works correct almost 99% percent of the time but it's still not acceptable. I may try to drop in your routines and see what I can do.


JoshK(Posted 2003) [#3]
I have used names before to attach properties, but I suspect that converting a string to a number would be slow.

I updated the program. This is MUCH BETTER. I can now handle 200 balls. The collisions are perfect, and it is written in such a way that adding inertia and mass would be easy. As of now, all balls just have the same mass.

Graphics3D 800,600,16,2
SetBuffer BackBuffer()

cam=CreateCamera()
;MoveEntity cam,0,-8,-20
MoveEntity cam,0,15,-20
TurnEntity cam,35,0,0

g=CreateCube()
ScaleMesh g,10,10,10
FlipMesh g
EntityType g,2

r=1
m=CreateSphere()
EntityShininess m,1
EntityType m,1
EntityRadius m,r
ScaleEntity m,r,r,r
EntityColor m,255,0,0

Collisions 1,2,2,2
Collisions 1,1,1,2

RotateEntity CreateLight(),25,45,0

Global gravity=True

Type physics
Field mesh
Field velocity#[5]
Field elasticity#
Field mass#
End Type

balls=5
e#=0.9

For n=1 To balls
	ph.physics=New physics
	ph\mesh=CopyEntity(m)
	ph\velocity[0]=Rnd(-.5,.5)
	ph\velocity[1]=Rnd(-1,1)
	ph\velocity[2]=Rnd(-.5,.5)	
	PositionEntity ph\mesh,Rnd(-8,8),-8,Rnd(-8,8)
	ResetEntity ph\mesh
	ph\elasticity#=e#
	EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
	Next

HideEntity m

period=1000/60
time=MilliSecs()-period

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 KeyDown(28)
			ph.physics=New physics
			ph\mesh=CopyEntity(m)
			ph\velocity[0]=Rnd(-.5,.5)
			ph\velocity[1]=Rnd(-1,1)
			ph\velocity[2]=Rnd(-.5,.5)	
			ScaleEntity ph\mesh,r,r,r
			EntityRadius ph\mesh,r
			ResetEntity ph\mesh
			ph\elasticity#=e
			EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
			balls=balls+1
			EndIf
			
		If KeyHit(57)
			For ph.physics=Each physics
				PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8)
				ph\velocity[0]=Rnd(-.5,.5)
				ph\velocity[1]=Rnd(-2,2)
				ph\velocity[2]=Rnd(-.5,.5)
				Next
			EndIf
		
		If KeyHit(34) gravity=1-gravity
		
		UpdatePhysics
		
		Next
		
	RenderWorld
	Text 0,0,fps()
	Text 0,20,"Press space to reset balls."
	Text 0,40,"Press enter to add more balls."
	Text 0,60,"Press g to toggle gravity."
	Text 0,80,balls+" balls exist."
	Flip
	
	Wend
	
Function UpdatePhysics()

friction#=0.99;sliding friction
staticfriction#=0.0001;static friction = minimum velocity before an objects starts sticking

For ph.physics=Each physics
	;gravity	
	If gravity ph\velocity[1]=ph\velocity[1]-0.03
	;carry out velocity
	TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1	
	Next

UpdateWorld

;transfer inertia
For ph.physics=Each physics
	
	vx#=ph\velocity[0]
	vy#=ph\velocity[1]
	vz#=ph\velocity[2]
	
	For c=1 To CountCollisions(ph\mesh)
	
		dx#=ph\velocity[0]*Abs(CollisionNX(ph\mesh,c))
		dy#=ph\velocity[1]*Abs(CollisionNY(ph\mesh,c))
		dz#=ph\velocity[2]*Abs(CollisionNZ(ph\mesh,c))
	
		If GetEntityType(CollisionEntity(ph\mesh,c))=2
			ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))-dx*ph\elasticity
			ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))-dy*ph\elasticity
			ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))-dz*ph\elasticity
			EndIf
				
		If GetEntityType(CollisionEntity(ph\mesh,c))=1
		
			ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))
			ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))
			ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))
	
			ph2.physics=findphysics(CollisionEntity(ph\mesh,c))
			ph2\velocity[0]=ph2\velocity[0]+dx
			ph2\velocity[1]=ph2\velocity[1]+dy
			ph2\velocity[2]=ph2\velocity[2]+dz

			EndIf
		
		Next
	Next	

;add friction
For ph.physics=Each physics
	If EntityCollided(ph\mesh,2)
		;sliding friction
		ph\velocity[0]=ph\velocity[0]*friction
		ph\velocity[1]=ph\velocity[1]*friction
		ph\velocity[2]=ph\velocity[2]*friction
		;static friction
		If Abs(ph\velocity[0])<staticfriction# ph\velocity[0]=0.0
		If Abs(ph\velocity[1])<staticfriction# ph\velocity[1]=0.0
		If Abs(ph\velocity[2])<staticfriction# ph\velocity[2]=0.0
		EndIf
	Next

End Function

Function FindPhysics.physics(e)
For ph.physics=Each physics
	If ph\mesh=e Return ph
	Next
Return Null
End Function

Global FPS_fpstime

Function FPS()
oldtime=FPS_fpstime
FPS_fpstime=MilliSecs()
elapsed=FPS_fpstime-oldtime
If Not elapsed elapsed=1
FPS_fps=1000/elapsed
Return FPS_FPS
End Function



ashmantle(Posted 2003) [#4]
Without gravity I can have over 300 balls without the fps dropping at all..

Amd XP 1800+, gf4-4200


Physt(Posted 2003) [#5]
Impressive! :)


Physt(Posted 2003) [#6]
I stuffed the handle to the type into the name and I don't see the speed increase I expected but I don't have a profiler handy. Oh well, interesting stuff all the same. Thanks for sharing. Love to see inertia and mass!

Graphics3D 800,600,16,2
SetBuffer BackBuffer()

cam=CreateCamera()
;MoveEntity cam,0,-8,-20
MoveEntity cam,0,15,-20
TurnEntity cam,35,0,0

g=CreateCube()
ScaleMesh g,10,10,10
FlipMesh g
EntityType g,2

r=1
m=CreateSphere()
EntityShininess m,1
EntityType m,1
EntityRadius m,r
ScaleEntity m,r,r,r
EntityColor m,255,0,0

Collisions 1,2,2,2
Collisions 1,1,1,2

RotateEntity CreateLight(),25,45,0

Global gravity=True

Type physics
Field mesh
Field velocity#[5]
Field elasticity#
Field mass#
End Type

balls=100
e#=0.9

For n=1 To balls
	ph.physics=New physics
	ph\mesh=CopyEntity(m)
	ph\velocity[0]=Rnd(-.5,.5)
	ph\velocity[1]=Rnd(-1,1)
	ph\velocity[2]=Rnd(-.5,.5)	
	PositionEntity ph\mesh,Rnd(-8,8),-8,Rnd(-8,8)
	ResetEntity ph\mesh
	ph\elasticity#=e#
	EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
	NameEntity ph\mesh, Str(Handle(ph))
	Next

HideEntity m

period=1000/60
time=MilliSecs()-period

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 KeyDown(28)
			ph.physics=New physics
			ph\mesh=CopyEntity(m)
			ph\velocity[0]=Rnd(-.5,.5)
			ph\velocity[1]=Rnd(-1,1)
			ph\velocity[2]=Rnd(-.5,.5)	
			ScaleEntity ph\mesh,r,r,r
			EntityRadius ph\mesh,r
			ResetEntity ph\mesh
			ph\elasticity#=e
			EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
			balls=balls+1
			NameEntity ph\mesh, Str(Handle(ph))
			EndIf
			
		If KeyHit(57)
			For ph.physics=Each physics
				PositionEntity ph\mesh,Rnd(-8,8),8,Rnd(-8,8)
				ph\velocity[0]=Rnd(-.5,.5)
				ph\velocity[1]=Rnd(-2,2)
				ph\velocity[2]=Rnd(-.5,.5)
				Next
			EndIf
		
		If KeyHit(34) gravity=1-gravity
		
		UpdatePhysics
		
		Next
		
	RenderWorld
	Text 0,0,fps()
	Text 0,20,"Press space to reset balls."
	Text 0,40,"Press enter to add more balls."
	Text 0,60,"Press g to toggle gravity."
	Text 0,80,balls+" balls exist."
	Flip
	
	Wend
	
Function UpdatePhysics()

friction#=0.99;sliding friction
staticfriction#=0.0001;static friction = minimum velocity before an objects starts sticking

For ph.physics=Each physics
	;gravity	
	If gravity ph\velocity[1]=ph\velocity[1]-0.03
	;carry out velocity
	TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1	
	Next

UpdateWorld

;transfer inertia
For ph.physics=Each physics
	
	vx#=ph\velocity[0]
	vy#=ph\velocity[1]
	vz#=ph\velocity[2]
	
	For c=1 To CountCollisions(ph\mesh)
	
		dx#=ph\velocity[0]*Abs(CollisionNX(ph\mesh,c))
		dy#=ph\velocity[1]*Abs(CollisionNY(ph\mesh,c))
		dz#=ph\velocity[2]*Abs(CollisionNZ(ph\mesh,c))
	
		If GetEntityType(CollisionEntity(ph\mesh,c))=2
			ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))-dx*ph\elasticity
			ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))-dy*ph\elasticity
			ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))-dz*ph\elasticity
			EndIf
				
		If GetEntityType(CollisionEntity(ph\mesh,c))=1
		
			ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))
			ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))
			ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))
	
			ph2.physics=findphysics(CollisionEntity(ph\mesh,c))
			ph2\velocity[0]=ph2\velocity[0]+dx
			ph2\velocity[1]=ph2\velocity[1]+dy
			ph2\velocity[2]=ph2\velocity[2]+dz

			EndIf
		
		Next
	Next	

;add friction
For ph.physics=Each physics
	If EntityCollided(ph\mesh,2)
		;sliding friction
		ph\velocity[0]=ph\velocity[0]*friction
		ph\velocity[1]=ph\velocity[1]*friction
		ph\velocity[2]=ph\velocity[2]*friction
		;static friction
		If Abs(ph\velocity[0])<staticfriction# ph\velocity[0]=0.0
		If Abs(ph\velocity[1])<staticfriction# ph\velocity[1]=0.0
		If Abs(ph\velocity[2])<staticfriction# ph\velocity[2]=0.0
		EndIf
	Next

End Function

Function FindPhysics.physics(e)
;For ph.physics=Each physics
;	If ph\mesh=e Return ph
;	Next
;Return Null
	Return Object.physics EntityName(e)
End Function

Global FPS_fpstime

Function FPS()
oldtime=FPS_fpstime
FPS_fpstime=MilliSecs()
elapsed=FPS_fpstime-oldtime
If Not elapsed elapsed=1
FPS_fps=1000/elapsed
Return FPS_FPS
End Function





JoshK(Posted 2003) [#7]
What is the advantage of using your FindPhysics() function?

Oh, I guess it could speed things up if you had thousands of a type, but here you don't.


starfox(Posted 2003) [#8]
this only seems to work good if the cube is not rotated.


JoshK(Posted 2003) [#9]
Try this one. If anyone can get the bonds to keep the balls the right distance from each other, please do:

Graphics3D 800,600,16,2
SetBuffer BackBuffer()

cam=CreateCamera()
MoveEntity cam,0,15,-20
TurnEntity cam,35,0,0

g=CreateCube()
ScaleMesh g,10,10,10
FlipMesh g
EntityType g,2
EntityColor g,100,100,100

r=1
m=CreateSphere()
EntityShininess m,1
EntityType m,1
EntityRadius m,r
ScaleEntity m,r,r,r

Collisions 1,2,2,2
Collisions 1,1,1,2
Collisions 1,3,2,2

Collisions 3,2,2,2
;Collisions 3,1,1,2
;Collisions 3,3,1,2

;cubes=5

;For n=1 To cubes
;	cube=CreateCube()
;	EntityRadius cube,r
;	ScaleEntity cube,r,r,r
;	cubeph.physics=New physics
;	cubeph\mesh=cube
;	cubeph\elasticity=0.2
;	ScaleEntity cube,3,1,1
;	EntityType cube,3
;	EntityColor cube,255,0,0
;	MoveEntity cube,Rnd(-8,8),-8,Rnd(-8,8)
;	Next

RotateEntity CreateLight(),25,45,0

Global gravity=True

Type bond
Field mesh
Field a.physics, b.physics
End Type

Type physics
Field mesh
Field velocity#[5]
Field elasticity#
Field mass#
End Type

balls=5
e#=0.9

b.bond=New bond
b\mesh=CreateCube()

For n=1 To balls
	ph.physics=New physics
	If n=1 b\a=ph
	If n=2 b\b=ph
	ph\mesh=CopyEntity(m)
	ph\velocity[0]=Rnd(-.5,.5)
	ph\velocity[1]=Rnd(-1,1)
	ph\velocity[2]=Rnd(-.5,.5)	
	PositionEntity ph\mesh,Rnd(-8,8),-8,Rnd(-8,8)
	ResetEntity ph\mesh
	ph\elasticity#=e#
	EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
	Next

HideEntity m

period=1000/60
time=MilliSecs()-period

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 KeyDown(28)
			ph.physics=New physics
			ph\mesh=CopyEntity(m)
			ph\velocity[0]=Rnd(-.5,.5)
			ph\velocity[1]=Rnd(-1,1)
			ph\velocity[2]=Rnd(-.5,.5)	
			ScaleEntity ph\mesh,r,r,r
			EntityRadius ph\mesh,r
			ResetEntity ph\mesh
			ph\elasticity#=e
			EntityColor ph\mesh,Rand(255),Rand(255),Rand(255)
			balls=balls+1
			EndIf
			
		If KeyHit(57)
			For ph.physics=Each physics
				ph\velocity[0]=Rnd(-.5,.5)
				ph\velocity[1]=Rnd(-2,2)
				ph\velocity[2]=Rnd(-.5,.5)
				ph\velocity[4]=0
				Next
			EndIf
		
		If KeyHit(34) gravity=1-gravity
		
		UpdatePhysics
	
		Next
		
	RenderWorld
	
	Text 0,0,fps()
	Text 0,20,"Press space to reset balls."
	Text 0,40,"Press enter to add more balls."
	Text 0,60,"Press g to toggle gravity."
	Text 0,80,balls+" balls exist."
	Flip
	
	Wend
Function UpdatePhysics()

friction#=1;0.99;sliding friction
staticfriction#=0.0000;static friction = minimum velocity before an objects starts sticking

For ph.physics=Each physics
	;gravity	
	If gravity ph\velocity[1]=ph\velocity[1]-0.03
	;ph\velocity[1]=0
	;execute translational velocity
	TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1
	;execute rotational velocity
	TurnEntity ph\mesh,ph\velocity[3],ph\velocity[4],ph\velocity[5],1	
	Next
	
UpdateWorld

;transfer inertia
For ph.physics=Each physics
	
	vx#=ph\velocity[0]
	vy#=ph\velocity[1]
	vz#=ph\velocity[2]
	
	For c=1 To CountCollisions(ph\mesh)
	
		collider=CollisionEntity(ph\mesh,c)
	
		dx#=ph\velocity[0]*Abs(CollisionNX(ph\mesh,c))
		dy#=ph\velocity[1]*Abs(CollisionNY(ph\mesh,c))
		dz#=ph\velocity[2]*Abs(CollisionNZ(ph\mesh,c))
	
		Select GetEntityType(collider)
	
			;Spheres
			Case 1
				ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))
				ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))
				ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))			
				ph\velocity[0]=ph\velocity[0];-dx*.5
				ph\velocity[1]=ph\velocity[1];-dy*.5
				ph\velocity[2]=ph\velocity[2];-dz*.5	
				ph2.physics=findphysics(collider)
				ph2\velocity[0]=ph2\velocity[0]+dx;*.5
				ph2\velocity[1]=ph2\velocity[1]+dy;*.5
				ph2\velocity[2]=ph2\velocity[2]+dz;*.5

			;Polygons with infinite mass
			Case 2
				ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))-dx*ph\elasticity
				ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))-dy*ph\elasticity
				ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))-dz*ph\elasticity

			;Polygons
			;Case 3
			;	ph\velocity[0]=ph\velocity[0]*(1.0-Abs(CollisionNX(ph\mesh,c)))
			;	ph\velocity[1]=ph\velocity[1]*(1.0-Abs(CollisionNY(ph\mesh,c)))
			;	ph\velocity[2]=ph\velocity[2]*(1.0-Abs(CollisionNZ(ph\mesh,c)))
			;	ph2.physics=findphysics(collider)
			;	temp=CreatePivot()
			;	PositionEntity temp,CollisionX(ph\mesh,c),CollisionY(ph\mesh,c),CollisionZ(ph\mesh,c);PickedX(),PickedY(),PickedZ()
			;	AlignToVector temp,-CollisionNX(ph\mesh,c),-CollisionNY(ph\mesh,c),-CollisionNZ(ph\mesh,c),3
			;	TFormPoint EntityX(ph2\mesh,1),EntityY(ph2\mesh,1),EntityZ(ph2\mesh,1),0,temp
			;	ph2\velocity[4]=ph2\velocity[4]-TFormedX()*Sqr(dx^2.0+dz^2.0)
			;	TFormPoint 0,0,TFormedZ(),temp,0
			;	ph2\velocity[0]=ph2\velocity[0]-dx*CollisionNX(ph\mesh,c)
			;	ph2\velocity[1]=ph2\velocity[1]-dy*CollisionNY(ph\mesh,c)
			;	ph2\velocity[2]=ph2\velocity[2]-dz*CollisionNZ(ph\mesh,c)
			;	FreeEntity temp
		
			End Select
		
		Next
	Next	

;add friction
For ph.physics=Each physics
	If EntityCollided(ph\mesh,2)
		For n=0 To 5
			;sliding friction
			ph\velocity[n]=ph\velocity[n]*friction
			;static friction
			If Abs(ph\velocity[n])<staticfriction# ph\velocity[n]=0.0
			Next
		EndIf
	Next

For b.bond=Each bond
	PositionEntity b\mesh,(EntityX(b\a\mesh,1)+EntityX(b\b\mesh,1))/2.0,(EntityY(b\a\mesh,1)+EntityY(b\b\mesh,1))/2.0,(EntityZ(b\a\mesh,1)+EntityZ(b\b\mesh,1))/2.0
	AlignToVector b\mesh,EntityX(b\a\mesh,1)-EntityX(b\b\mesh,1),EntityY(b\a\mesh,1)-EntityY(b\b\mesh,1),EntityZ(b\a\mesh,1)-EntityZ(b\b\mesh,1),3
	RotateEntity b\mesh,EntityPitch(b\mesh,1),EntityYaw(b\mesh,1),0,1
	ScaleEntity b\mesh,.25,.25,0.5*pointdistance(EntityX(b\b\mesh,1),EntityY(b\b\mesh,1),EntityZ(b\b\mesh,1),EntityX(b\a\mesh,1),EntityY(b\a\mesh,1),EntityZ(b\a\mesh,1))	
	ax#=b\a\velocity[0]
	ay#=b\a\velocity[1]
	az#=b\a\velocity[2]
	bx#=b\b\velocity[0]
	by#=b\b\velocity[1]
	bz#=b\b\velocity[2]

	;TFormPoint EntityX(b\a\mesh),EntityY(b\a\mesh),EntityZ(b\a\mesh),0,b\mesh
	;TFormPoint 0,0,TFormedZ()+2,b\mesh,0
	;b\a\velocity[0]=b\a\velocity[0]+TFormedX()
	;b\a\velocity[1]=b\a\velocity[1]+TFormedY()
	;b\a\velocity[2]=b\a\velocity[2]+TFormedZ()

	;TFormPoint EntityX(b\b\mesh),EntityY(b\b\mesh),EntityZ(b\b\mesh),0,b\mesh	
	;TFormPoint 0,0,TFormedZ()-2,b\mesh,0
	;b\b\velocity[0]=b\b\velocity[0]+TFormedX()
	;b\b\velocity[1]=b\b\velocity[1]+TFormedY()
	;b\b\velocity[2]=b\b\velocity[2]+TFormedZ()
	;b\a\velocity[0]=-bx;(EntityX(b\a\mesh)-TFormedX())
	;b\a\velocity[1]=-by;(EntityY(b\a\mesh)-TFormedY())
	;b\a\velocity[2]=-bz;(EntityZ(b\a\mesh)-TFormedZ())
	;PositionEntity b\a\mesh,TFormedX(),TFormedY(),TFormedZ(),1	
	;TranslateEntity b\a\mesh,bx,by,bz,1
	;TFormPoint 0,0,2,b\mesh,0
	;b\b\velocity[0]=-ax;(EntityX(b\b\mesh)-TFormedX())
	;b\b\velocity[1]=-ay;(EntityY(b\b\mesh)-TFormedY())
	;b\b\velocity[2]=-az;(EntityZ(b\b\mesh)-TFormedZ())	
	;TranslateEntity b\b\mesh,ax,ay,az,1;TFormedX(),TFormedY(),TFormedZ(),1	
	Next

End Function

Function FindPhysics.physics(e)
For ph.physics=Each physics
	If ph\mesh=e Return ph
	Next
Return Null
End Function

Function PointDistance#( x1#,y1#,z1#,x2#,y2#,z2# )
Return Sqr#((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
End Function

Global FPS_fpstime

Function FPS()
oldtime=FPS_fpstime
FPS_fpstime=MilliSecs()
elapsed=FPS_fpstime-oldtime
If Not elapsed elapsed=1
FPS_fps=1000/elapsed
Return FPS_FPS
End Function



mongia2(Posted 2003) [#10]
dont utilise mass#

if mass#<>

thanks


Bouncer(Posted 2003) [#11]
What is this doing in Advanced 3d forum?


Miracle(Posted 2003) [#12]
sswift, check one of the many versions of the verlet engine code for some good rigid constraints.


Tin-cat(Posted 2007) [#13]
sniff..


bytecode77(Posted 2007) [#14]
basicaly this actually is a real good physic engine! you only need to do a few things: at first, make the spheres rotate, too. this will look better. at second, you need cubes/cylinders/cones and as many primitives as possible to do a real nice physic engine :)

i wanna hear from you when you got that right :)


Naughty Alien(Posted 2007) [#15]
..and thats 4 years old thread :)


bytecode77(Posted 2007) [#16]
oh, i didnt see.
but "tin-cat" posted here first after 5 years BEFORE i did...
also i would like to know how to do cube to cube verlets!!