Collision - Same old story!

Blitz3D Forums/Blitz3D Beginners Area/Collision - Same old story!

Grovesy(Posted 2005) [#1]
Ok, i know this has been asked a 100 times, but im still having probables with collision detection.

All I want to do is detect collision between meshs, lets say 2 cubes. How do I do this?

Any help is appricated.

Cheers


Beaker(Posted 2005) [#2]
What you must know is that the collision system won't handle collisions between 2 moving cubes (not mesh cubes, but collision cubes). In fact the only 2 *moving* objects you can collide is two spheres (again not meshes but collision spheres - the shape of the object doesn't actually matter).

However, you can collide a moving sphere with a static mesh or cube.

You have three choices:

1) use sphere collisions for your 2 cubes.

2) use the MeshesIntersect() command.

3) make your own collision system (or use a 3rd party one like Nuclear Glory [EDIT: actually I'm not sure you will be any better off with Nuclear], or a physics system: ODE (KODE or JV-ODE) or Tokamak).


PowerPC603(Posted 2005) [#3]
I once altered the car-demo that comes with B3D.

I tried to do collisions with two moving objects.
I positioned a cube on the floor, which moves on it's own (just a MoveEntity inside the main loop).
Then I tried to hit it with my car.
When I was driving against it's backside (the cube would move away from me if I should stop the car), I could collide with it.
When the cube was coming towards me, I ran right through it.

That was because I've setup collisions between the car and the cube, but not the other way around.
That was the solution for my problem.
It might not work in any situation.
; Initiate a 3D window of size 800x600
Graphics3D 800, 600, 0, 2
; Set backbuffer
SetBuffer BackBuffer()

; Set some variables for collision-types
col_cube1 = 1
col_cube2 = 2

; Create a floor-plane
Floor = CreatePlane()

; Create cube1, give it a color, position it, give it a spherical collision radius and set it's collisiontype
cube1 = CreateCube()
EntityColor cube1, 255, 0, 0
PositionEntity cube1, -10, 1, 0
EntityRadius cube1, 1
EntityType cube1, col_cube1

; Create cube2, give it a color, position it, give it a spherical collision radius and set it's collisiontype
cube2 = CreateCube()
EntityColor cube2, 0, 255, 0
PositionEntity cube2, 10, 1, 0
EntityRadius cube2, 1
EntityType cube2, col_cube2

; Setup collisions for collisiontype col_cube1 to col_cube2 and vice versa
Collisions col_cube1, col_cube2, 1, 2
Collisions col_cube2, col_cube1, 1, 2

; Create and position camera
camera = CreateCamera()
MoveEntity camera, 0, 5, -10

; Main loop
While Not KeyHit(1)
	; Move both entities towards eachother
	MoveEntity cube1, 0.1, 0, 0
	MoveEntity cube2, -0.15, 0, 0

	; Detect when cube1 has collided with cube2
	; When collision occurs, reposition both entities to their starting positions
	If EntityCollided(cube1, col_cube2) Then
		PositionEntity cube1, -10, 1, 0
		PositionEntity cube2, 10, 1, 0
	EndIf

	; Process collicions
	UpdateWorld
	; Render scene
	RenderWorld
	; Flip backbuffer to frontbuffer
	Flip
Wend

This short code shows two moving cubes (moving towards eachother) and hitting eachother.
But they stop on impact, even when one cube is moving faster than the other.
You could always check to see if both cubes are still moving.
If not (they have collided and are pushing against eachother), do something else.

Like Beaker said, both cubes here use an entityradius, so their collisionboxes are actually spheres, but you don't see any evidence of that in this example.

To detect collisions, I've added a small If-EndIf part in the main-loop.
As soon as cube1 collides with an object which has cul_cube2 as collisiontype, reset both cubes to their starting positions.


jfk EO-11110(Posted 2005) [#4]
A few additional, general words to collsion, although this may be written in the Documentation. A minimum setup for collision handling is:

define what type a mesh is (give away numbers for families that react all the same), eg: all cars are type 1, all static map (ground etc.) is type 2 etc. It's up to you to choose any numbers, it could also be 1000 or 333:
EntityType player,1
EntityType landscape,2


Then you need to define how these types react on one another. You always need 2 types to define a reaction, eg:

collisions 1,2,2,2


this means reaction of entity type 1 versus type 2 will be mode 2(sphere to polygon collision detection).

There 3 possible collision reactions:

1: sphere to sphere
2: sphere to polygon
3: sphere to box

Where polygon means the real shape of the mesh will be used, sphere means there is a hypotetical sphere around the mesh, no matter how the mesh looks. box means there's a hypotetical box around the mesh. You can define their size by: EntityRadius and EntityBox

The last parameter of "collisions" defines some reaction options:
1: stop
2: full slide
3: slide and prevent sliding down slope

Ok, after defining the Tyes of the meshes, and how these types should react on one another, you shouldn't forget to call updateworld in the mainloop to make to collisions take place. you best place Updateworld() right before Renderworld()

Updateworld() will also process animated Meshes and it allows a speed parameter, but this is not related to collisions. (simply omit the parameter)

Now you already have a working automatic collision handler. If you want to detect collisions of certain meshes, you need to use commands like

EntityCollided(entity, type) 


that will return the entity handle of the collided mesh. Note in this case you should place ENtityCollided between Updateworld and Renderworld.
BTW: EntityCollided takes two parameters, where the second needs to be a type (see above, ENtityType).
So let's say there's an Entity named Player, and a oildrum mesh of type 4 (Entitytype oildrum27,4), then you would use it this way:
coll=EntityCollided(player,4)
if coll<>0 ;collided with something of type 4
 if coll=oildrum27 then
  print "collided with oildrum 27"
 endif
endif

I hope that helps. And check out the Docs.


nadia(Posted 2005) [#5]
Isn't there also a trick about doing the collision checking between the calls to UpdateWorld{} and
RenderWorld()? Something to do with catching a collision before a mesh moves through another mesh like in fast flying bullets. Does this also help for checking collision between two moving entities?

thanx


jfk EO-11110(Posted 2005) [#6]
I think if you want to ckeck collisions of multiple moving objects, you need to set up Collisions in both directions (eg. Collisions 1,2,x,x and 2,1,x,x). It's even simpler when both moving objects are from the same type, so you can simply use Collisions 1,1,x,x.

There has been a work around for No-Action Collision detection, maybe that's what you meant? First move the object to the new position and store that position in variables, then call Updateworld(), then use EntityCollided to check if it collided, then hide the object (this will automaticly erase its collision buffer) , then position it at the previously stored coordinates and show it again.


nadia(Posted 2005) [#7]
thanx jfk,
this sounds more complicated then what I had in mind and doesn't seem to apply to moving objects. I guess to achieve reliant, fast collision detection it might be best to use an external physics library. Maybe I'll buy that JV-ODE wrapper. The demos look great!