Thanks to everybody who helped me perfect this algorithm. Now we have collision with convervation of momentum as well as accurate rolling simulation. Here is the code if anybody wants to use it. Feel free....
;
; Bouncing ball physics - by Vincent DeCampo 2/1/04
;
Const GRAVITY#=-.05
Const BALLS=1
Graphics3D 640,480
;*** Type for Ball ***
Type Ball_Object
Field Entity
Field Pivot
Field x#
Field y#
Field z#
Field dx#
Field dy#
Field dz#
Field xMin#
Field xMax#
Field yMin#
Field yMax#
Field zMin#
Field zMax#
Field elasticity#
Field friction#
End Type
;*** Lets create the floor ***
Room=CreateTerrain(64)
PositionEntity room,-32,0,-32
EntityColor Room, 0, 150, 0
;******* Create Initial Ball ******
Blitz.Ball_Object = New Ball_Object
InitBallVars(Blitz)
Collisions BALLS, BALLS, 1, 2
;***** Create Camera *****
camera=CreateCamera()
PositionEntity camera,0,5,-40
PointEntity camera, Blitz\Entity
;**********************************
; Main Loop
;**********************************
;
While Not KeyHit(1)
If KeyHit(57) Then
;***** Seed RND Generator *****
SeedRnd (MilliSecs())
;*** Create New Ball ***
Blitz.Ball_Object = New Ball_Object
InitBallVars Blitz
End If
;**** Perform Room Physics ****
For Ball.Ball_Object = Each Ball_Object
BallPhysics (Ball)
Next
UpdateWorld
;**** Perform Ball-on-Ball Physics ****
CheckCollisions (Blitz)
RenderWorld
Text 0,5,"Press SPACE to throw another ball"
Text 0,15,"Press ESC to Exit"
Flip
Wend
End
;**********************************
Function CheckCollisions (Ball.Ball_Object)
For C.Ball_Object = Each Ball_Object
If EntityCollided(c\Entity, BALLS)
For i = 1 To CountCollisions(c\Entity)
Ent=CollisionEntity (c\Entity, i)
;Get the normal of the surface which the entity collided with.
Nx# = CollisionNX(c\Entity, i)
Ny# = CollisionNY(c\Entity, i)
Nz# = CollisionNZ(c\Entity, i)
;Compute the dot product of the entity's motion vector And the normal of the surface collided with.
VdotN# = (c\dx# * Nx# + c\dy# * Ny# + c\dz# * 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\dx# = c\dx# + NFx#/2
c\dy# = c\dy# + NFy#/2 ;Force /2 assumes balls equal in mass
c\dz# = c\dz# + NFz#/2
For Hit.Ball_Object = Each Ball_Object
If Hit\Entity = Ent Then
;Add negative force to collision entity vector
Hit\dx# = Hit\dx# - NFx#/2
Hit\dy# = Hit\dy# - NFy#/2 ;Force /2 assumes balls equal in mass
Hit\dz# = Hit\dz# - NFz#/2
End If
Next
Next
EndIf
Next
End Function
;**********************************
Function InitBallVars(Ball.Ball_Object)
;Create Ball
Ball\Entity=CreateSphere()
ScaleEntity Ball\Entity, 1,1,1
EntityType Ball\Entity, BALLS
txt=LoadTexture("blitzlogo.bmp")
EntityTexture Ball\Entity, txt
;Create Pivot
Ball\Pivot=CreatePivot()
;*** Variables for Ball ***
Ball\x#=0
Ball\y#=20 ;set ball 20 units above floor
Ball\z#=0
Ball\dx#=Rand(5)
Ball\dy#=0 ;at rest
Ball\dz#=Rand(5)
Ball\yMin#=1
Ball\yMax#=9999
Ball\xMin#=-32
Ball\xMax#=32
Ball\zMin#=-32
Ball\zMax#=32
Ball\elasticity#=.75 ;value from >0 to <1 (1=pure elastic collision)
Ball\friction#=.01
;**************************
End Function
;**********************************
Function BallPhysics (Ball.Ball_Object)
If ball\y =< Ball\yMin# Then
Ball\y = Ball\yMin#
Ball\dy = -Ball\dy
Ball\dy = Ball\dy * Ball\elasticity
End If
If Ball\x =< Ball\xMin# Then
Ball\x = Ball\xMin#
Ball\dx = -Ball\dx
Ball\dx = Ball\dx * Ball\elasticity
UpdatePivot (Ball)
End If
If Ball\x >= Ball\xMax# Then
Ball\x = Ball\xMax#
Ball\dx = -Ball\dx
Ball\dx = Ball\dx * Ball\elasticity
UpdatePivot (Ball)
End If
If Ball\z =< Ball\zMin# Then
Ball\z = Ball\zMin#
Ball\dz = -Ball\dz
Ball\dz = Ball\dz * Ball\elasticity
UpdatePivot (Ball)
End If
If Ball\z >= Ball\zMax# Then
Ball\z = Ball\zMax#
Ball\dz = -Ball\dz
Ball\dz = Ball\dz * Ball\elasticity
UpdatePivot (Ball)
End If
If Ball\y >= Ball\yMin# Then
Ball\dy = Ball\dy + GRAVITY
End If
Ball\x = Ball\x + Ball\dx
Ball\z = Ball\z + Ball\dz
Ball\y = Ball\y + Ball\dy
Ball\dx = Ball\dx - (Ball\dx*Ball\friction)
Ball\dz = Ball\dz - (Ball\dz*Ball\friction)
;Move ball to new coords
PositionEntity Ball\Entity, Ball\x, Ball\y, Ball\z, 0
;Rotate mesh to give appearance of rolling
TurnEntity Ball\Entity, Ball\dz*50,0,-Ball\Dx*50, 1
End Function
Function UpdatePivot (Ball.Ball_Object)
;Move pivot to coords + deltas
PositionEntity Ball\Pivot, Ball\x+Ball\dx, Ball\y+Ball\dy, Ball\z+Ball\dz
PointEntity Ball\Entity, Ball\Pivot, 0
End Function
PS: You will need the file Blitzlogo.bmp as the ball texture.
|