How do you handle Momentum?

Blitz3D Forums/Blitz3D Programming/How do you handle Momentum?

PaulF(Posted 2003) [#1]
I know that there is a lot of information on collisions in these forums, but I can't seem to find anything which addresses my particular query. I hope that some of you out there will be able to help.

From what I've read, and have found by experimenting, for any collision between two spheres, the contents of the collision table indexed by CountCollisions(entity) seems to vary depending upon the circumstances of the collision. i.e whether both objects are travelling in opposing directions, both in the same direction but at differing speeds, or if either is stopped.

Sometimes there seem to be multiple entries for the same entity, I guess if there have been multiple collisions within a single UpdateWorld.

It appears that once a collision has happened, there may be one, two or even more entries in the collision table for the same event. I know that if these were collisions with infinite mass objects, this would probably not matter since the rebounds of each can be calculated from the collision normals for each, but if one is trying to handle the momentum properly, collecting all entries which relate to the same event seems to be tricky, to say the least.

Am I understanding things properly, and is there an 'approved' method of linking up these entries, or am I missing something and in reality its all extremely easy?


Rob Farley(Posted 2003) [#2]
Check the code archives

http://www.blitzbasic.com/codearcs/codearcs.php?code=751


PaulF(Posted 2003) [#3]
Many thanks for that speedy reply. I missed that example in the code archives and it is certainly very interesting.

Whilst it does thoroughly answer part of my query, it doesn't in any way answer the query as to how the collision table is populated by Blitz3D.

From further experimentation, you seem to get one entry if two spheres collide whilst one is stopped, two entries if they are both moving at similar velocities, and three entries if their speeds vary considerably. (And not surprisingly, no entries if they are both stopped!!)

I think I'm comfortable as to why that should be, but would like to feel that my findings can be relied upon. Also, are there circumstances when the same two spheres can cause 4 or more entries in the collision table?

The example to which you referred completely avoids the normal collision mechanism, and whilst its a fascinating way to do things, I shudder to think how it could be developed into a general solution in a more complicated 3D world.

Can anyone point me to an article which fully explains the collision table?


sswift(Posted 2003) [#4]
Paul:
I've been using Blitz3D for a long time, and I've never heard of more than one collision being reported when two objects collide. I doubt that you will find any information on that. I also don't reccomend that you assume that more than one collision will be reported when two objects are moving at certain speeds. It seems very likely that that would change in the future, as only a single collision should be reported in a properly functioning collision system that functions as Blitz's does.

I do know that Blitz's collision system doesn't handle most collisions between moving objects correctly and that Mark has mentioned that it needs to be fixed. Mark designed the system so that objects that collide will not interpenetrate, but when more than one object is moving and they collide, they do interpentrate, and that's an issue that needs to be corrected. The fact that the two objects are interpenetrating is likely what leads to the erroneous reporting of multiple collisions.

I thought the one exception to the moving object interpenetration issue was between moving spheres, and that collisions between these could be relied upon. However, if what you say is true, then that is clearly not the case.

I suppose it's possible Mark broke moving sphere collisions when he implemented ellipsoid collisions.

Some folks were complaining in the bug reports forum about ellipsoid collisions not working as expected. I think some other folks also complained about regular sphere collisions being broken in some way as a result as well.


Rob Farley(Posted 2003) [#5]
In my latest project I've noticed that with basic sphere-polygon collision the sphere sometimes drops through the mesh. I can't seem to find any rhyme or reason why this happens but it does... bloody annoying... trying to find a way round it.


PaulF(Posted 2003) [#6]
OK - You may shoot me down in flames for this, but here's the program with which I've been testing.
Apologies for the sloppy code, but that wasn't the idea of this.

I would prefer that I'm doing something wrong here because if it's a bug, surely it could be quite significant.

Assuming I've not made a boo-boo, could someone please explain just how this collision table is supposed to work.

The circumstance with only a single collision recorded when one ball is stopped is reasonable. I feel that the other cases though need to be explained. - Cases 2 and 5

; Very unfinished - Test framework only
; Run with debug, when it stops, view debug log
; then kill program and repeat with different option
; Probably I'm doing something wrong but I can't find it
; Essentially all these variants are surely the same thing??

.Begin
Global v1#,v2#
Print "1 - Opposite Directions Similar Speed (2)"
Print "2 - Opposite Directions Differing Speeds (3)"
Print "3 - Ball1 Stopped (2)"
Print "4 - Ball2 Stopped (1)"
Print "5 - Same Directions (1)"
Print "6 - Both Stopped (Takes Quite a While)!"
Print
Print "Which Test 1-6"

.Here
If KeyDown(2) Then v1# = 0.3 : v2# = -0.3 : Goto Doit
If KeyDown(3) Then v1# = 1.5 : v2# = -0.02 : Goto Doit
If KeyDown(4) Then v1# = 0 : v2# = -0.3 : Goto Doit
If KeyDown(5) Then v1# = 0.3 : v2# = 0 : Goto Doit
If KeyDown(6) Then v1# = 0.3 : v2# = 0.05 : Goto Doit
If KeyDown(7) Then v1# = 0 : v2# = 0 : Goto Doit

Goto here

.Doit

Const Coll_Wall = 1
Const Coll_Ground = 2
Const Coll_Ball = 3

Const FPS=30
Global period=1000/FPS
Global time=MilliSecs()-period

Const ScrWid = 640
Const ScrHgt = 480

Global Camera1_Pivot,Camera1

Type ball
Field entity
Field index%
Field name$
Field mass#
Field xvel#,yvel#,zvel#
End Type


Global collcount
Dim collsubj$(20),collobj$(20),colltriangle#(20)

Dim coltab#(20)
Global colmod%

SetBuffer BackBuffer()
Graphics3D ScrWid,ScrHgt



Buildworld()

PositionEntity Camera1,0,15,-20
RotateEntity Camera1,30,0,0
RotateEntity Camera1_Pivot,0,0,0

Collisions Coll_Ball,Coll_Ball,1,1
; Main Loop
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 k=ticks Then CaptureWorld
UpdateBalls()
UpdateWorld
Next

RenderWorld tween

Flip
Wend

End

Function BuildWorld()
Cls
HidePointer
AmbientLight(255,255,255)

Camera1_Pivot = CreatePivot()
PositionEntity Camera1_Pivot,0,0,0
Camera1 = CreateCamera(Camera1_Pivot)

Board = CreateCube()
ScaleMesh Board,20,0.2,20
EntityColor Board,100,200,100
EntityType Board,Coll_Ball
EntityRadius board,2
PositionEntity Board,0,-0.2,0

b.ball = New ball ; Yellow Ball
b\index% = 1
b\name$ = "Yellow"
b\entity = CreateSphere()
EntityColor b\entity,255,255,20
EntityType b\entity,Coll_Ball
ScaleEntity b\entity,2,2,2
EntityRadius b\entity,2
PositionEntity b\entity,-10,10,10
b\mass# = 1
b\xvel# = v1#
b\yvel# = 0
b\zvel# = 0

b.ball = New ball ; Magenta Ball
b\index% = 2
b\name$ = "Magenta"
b\entity = CreateSphere()
EntityColor b\entity,255,0,255
EntityType b\entity,Coll_Ball
ScaleEntity b\entity,2,2,2
EntityRadius b\entity,2
PositionEntity b\entity,10,10,10
b\mass# = 1
b\xvel# = v2#
b\yvel# = 0
b\zvel# = 0

End Function


Function UpdateBalls(dt#=1);
DebugLog "UpdateBalls Begins"
collcount = 0
For b.ball = Each ball
c = CountCollisions(b\entity)
If c = 0 Then ; No collision
DebugLog "No collisions for ball "+b\name$
Else
For i = 1 To c ; For each collision for this ball
collcount% = collcount% + 1 ; Store Index of collision object
d$ = ""
d$ = d$ + b\name$ + "-"
collsubj$(collcount%) = b\name$
ent = CollisionEntity(b\entity,i)
For b2.ball = Each ball ; Find name of collision object
If ent = b2\entity Then
collobj$(collcount%) = b2\name$
d$ = d$ + b2\name$ + " "
Nx# = CollisionNX#(b\entity,i) ; Get Collision Suface Normals
Ny# = CollisionNY#(b\entity,i)
Nz# = CollisionNZ#(b\entity,i)
VdotN# = (b\xvel#*Nx#)+(b\yvel#*Ny#)+(b\zvel#*Nz#) ; Vector Product
NFx# = -2 * Nx# * VdotN# ; Normal Force (direction)
NFy# = -2 * Ny# * VdotN#
NFz# = -2 * Nz# * VdotN#
b\xvel# = b\xvel# + NFx#
b\yvel# = b\yvel# + NFy#
b\zvel# = b\zvel# + NFz#
EndIf
Next
DebugLog d$
Next
EndIf
Next


For b.ball = Each ball

TranslateEntity (b\entity,b\xvel#,b\yvel#,b\zvel#)
Next
ShowStats()
DebugLog "UpdateBalls Ends"
DebugLog ""
End Function


Function ShowStats()

If collcount > 0
Text 10,10,Str(collcount) + " Collisions Logged"
For j = 1 To collcount
Text 10,30+(j*15),collsubj$(j)+"-"+collobj$(j)+" "
Next
Flip
Stop
End If


End Function


My thanks go to anyone who cares to explain.


sswift(Posted 2003) [#7]
Would that mesh happen to be a terrain?

Terrains change their meshes dynamically as you move around. A polygon which had a sharp indentation a moment ago beneath the sphere, may suddenly get smoothed over as more detail is added, resulting in the sphere interpenetrating the mesh. Interpenetration breaks the collision system.

Of course I'm just guessing that Mark didn't code some workaround to this issue into his terrain system.


PaulF(Posted 2003) [#8]
I realise now that I probably asked the wrong question at the start of this thread!

Can anyone please tell me if this is a bug or am I just not unerstanding.

Thanks.


sswift(Posted 2003) [#9]
I'm pretty sure it's a bug. If you want to do collisions between two moving spheres, you may have to write your own sphere to sphere collision routine.