Collision Vector and Force...need help

Blitz3D Forums/Blitz3D Programming/Collision Vector and Force...need help

Chroma(Posted 2003) [#1]
It's pretty simple. You place a ball above a surface. Apply gravity. Check for the collision. At the moment of collision you gather some information. The velocity of the ball, the collision normal using CollisionNX-Y-Z. You take something like this:

See Below...


And add it back into the velocity. Is there something to do with Blitz's collision system that makes this unreliable? Sometimes the ball bounces. Sometimes it sticks to the floor. Sometimes it bounce twice then sticks to the floor. Anyone know what the deal is?


DJWoodgate(Posted 2003) [#2]
Halo posted some code a little while ago that does this sort of thing. I suggest you take a look.
http://www.blitzbasic.co.nz/bbs/posts.php?topic=21629
Though where he poses the question 'Should the collision normals be absolute value or not' in the first bit of code I suspect the answer is not.


Chroma(Posted 2003) [#3]
Actually, this should work and eliminates the abs part. Any ideas why this sometimes sticks after 1 or 2 bounces? I think it may be the collision detection screwing it up. You shouldn't have to do all that extra stuff that halo does.

NVx# = velx# * (-1.0 - elasticity#) * CollisionNX(ent,1)
NVy# = vely# * (-1.0 - elasticity#) * CollisionNY(ent,1)
NVz# = velz# * (-1.0 - elasticity#) * CollisionNZ(ent,1)



DJWoodgate(Posted 2003) [#4]
Well its a bit different from the plain old reflective bounce stuff that Darkeagle has kindly posted in the archives. So maybe thats right, I don't really have an intuitive grasp of this stuff though, so I would have to play around with some vectors and try it out. It doesn't look it would work though, bearing in mind the way the other method works. Take a look.
http://www.blitzbasic.co.nz/codearcs/codearcs.php?code=670
I assume the undefined bounce in his code is sort of similar to elasticity in yours. Thing is to do it properly I think you need to calculate interpenetration and it looks like Halo is doing that. I haven't really got into this sort of stuff though, I'm happy enough just for some normal bouncing at the moment :)


Chroma(Posted 2003) [#5]
For an example, say you have a ball falling straight down and at the point of collision the Y velocity is -5.0m/sec and the elasticity (coefficient of restitution - Kr) is 0.62. Plugging that into the equation above we get:

NVy# = -5.0 * (-1.0 - 0.62) * 1.0


Which would mean we add 8.1 back into the Y velocity. 5 of the 8.1 is spent negating the current -5 velocity and the remaining 3.1 is the new Y velocity. 3.1 is 62% of the original velocity. This "SHOULD" work perfectly. Can anyone tell me why it doesn't?


DJWoodgate(Posted 2003) [#6]
Yeah, but I suggest you try it for other intercept angles and particularly when the coliding surface is not axis aligned. I'm not saying you are wrong, just that it might be a bit of an oversimplification.


Chroma(Posted 2003) [#7]
I took halo's cube in his app and rotated it. The balls did not roll and fell right thru the walls. Quite odd. I also tried Shawn's code (that's where Darkeagle got his bounce code from) and that intermittently sticks too. I just think there's a lot of unnecessary math going on to make the collisions bounce correctly. And that may be due to the built in collision of Blitz. I DON'T know if that's true tho.

And theoretically, as long as the CollisionN commands return the correct collision normal then the ball should bounce in the right direction regardless of the walls orientation.


DJWoodgate(Posted 2003) [#8]
Couple of things there. The balls would fall through the walls if you rotate the cube while they are in contact with it. Collisions where both objects are moving are only sphere to sphere. Note Halo is using sliding collisions, that might help. Intuitively I would say it should not make a difference, but you might imagine that at some points in the cube you will have two or more collisions to deal with at the same time. Sliding collisions might help in this respect even its a bit of a fudge.


Chroma(Posted 2003) [#9]
I'm not rotating the floor plane in my test. It's just a straight drop from 9.8 meters high. There's some math messing up where somehow the resultant velocity is 0 when it should be a positive number. That's the only thing I can figure as to why the ball sometimes sticks to the floor when it should bounce naturally.

I double checked the code and it outputs the right number. Just doesn't make sense. So either CollisionN or the actual collision detection is to blame as far as I can tell. Is it possible it's registering a double collision hit? Maybe on the way back up it registers another collision and kills the velocity.

Maybe I need to move the position of the ball in the collision normal direction the radius of the ball +.01 so there can be no possible second collision detection.


DJWoodgate(Posted 2003) [#10]
Maybe not. Have a look at this code brought to us by Bradford6 and Sswift. It might help resolve some issues. http://www.blitzbasic.co.nz/bbs/posts.php?topic=14125


Chroma(Posted 2003) [#11]
Ok...I guess there's something I'm missing about how the whole thing works. You "should" be able to take the velocity at the moment of collision and use that with the collisionN commands and make a simple bounce. I just don't understand why it sometimes sticks to the ground. I've checked out the above code and don't see why it needs to be so complex.

Can someon explain step by step what happens when a ball falls and bounces. Halo, you mentioned that you solved a problem with collisions and bounce type physics, is this the problem you were encountering?


Tom(Posted 2003) [#12]
http://www.wildtangent.com/developer/howtos/CollisionHowTo/

http://www.dev-gallery.com/programming/opengl/colision/collision3.htm


Chroma(Posted 2003) [#13]
Thanks Tom...very informative. I'll give it another go.


Jeremy Alessi(Posted 2003) [#14]
I had similar problems to yours with the ball code in Aerial Antics. They've all been fixed in the new version. I had problems when I would translate the ball and not directly before doing so record it's old position and then directly after record it's new position. I worked off of Sswift's code and use this basically. This is from my Splash Screen which reacts the same everytime.


num_splash_collisions=CountCollisions(sde\h_andle)
			If num_splash_collisions=0		
				sde\vx#=sde\curr_x#-sde\old_x#
				sde\vz#=sde\curr_z#-sde\old_z#
				sde\velocity#=Sqr(sde\vx#^2+sde\vy#^2+sde\vz#^2)
													
				sde\old_x#=sde\curr_x#
				sde\old_y#=sde\curr_y#
				sde\old_z#=sde\curr_z#
				
				
				If sde\velocity#>0
					sde\dx# = sde\vx# / sde\velocity#
					sde\dy# = sde\vy# / sde\velocity#
					sde\dz# = sde\vz# / sde\velocity#
					
					sde\air_friction_force#=splash_air_friction# * sde\velocity#^2
					sde\velocity#=sde\velocity-sde\air_friction_force#
										
					sde\vx# = sde\dx# * sde\velocity#
					sde\vy# = sde\dy# * sde\velocity#
					sde\vz# = sde\dz# * sde\velocity#
				EndIf
			
				sde\vy#=sde\vy#-splash_gravity#
				TranslateEntity sde\h_andle,sde\vx#,sde\vy#,sde\vz#
									
				sde\curr_x#=EntityX#(sde\h_andle)
				sde\curr_y#=EntityY#(sde\h_andle)
				sde\curr_z#=EntityZ#(sde\h_andle)
				
				Mx# = (sde\curr_x# - sde\old_x#) 
				Mz# = (sde\curr_z# - sde\old_z#) 
				; Rotate the entity the right amount for it's radius and the distance it has moved along the X and Z axis. 
				; This is kinda a hack and only designed for rolling on planes but you won't notice the diffrence. 
				XAngleAdjust# = (Mx# / (MeshWidth(sde\h_andle)/2)) * (180.0/Pi) 
				ZAngleAdjust# = (Mz# / (MeshWidth(sde\h_andle)/2)) * (180.0/Pi) 
				TurnEntity sde\h_andle,ZAngleAdjust#,0,-XAngleAdjust#,True
			Else
				If sde\velocity#>0
					splash_hit=CollisionEntity(sde\h_andle,num_splash_collisions)
					If sde\velocity#>.1
						; Rotate the entity the right amount for it's radius and the distance it has moved along the X and Z axis. 
						; This is kinda a hack and only designed for rolling on planes but you won't notice the diffrence. 
						XAngleAdjust# = (Mx# / (MeshWidth(sde\h_andle)/2)) * (180.0/Pi) 
						ZAngleAdjust# = (Mz# / (MeshWidth(sde\h_andle)/2)) * (180.0/Pi) 
						TurnEntity sde\h_andle,ZAngleAdjust#,0,-XAngleAdjust#,True
					EndIf
					For i=1 To CountCollisions(sde\h_andle)	
						If sde\vy#<-.1 And ChannelPlaying(kick_ball_chan)=0
							kick_ball_chan=EmitSound(kick_ball,sde\h_andle)
							Exit
						EndIf
					Next
					;Get the normal of the surface which the entity collided with. 
					Nx# = CollisionNX#(sde\h_andle, num_splash_collisions) 
					Ny# = CollisionNY#(sde\h_andle, num_splash_collisions) 
					Nz# = CollisionNZ#(sde\h_andle, num_splash_collisions) 
					If CollisionNY#(sde\h_andle,num_splash_collisions)<1
						sde\vy#=sde\vy#-splash_gravity#
					EndIf
					; Compute the dot product of the entity's motion vector and the normal of the surface collided with. 
					VdotN# = sde\vx# * Nx# + sde\vy#*Ny# + sde\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. 
					sde\vx# = sde\vx# + NFx# 
					sde\vy# = sde\vy# + NFy# 
					sde\vz# = sde\vz# + NFz# 
						
					sde\dx# = sde\vx# / sde\velocity#
					sde\dy# = sde\vy# / sde\velocity#
					sde\dz# = sde\vz# / sde\velocity#
						
					sde\velocity#=sde\velocity#-(splash_ball_ground_friction#)
						
					sde\vx# = sde\dx# * sde\velocity#
					sde\vy# = sde\dy# * sde\velocity#
					sde\vz# = sde\dz# * sde\velocity#
				
					If sde\vy#<=.005 And CollisionNY#(sde\h_andle,num_splash_collisions)=1
						sde\vy#=0
						sde\old_y#=sde\curr_y#
					EndIf
					If sde\velocity#<.1 And sde\vy#<=.005
						sde\velocity#=0
						sde\vx#=0
						sde\vy#=0
						sde\vz#=0
						sde\dx=0
						sde\dy#=0
						sde\dz#=0
						PositionEntity(sde\h_andle,EntityX#(sde\h_andle),1,EntityZ#(sde\h_andle))
						sde\curr_x#=EntityX#(sde\h_andle)
						sde\curr_y#=EntityY#(sde\h_andle)
						sde\curr_z#=EntityZ#(sde\h_andle)
						sde\old_x#=sde\curr_x#
						sde\old_y#=sde\curr_y#
						sde\old_z#=sde\curr_z#
					EndIf
				EndIf
			EndIf
			UpdateWorld
		Next
		RenderWorld tween#