Help > Collision problems with rotating objects

Blitz3D Forums/Blitz3D Programming/Help > Collision problems with rotating objects

EOF(Posted 2003) [#1]
How can I get a rotating object to 'push' a ball?
The object in question is a scaled cube.
Try the example below.

USE THE MOUSE TO CONTROL THE BALL

If you follow the rotating object around then the collisions work .. that is, the ball is blocked.
However, if you go against the rotation then the ball can pass through.

What I want to do is get the object to push or rebound the ball away.

@MASTERBEAKER > This is the problem I'm having regarding the email I sent you.

Any help / scary maths stuff would be appreciated.
Thanks coders.

NOTE: If you keep the ball still and close to the block then NO collisions are reported.

; colliding with rotating block

; Following rotation of block stops ball as expected
; Going against rotation allows ball to pass through *
; * How do I prevent this and get the block to 'push' the ball?

; (Syntax Error)

; display
Graphics3D 640,480,0,2
HidePointer

; entitys
cam=CreateCamera() : MoveEntity cam,0,5,-9
light=CreateLight()
block=CreateCube() : MoveEntity block,-2,0,0 : EntityColor block,200,100,100
ScaleEntity block,0.4,1,3
ball=CreateSphere() : MoveEntity ball,2.5,0,0 : EntityColor ball,100,200,200
PointEntity cam,ball

; collisions
Const cBALL=1 , cBLOCK=2
EntityType ball,cBALL : EntityRadius ball,1
EntityType block,cBLOCK
Collisions cBALL,cBLOCK,2,1

; init
MoveMouse 320,240 : FlushMouse
vx#=0 : vz#=0

; MAINLOOP
Repeat
	; mouse control
	vx=vx+Float(MouseXSpeed())/96
	vz=vz-Float(MouseYSpeed())/96
	vx=vx/1.1 : vz=vz/1.1
	MoveMouse 320,240
	MoveEntity ball,vx,0,vz
	TurnEntity block,0,0.05,0

	UpdateWorld : RenderWorld

	Text 10,10,"Collided with = "+EntityCollided(block,cBALL)
	Text 10,30,"BLOCK handle = "+block
	Text 10,50," BALL handle = "+ball
	Text 320,450,"MOVE BALL WITH MOUSE",1
	Flip
Until KeyHit(1)

End



(tu) sinu(Posted 2003) [#2]
isn't the cube passing thru the ball and not the other way around, you need to setup collision for the cube to, it's a moving object so if the positioning/roation of it is different on updateworld no collision will happen on those collision settings.
The reason it's colliding with it if you follow it is because your hitting it's old position whereas if your moving into the rotation your hitting it's new position or something along those lines.

ps thats what i think, im not to bright so i could be way off.


EOF(Posted 2003) [#3]
Thanks for the info sinu.
I tried

Collisons cBLOCK,cBALL,2,3
but that failed as well.
Nothing gets reported.
Is that because the block is only 'ROTATING' as opposed to physically 'MOVING' ?


(tu) sinu(Posted 2003) [#4]
don't forget you can't have sphere to poly on 2 moving objects, that includes rotation.
So if your cube and ball are moving you'd need to use sphere to sphere or another way other than sphere to poly.


EOF(Posted 2003) [#5]
Ok, thanks again. I still cannot get it working :-(


Ice9(Posted 2003) [#6]
Blitzes collision has a problem with collision and two moving objects. especially when they are moving and translating at such a distance that more than a few of the
vertexes have already passed through the surface by the time
collision is checked. try TurnEntity block,0,0.05,0 or an even slower turn rate and you'll see collision works and it works better on the trailing edge of the cube from the direction it is turning. You may have to write your own collision system for two objects moving at the same time.


EOF(Posted 2003) [#7]
Yes, your right. If I move the block and ball *very* slowly then the collision gets picked up.

@MASTERBEAKER - How did you solve this in your hamsterball/rollerball example?


Beaker(Posted 2003) [#8]
Did you not get my e-mail? I wrote my own collision routines. Maybe I should put together a shareware library or something.


TartanTangerine (was Indiepath)(Posted 2003) [#9]
MasterBeaker. Could you please email me your collision routines....


CopperCircle(Posted 2003) [#10]
Could you mail me too please. Id love to have a look.


Beaker(Posted 2003) [#11]
Sorry guys, my routines aren't in any fit state to be used by others. To clean them up would take a considerable amount of work on top of the work already done creating them. As a result I wouldn't be giving them away.

Sorry if this wasn't clear in my earlier post. :/


EOF(Posted 2003) [#12]
Did you not get my e-mail?

No :-( ... I have been missing several emails lately.
Is 'writing your own collison routines' the only way around the problem?

aybe I should put together a shareware library or something
Sounds good. I have a decent 'rolling ball' thingy under way but because of the colision problems above I have hit a brick wall. Err.. I mean, I keep going through it!! :-0


DJWoodgate(Posted 2003) [#13]
Its possible to make the block push the ball in this example. Its a nasty workaround though, that will not be much good in a game because it involves moving the sphere relative to the block and 2 updateworlds to ensure the block is stationary when the sphere is moved globally. Collisions are only sphere to something, and if the something is not a sphere then it must be stationary. Hopefully Mark will think about adding some more collision options at some point. Until then the only practical way around it seems to be to write your own.


EOF(Posted 2003) [#14]
and if the something is not a sphere then it must be stationary
Ahh. I see.
Hopefully Mark will think about adding some more collision options at some point
Me too. Polygon>Sphere Polygon>Polygon etc ..

I wonder why these are not already in?


(tu) sinu(Posted 2003) [#15]
mark posted once why they weren't in or wouldn't be in soon.
bit to hard to remember what he said though.


DJWoodgate(Posted 2003) [#16]
Here is the nasty workaround mentioned above. Maybe someone can think of better methods to get around some of the limitations, it all gets a bit messy though.

; colliding with rotating block

; Following rotation of block stops ball as expected
; Going against rotation allows ball to pass through *
; * How do I prevent this and get the block to 'push' the ball?
; (Syntax Error)

; One possible approach.  Not very satisfactory.  Lots of issues.
; ( must separate blocks from other blocks and so on )
; Credit Shawn Swift for the ball bouncing/rotating code.

; Note: Transfer of block momentum is incorrectly implemented, but thats the
; least of your worries when using this method so hey... :-) 
; (D. Woodgate)

; display
Graphics3D 640,480,0,2
HidePointer
SeedRnd MilliSecs()

; entitys
campiv=CreatePivot()
camera=CreateCamera(campiv)
PositionEntity camera,0,50,0
PointEntity camera,campiv

light=CreateLight(1,campiv)
TurnEntity light,60,-60,0

texture=CreateTexture(128,128)
SetBuffer TextureBuffer(texture)
Color 128,128,128
Rect 0,0,128,128
Color 128,0,0
Rect 0,0,64,64 Rect 64,64,64,64
SetBuffer BackBuffer()
ScaleTexture texture,0.25,0.25

Color 255,255,255
plane=CreatePlane()
EntityColor plane,50,100,50
PositionEntity plane,0,-1,0

; collisions
Const cBALL=1 , cBLOCK=2, cWALL=3

Collisions cBALL,cBLOCK,2,2
Collisions cBALL,cWALL,2,2

Dim block(50)
Dim rotspd#(50)


; create arena
Nwall=CreateCube()
EntityColor Nwall,200,0,0
EntityType Nwall,cWALL
FitMesh Nwall,-35,-1,-0.5, 70,2,0.5
PositionEntity nwall,0,0,35
Swall=CopyEntity(Nwall)
PositionEntity Swall,0,0,-35
Ewall=CopyEntity(Nwall)
RotateEntity EWall,0,90,0
PositionEntity Ewall,-35,0,0
Wwall=CopyEntity(Nwall)
RotateEntity Wwall,0,-90,0
PositionEntity Wwall,35,0,0

; The blocks
accel#=1
For x=-24 To 24 Step 15
	For z=-24 To 24 Step 15
		numblock=numblock+1
		block(numblock)=CreateCube()
		PositionEntity block(numblock),x,0,z
		EntityColor block(numblock),200,100,100
		ScaleMesh block(numblock),0.4,1,3.5
		EntityType block(numblock),cBLOCK
		rotspd(numblock)=Rnd(2,15)
		If Rand(1,2)=1 Then rotspd(numblock)=-rotspd(numblock)
	Next	
Next

; the ball
ballrad# = 1.5
maxballspd# = 3
Drag#=0.98

ball=CreatePivot() ; Collision proxy
PositionEntity ball,0,0,0
EntityRadius ball,ballrad
EntityType ball,cBALL

orb=CreateSphere(12) ; The visible ball
ScaleEntity orb,ballrad,ballrad,ballrad
EntityTexture orb,texture

; init
MoveMouse 320,240 : FlushMouse
vx#=0 : vz#=0

; MAINLOOP
Repeat
	; mouse control
	MXSpd# = Float(MouseXSpeed())/255
	MySpd# = Float(MouseYSpeed())/255
	MoveMouse 320,240
	
	; parent ball collision proxy to block collision candidate
	; rotate all blocks	and calculate ball translation due to block rotation
	Gosub updateblocks
	
	; Reset block state
	UpdateWorld

	; unparent ball from block
	EntityParent ball,0
	
	; update ball motion with drag and user input.  Limit ball speed
	Gosub updateball

	; translate ball taking into account relative movement
	; get ball position before applying collisions.
	Gosub moveball

	; Second update world to capture ball collisions
	UpdateWorld 
	 
	Gosub checkcollisions
	
	; rotate ball according to motion vector
	Gosub rotateball

	Gosub movecamera

	RenderWorld

	Text 320,450,"MOVE BALL WITH MOUSE",1
	Flip

Until KeyHit(1)

End

.checkcollisions
	If CountCollisions(ball)>0 Then
	; Swifty bounce code:
	; Get the normal of the surface which the entity collided with. 
		Nx# = CollisionNX(ball, 1)
		Nz# = CollisionNZ(ball, 1) 
	; Compute the dot product of the entity's motion vector and the normal of the surface collided with. 
	; Adding Rx and Rz is my lame attempt to factor in block rotational momentum
		VdotN# = (Vx# + Rx#) * Nx# + (Vz# + Rz# ) * Nz# 
	; Calculate the normal force. 
		NFx# = -2.0 * Nx# * VdotN#
		NFz# = -2.0 * Nz# * VdotN#
	; Add the normal force to the direction vector. 
		Vx# = Vx# + NFx# 
		Vz# = Vz# + NFz# 
	EndIf
Return

.updateball
	; apply drag
	Vx# = Vx# * Drag# : Vz# = Vz# * Drag#
	
	; transform mouse input so we move the ball with respect to the camera pivot	
	TFormVector MxSpd,0,-Myspd,campiv,0
	Vx# = Vx# + TFormedX()
	Vz# = Vz# + TFormedZ()
	
	; limit ball speed, things break down if its going too fast
	ballspd# = Sqr(Vx# * Vx# + Vz# * Vz#)
	If ballspd# > maxballspd# Then
		Vx# = Vx# / ballspd# * maxballspd#
		Vz# = Vz# / ballspd# * maxballspd#
	; keep the ball rolling if it stops
	ElseIf ballspd<0.01 Then
		vx#=Rnd(-1,1) vz#=Rnd(-1,1)
	EndIf
Return

.updateblocks
	; get global ball position
	Gx#=EntityX(ball,1)
	Gz#=EntityZ(ball,1)
	
	accel# = 1+(KeyDown(52)-KeyDown(51))*0.01
	
	; parent ball to nearest rotating block.  This means of course that blocks
	; cannot be too close together or too close to any other colliding object.

	For i=1 To numblock
		If EntityDistance(ball,block(i))<6.5 Then 
			EntityParent ball,block(i)
			EntityColor block(i),200,200,100
		Else
			EntityColor block(i),200,100,100
		EndIf
		rotspd(i) = rotspd(i) * accel#
		TurnEntity block(i),0,rotspd(i),0		
	Next
	
	; the distance the ball has moved due to block rotation
	; if there is no collision candidate then this will be zero
	Rx# = Gx# - EntityX(ball,1)
	Rz# = Gz# - EntityZ(ball,1)
Return

.moveball
	; correct for relative movement
	TranslateEntity ball,Rx,0,Rz,True

	; get ball position before movement
	OldX# = EntityX(ball,1) 
	OldZ# = EntityZ(ball,1)

	; move ball globally 
	TranslateEntity ball,Vx#,0,Vz#,True
Return

.rotateball
	; get distance ball has moved
	NewX# = EntityX(ball,1) 
	NewZ# = EntityZ(ball,1) 
	Mx# = (NewX# - OldX#) 
	Mz# = (NewZ# - OldZ#)
	 
	; Swifty rotation code:
	; 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 difference.
	XAngleAdjust# = (Mx# / ballrad) * (180.0/Pi) 
	ZAngleAdjust# = (Mz# / ballrad) * (180.0/Pi)
	PositionEntity orb,EntityX(ball,1),EntityY(ball,1),EntityZ(ball,1),True
	TurnEntity orb,ZAngleAdjust#,0,-XAngleAdjust#,True 
Return

.movecamera
	; move the camera
	TurnEntity campiv,0,KeyDown(203)-KeyDown(205),0
	TurnEntity camera,KeyDown(200)-KeyDown(208),0,0
	MoveEntity camera,KeyDown(32)-KeyDown(46),KeyDown(31)-KeyDown(45),KeyDown(30)-KeyDown(44)	
Return


[Edit] Changed the bounce routine a bit. Seems to give better results as does using sliding collisions, though I am not quite sure why (I suspect it has to do with the fact I am doing two translations ) I am now wondering if more flexibility might be gained by using multiple collision proxies, though I am not sure yet how that would pan out in practice.


EOF(Posted 2003) [#17]
Hey. What can I say!!!
Lovely stuff David (and Swift)
Something for me to play with over the weekend.
Thankyou kindly for digging in and getting yours hands dirty. Much appreciated :_:


DJWoodgate(Posted 2003) [#18]
Made a few changes above. Still fudging the block rotation to ball motion thing, but it's a slightly better fudge.