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

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

Download source code

Wheel rolling example by Jeppe Nielsen2003
Shows how to roll a wheel, unlike a ball it cannot go in any direction.
;wheel rolling physics example by Jeppe Nielsen 2003
;email: nielsen_jeppe@hotmail.com

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

Graphics3D 800,600,16,2

Const wheel_col=1
Const world_col=2
Collisions wheel_col,world_col,2,3


;create old amiga texture :-)
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.5,0.5

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



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


obj=CreateCube()
EntityType obj,world_col
PositionEntity obj,0,-20,-175
ScaleEntity obj,10,140,40
RotateEntity obj,75,0,0
EntityTexture obj,texture


sphere=CreateSphere(32)
EntityType sphere,world_col
ScaleEntity sphere,40,40,40
EntityTexture sphere,texture


Dim VertArray(0)
sphere1=AdjustTriangles(sphere,0.5,False)
sphere2=AdjustTriangles(Sphere,0.5,True)
FlipMesh sphere2

PositionEntity sphere1,0,35,0
RotateEntity sphere1,180,0,0
ScaleEntity sphere1,40,40,40
EntityTexture sphere1,texture
EntityType sphere1,world_col
RotateEntity sphere2,180,0,0
PositionEntity sphere2,0,35,0
ScaleEntity sphere2,40,40,40
EntityTexture sphere2,texture
EntityType sphere2,world_col


camera=CreateCamera()
CameraClsColor camera,0,0,255
PositionEntity camera,0,600,-40

wheel.wheel=wheelnew(0,4,0,2)

zoom#=14

Repeat

