Code archives/3D Graphics - Maths/Ball rolling example

This code has been declared by its author to be Public Domain code.

Download source code

Ball rolling example by Jeppe Nielsen
(Posted 23 years ago)
Shows how you can make a ball roll
;Ball rolling physics example by Jeppe Nielsen 2003

Const gravity#=-0.04;-0.02 ;gravity constant

Graphics3D 800,600,16,1

Const ball_col=1
Const world_col=2

Collisions ball_col,world_col,2,2

Global texture

texture=CreateTexture(16,16)

SetBuffer TextureBuffer(texture)

Color 255,255,255
Rect 0,0,16,16,1

Color 255,0,0
Rect 0,0,8,8,1
Rect 8,8,8,8,1

ScaleTexture texture,0.1,0.1


Global groundtexture=CreateTexture(32,32,1+8)

SetBuffer TextureBuffer(groundtexture)

Color 0,0,0
Rect 0,0,32,32,1

Color 0,0,255
Rect 0,0,32,32,0

ScaleTexture groundtexture,2,2

SetBuffer BackBuffer()
Color 255,255,255

plane=CreatePlane()
EntityTexture plane,groundtexture
EntityType plane,world_col
EntityAlpha plane,0.5

mirror=CreateMirror()




light=CreateLight(1)
RotateEntity light,30,20,0


obj=CreateCube()

EntityType obj,world_col
PositionEntity obj,0,0,0
ScaleEntity obj,10,10,10
RotateEntity obj,45,0,0



camera=CreateCamera()
CameraClsColor camera,0,0,255


ball.ball=ballnew(0,4,-120,2,0.8)


zoom#=14

Repeat

