Energy loss problem with physics objects bouncing off each other.

Blitz3D Forums/Blitz3D Programming/Energy loss problem with physics objects bouncing off each other.

Here's some physics for you of two objects with variable mass and different coefficients of friction colliding with one another. Still not 100% proper physics though. I didn't know what to do when the coefficients of friction (elasticity) are different.

Be aware that you must make sure that you do this only once for each pair of colliding objects. If you just detect every object that collides and then determine what it collided with and do this code, then you'll UNDO the energy transfer that takes place when you do it the second time.

I couldn't think of a way to allow you to do the collisoon code just for one of the objects, transfer the energy, and then do the other. Like if two balls collide with eachother head on, if you just did one first and then the other after, with the first one, you'd just cancel out it's momentum and end up with 0 movement, and then have nothing to transfer when you get to the second. They have to transfer their energy simulatanously. I suppose you could maintain a before and after state for all objects though and operate on the before state and set the after. Hm...

     ; Convert the player's velocities and directions into vectors.
	    	        MagDirToVector(ThisBike)
					MagDirToVector(HitPlayer)

					;DebugLog("Before:")
					;DebugLog(HitPlayer\VECTOR_X#)
					;DebugLog(HitPlayer\VECTOR_Y#)
					;DebugLog(HitPlayer\VECTOR_Z#)
					;DebugLog("")

					; Transfer momentum from one entity to the other.

						; First, get caclulate a vector from the center of mass of the first player,
						; to the center of mass of the second.
						
							CNx# = EntityX#(ThisBike\Pivot, True) - EntityX#(HitPlayer\Pivot, True)
							CNy# = EntityY#(ThisBike\Pivot, True) - EntityY#(HitPlayer\Pivot, True)
							CNz# = EntityZ#(ThisBike\Pivot, True) - EntityZ#(HitPlayer\Pivot, True)
						
						; Normalize the vector.
		
							CNl# = Sqr(CNx#*CNx# + CNy#*CNy# + CNz#*CNz#)
							CNx# = CNx# / CNl#
							CNy# = CNy# / CNl#
							CNz# = CNz# / CNl#

						; Find the length of each of the movement vectors along the normal.

							;V1dotN# = ThisBike\VECTOR_X#*CNx#  + ThisBike\VECTOR_Y#*CNy#  + ThisBike\VECTOR_Z#*CNz#
							;V2dotN# = HitPlayer\VECTOR_X#*CNx# + HitPlayer\VECTOR_Y#*CNy# + HitPlayer\VECTOR_Z#*CNz#

						; Get the mass of the objects involved in the collision.

							Mass1# = 1.0
							Mass2# = 1.0

						; Get the coefficient of restitution of each object.
						
							; The coefficient of restitution is a value between 0 and 1 which defines how elastic
							; the objects that collide are.  A metal ball is inelastic, and would have a coefficient
							; of 0... all energy would be transferred from the first object to the second during
							; a collision.  A basketball on the other hand has a coefficient of 0.6...  So it bounces
							; when it hits the floor rather than transferring all it's energy to the floor.  
							; A baseball, btw, has a coefficient of 0.55.
													
							E1# = 0.25
							E2# = 0.25
							
						; Calculate the coefficient of restitution to use for the collision.
							
							; Note:
							; This is probably not the correct physical way to model a collision when the two
							; objects have different coefficients of friction, but it should work well enough.
																										
							; If the first object is softer than the second object...
							If E1# > E2#
								E# = E1#		; Use the first object's coefficient.
							Else
								E# = E2#		; Use the second object's coefficient.
							EndIf

						; Caclulate the new velocities of the two objects.
							
							C# = CNx# * (ThisBike\VECTOR_X# - HitPlayer\VECTOR_X#) + CNy# * (ThisBike\VECTOR_Y# - HitPlayer\VECTOR_Y#) + CNz# * (ThisBike\VECTOR_Z# - HitPlayer\VECTOR_Z#)
							
							P1# = ((Mass2# * C#) / (Mass1# + Mass2#)) * (1.0 + E#)
							
							ThisBike\VECTOR_X# = ThisBike\VECTOR_X# - P1# * CNx#
							ThisBike\VECTOR_Y# = ThisBike\VECTOR_Y# - P1# * CNy#
							ThisBike\VECTOR_Z# = ThisBike\VECTOR_Z# - P1# * CNz#

							P2# = ((Mass1# * C#) / (Mass1# + Mass2#)) * (1.0 + E#)
							
							HitPlayer\VECTOR_X# = HitPlayer\VECTOR_X# + P2# * CNx#
							HitPlayer\VECTOR_Y# = HitPlayer\VECTOR_Y# + P2# * CNy#
							HitPlayer\VECTOR_Z# = HitPlayer\VECTOR_Z# + P2# * CNz#
	
						; Convert the movement vector back into a magnitude and direction.
							VectorToMagDir(ThisBike,  ThisBike\VECTOR_X#,  ThisBike\VECTOR_Y#,  ThisBike\VECTOR_Z#)
							
						; Store the new movement vector for the player collided with.
						
						    HitPlayer\Vx# = HitPlayer\VECTOR_X#
						    HitPlayer\Vy# = HitPlayer\VECTOR_Y#
							HitPlayer\Vz# = HitPlayer\VECTOR_Z#