zoom#=zoom#-MouseZSpeed()
wheelcamera(camera,wheel,0,zoom#,-zoom#,0,5,0)


wheelcontrol(wheel)
wheelupdate()

RenderWorld()

Color 255,255,255

Text 10,10,"Arrow keys to control wheel"
Text 10,20,"Space to lift wheel"
Text 10,30,"Scroll on mouse to zoom"


Flip


Until KeyDown(1)
End


Type wheel

Field e ;entity

Field cylinder

Field pivot

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

Field vx#,vy#,vz# ; velocity

Field ax#,ay#,az# ; acceleration

Field size#

Field vel#

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

Field collided

End Type


Function wheelnew.wheel(x#,y#,z#,size#=1)
	
	c.wheel=New wheel
	
	c\x#=x#
	c\y#=y#
	c\z#=z#
	
	c\size=size
	
	c\e=CreatePivot()
			
	c\cylinder=CreateCylinder(64)
	RotateMesh c\cylinder,0,0,90
	
	c\pivot=CreatePivot()
	
	EntityType c\e,wheel_col
	EntityRadius c\e,c\size
	
	PositionEntity c\e,c\x,c\y,c\z
	ScaleEntity c\cylinder,c\size,c\size,c\size
	
	EntityTexture c\cylinder,texture
	
	Return c
	
End Function

Function wheelupdate()
	
	For c.wheel=Each wheel
	
			
		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.wheel=Each wheel
	
		;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\cylinder,c\x,c\y,c\z
		PositionEntity c\pivot,c\x,c\y,c\z
		
		TFormVector 1,0,0,c\e,0
		AlignToVector c\cylinder,TFormedX(),TFormedY(),TFormedZ(),1,0.6
		
		c\collided=0
				
		If EntityCollided(c\e,world_col)
		
			c\collided=1
				
			avnx#=0
			avny#=0
			avnz#=0
				
			count=CountCollisions(c\e)	
				
			For i = 1 To count
				; 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) 
				
				avnx#=avnx+Nx
				avny#=avny+Ny
				avnz#=avnz+Nz
				
				; 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\vy# = c\vy# + NFy# 
				c\vz# = c\vz# + NFz# 
								
			Next
				
			If count>0 
							
				;average collision normals
				avnx#=avnx/count
				avny#=avny/count
				avnz#=avnz/count

				;align controlpivot to averaged collision normals
				AlignToVector c\e,avnx,avny,avnz,2
				
				;calculate length of motion vector, or total velocity.
				l#=Sqr(c\vx*c\vx+c\vy*c\vy+c\vz*c\vz)

				;get normalized direction of motion, the vector will have a length of one.
				;the +0.00001 is there to aviod NaN (not a number) numbers. This happens
				;if the length of the vector is 0.
				TFormNormal c\vx,c\vy+0.00001,c\vz,0,0
				vx#=TFormedX()
				vy#=TFormedY()
				vz#=TFormedZ()
											
				;get direction of wheel
				TFormNormal 0,0,1,c\e,0
				
				;calculate a dot product, a number between -1 and 1 to determine angle
				;calculate angle like this: angle#=Acos(dot#)		
				dot#=TFormedX()*vx+TFormedY()*vy+TFormedZ()*vz
			
				;correct velocities, by multiplying the controlpivotīs direction with
				;the dot product, followed by the original velocity vector length:
				c\vx=TFormedX()*dot*l
				c\vy=TFormedY()*dot*l
				c\vz=TFormedZ()*dot*l
							
				RotateEntity c\pivot,EntityPitch(c\e),EntityYaw(c\e),EntityRoll(c\e)
																					
			EndIf
						
			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\cylinder,c\pivot
		
		TFormVector c\vx,c\vy,c\vz,0,c\e
		;moving forward
		If TFormedZ()>0
		
			TurnEntity c\pivot,c\vel#*(180/Pi)/c\size#,0,0
		
		Else
		;moving backwards
		
			TurnEntity c\pivot,-c\vel#*(180/Pi)/c\size#,0,0
			
		EndIf

		EntityParent c\cylinder,0

		;reset acceleration
		c\ax#=0
		c\ay#=0
		c\az#=0	
		
	Next
	
End Function


Function wheelcontrol(c.wheel)

		If c\collided=1
		
			If KeyDown(200)
				
				TFormVector 0,0,0.05,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
		
		EndIf
		
		If KeyDown(57)
			
			c\ay#=c\ay+0.05
														
		EndIf
		
		If KeyDown(203)
			
			TurnEntity c\e,0,2,0
			
		EndIf
		
		If KeyDown(205)
			
			TurnEntity c\e,0,-2,0
			
		EndIf
		
		
	
End Function

Function wheelcamera(camera,b.wheel,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

;function by Graythe
Function AdjustTriangles%(EntityNo%,Triangles#,FreeSource%=True,FX%=False)
Dim VertArray(2^16)
Copied=CreateMesh(GetParent(EntityNo))
For SurfLoop=1 To CountSurfaces(EntityNo)
	
	NewSurface=CreateSurface(Copied)

	OldSurface=GetSurface(EntityNo,SurfLoop)
	
	NoVertices=CountVertices(OldSurface)-1
	TotTriangles=Int(CountTriangles(OldSurface)*Triangles)-1
		
	For TriLoop=False To TotTriangles
		For CornerLoop=False To 2
			tri=TriangleVertex(OldSurface,TriLoop,CornerLoop)
			VertArray(tri)=True
		Next
	Next
	
	For VertLoop = False To NoVertices
		If VertArray(VertLoop) Then
			NewVertex=AddVertex(NewSurface,VertexX(OldSurface,VertLoop),VertexY(OldSurface,VertLoop),VertexZ(OldSurface,VertLoop),VertexU(OldSurface,VertLoop),VertexV(OldSurface,VertLoop),VertexW(OldSurface,VertLoop))
		End If
	Next		
		
	For TriLoop=False To TotTriangles
		AddTriangle NewSurface, TriangleVertex(OldSurface,TriLoop,False),TriangleVertex(OldSurface,TriLoop,1),TriangleVertex(OldSurface,TriLoop,2)
	Next
		
Next
Dim VertArray(0)
UpdateNormals Copied
If FX Then EntityFX Copied,FX
If FreeSource Then FreeEntity EntityNo
Return Copied
End Function

Comments

Santiworld2008
super!... :)


Panno2008
awesome

a big thx

mfg


Code Archives Forum