zoom#=zoom#-MouseZSpeed()
ballcamera(camera,ball,0,zoom#,-zoom#,0,5,0)


ballcontrol()
ballupdate()

RenderWorld()

Text 10,10,"Arrow keys to control ball"
Text 10,30,"Scroll on mouse to zoom"


Flip


Until KeyDown(1)
End


Type ball

Field e ;entity

Field sphere

Field pivot

Field x#,y#,z# ; position in 3d-space

Field vx#,vy#,vz# ; velocity

Field ax#,ay#,az# ; acceleration

Field size#

Field bounce# ; bounce factor

Field vel#

Field vx2#,vy2#,vz2# ; temp velocity

End Type


Function ballnew.ball(x#,y#,z#,size#=1,bounce#=0.9)
	
	c.ball=New ball
	
	c\x#=x#
	c\y#=y#
	c\z#=z#
	
	c\size=size
	
	c\bounce#=bounce#
	
	c\e=CreatePivot()
		
	c\sphere=CreateSphere(64)
	
	c\pivot=CreatePivot()
	
	EntityType c\e,ball_col
	EntityRadius c\e,c\size
	
	PositionEntity c\e,c\x,c\y,c\z
	ScaleEntity c\sphere,c\size,c\size,c\size
	
	EntityTexture c\sphere,texture
	
	Return c
	
End Function

Function ballupdate()
	
	For c.ball=Each ball
	
			
		c\vy#=c\vy#+gravity#
		
		c\vx#=c\vx#+c\ax#
		c\vy#=c\vy#+c\ay#
		c\vz#=c\vz#+c\az#
		
		c\x#=EntityX(c\e)
		c\y#=EntityY(c\e)
		c\z#=EntityZ(c\e)
		
		TranslateEntity c\e,c\vx,c\vy,c\vz	
	
	Next
	
	UpdateWorld()
		
	For c.ball=Each ball
	
		;correct velocity if collided
		c\vx2=(EntityX(c\e)-c\x)
		c\vy2=(EntityY(c\e)-c\y)
		c\vz2=(EntityZ(c\e)-c\z)
		
		c\x#=EntityX(c\e)
		c\y#=EntityY(c\e)
		c\z#=EntityZ(c\e)
		
		PositionEntity c\sphere,c\x,c\y,c\z
		PositionEntity c\pivot,c\x,c\y,c\z
		
		If EntityCollided(c\e,world_col)
				
			For i = 1 To CountCollisions(c\e)
				; Get the normal of the surface which the entity collided with. 
				Nx# = CollisionNX(c\e, i) 
				Ny# = CollisionNY(c\e, i) 
				Nz# = CollisionNZ(c\e, i) 
				
				; Compute the dot product of the entity's motion vector and the normal of the surface collided with. 
				VdotN# = c\vx#*Nx# + c\vy#*Ny# + c\vz#*Nz# 
				
				; Calculate the normal force. 
				NFx# = -2.0 * Nx# * VdotN# 
				NFy# = -2.0 * Ny# * VdotN# 
				NFz# = -2.0 * Nz# * VdotN# 
				
				; Add the normal force to the direction vector. 
				c\vx# = c\vx# + NFx# * c\bounce#
				c\vy# = c\vy# + NFy# * c\bounce#
				c\vz# = c\vz# + NFz# * c\bounce#

				avx#=EntityPitch(c\sphere)
				avy#=EntityYaw(c\sphere)
				avz#=EntityRoll(c\sphere)

				;Rotate stuff
				;Get vector from center to collision
				dx1#=(CollisionX(c\e,i)-c\x)
				dy1#=(CollisionY(c\e,i)-c\y)
				dz1#=(CollisionZ(c\e,i)-c\z)
				
				dx2#=c\vx
				dy2#=c\vy
				dz2#=c\vz
				
				;Cross product
				cx# = ( dy1 * dz2 ) - ( dz1 * dy2 ) 
				cy# = ( dz1 * dx2 ) - ( dx1 * dz2 ) 
				cz# = ( dx1 * dy2 ) - ( dy1 * dx2 ) 				
															
				AlignToVector c\pivot,cx,cy,cz,1
																									
			Next
			
			Nx# = CollisionNX(c\e, 1) 
			Ny# = CollisionNY(c\e, 1) 
			Nz# = CollisionNZ(c\e, 1) 				
					
			AlignToVector c\e,Nx#,Ny#,Nz#,2,0.5
			
			c\vel#=Sqr(c\vx2*c\vx2+c\vy2*c\vy2+c\vz2*c\vz2)
						
			;slow down due to friction
			c\vx#=c\vx*0.98
			c\vy#=c\vy*0.98
			c\vz#=c\vz*0.98
					

		EndIf

			
		EntityParent c\sphere,c\pivot
								
		TurnEntity c\pivot,-c\vel#*(180/Pi)/c\size#,0,0

		EntityParent c\sphere,0

		c\ax#=0
		c\ay#=0
		c\az#=0	
		
	Next
	
End Function


Function ballcontrol()
	
	For c.ball=Each ball
		
		If KeyDown(200)
			
			TFormVector 0,0,0.03,c\e,0
			
			c\ax#=TFormedX()
			c\ay#=TFormedY()
			c\az#=TFormedZ()
			
		EndIf
		
		If KeyDown(208)
			
			c\vx=c\vx*0.94
			c\vy=c\vy*0.94
			c\vz=c\vz*0.94
			
		EndIf
		
		If KeyDown(57)
			
			TFormVector 0,0.05,0,c\e,0
			
			c\ax#=c\ax+TFormedX()
			c\ay#=c\ay+TFormedY()
			c\az#=c\az+TFormedZ()
			
									
		EndIf
		
		If KeyDown(203)
			
			TurnEntity c\e,0,2,0
			
		EndIf
		
		If KeyDown(205)
			
			TurnEntity c\e,0,-2,0
			
		EndIf
		
		
	Next
	
	
	
End Function

Function ballcamera(camera,b.ball,camx#,camy#,camz#,aimx#=0,aimy#=0,aimz#=0,smoothcam#=0.1,roll#=0)
	
	TFormPoint camx#,camy#,camz#,b\e,0
	
	dx#=(TFormedX()-EntityX(camera))*smoothcam#
	dy#=(TFormedY()-EntityY(camera))*smoothcam#
	dz#=(TFormedZ()-EntityZ(camera))*smoothcam#
	
	TranslateEntity camera,dx,dy,dz
	
	TFormPoint aimx#,aimy#,aimz#,b\e,0
	
	dx# = EntityX(camera)-TFormedX()
	dy# = EntityY(camera)-TFormedY()
	dz# = EntityZ(camera)-TFormedZ()
	dist#=Sqr#((dx#*dx#)+(dz#*dz#))
	pitch#=ATan2(dy#,dist#)
	yaw#=ATan2(dx#,-dz#)
	
	RotateEntity camera,pitch#,yaw#,roll#
	
End Function