collision detection speed

Blitz3D Forums/Blitz3D Programming/collision detection speed

ryan scott(Posted 2004) [#1]
is there a way to UNDO this?

collisions TYPE1,TYPE2

I really want to segment my objects into sectors, so not all objects will be included in collision detection.

There's no point checking collisions with your player and an object that's 50 feet away, even though that object is visible.

I am noticing significant slowdown when i have 10 bullets on screen vs when i have none. My collision code is pretty standard - i'm using Object and Handle to get directly to the colliding objects, it's just that 10 bullets is 10 times more collision detection on just the bullets than 1 bullet. 10 bullets, 10 enemies, terrain, walls, blah blah. It adds up. The number of objects on screen is still reasonable, its just collision detection that's killing me, I think.

Anyone have any idea how I can undo a Collisions statement?

Halo? You seem to be the resident deep blitz genius.

I want to develop a simple system like you use with hiding entities that aren't visible, except i'll hide from the collision system. it'll be an even tighter area than with the visible area.


Jeremy Alessi(Posted 2004) [#2]
You must set the EntityType() to nothing or something other than TYPE1 or TYPE2. I think you can actually just call ResetEntity() to clear it's collision type.


Boiled Sweets(Posted 2004) [#3]
try ClearCollisions()

I use this and it's fine. Obviously you will need to setup any collision you want afterwards...


ryan scott(Posted 2004) [#4]
EntityType to nothing... ah ha! i was thinking about it the other way.

ClearCollisions - didn't know it existed. Would be nice if it were more specific! Hmm, would be nice if it were in the documentation too.

ClearCollisions TYPE1,TYPE2

Thanks!


ryan scott(Posted 2004) [#5]
I just discovered:
ClearCollisions clears the list of everything that recently collided, which is the same as doing ResetEntity on all the collided entities. It doesn't clear the list of objects that are checked for collisions. it doesn't do what I want here.

I just ran a speed test, and EntityType model,0 (where 0 is not involved in any collisions) does NOT increase the speed of checking.

In fact it seems that the entity is involved in collision checking because it's the same speed!


In fact, UpdateWorld runs the same whether or not I have ANY Collisions statements. The only thing that speeds it up is HideEntity.

UpdateWorld does more than collision detection, maybe collision detection is actually quite fast, and it's the other things that UpdateWorld does that slow things down?

I don't know - i think I see exponential slowdown the more bullets i have on screen, which would seem to me that there's something going on like bullets x enemies collision checking. just drawing a new bullet should be a linear progression. collision detecting will grow faster.

so, if not collision detection i can't figure out why i'm losing so much speed

here's testing code, kinda interesting.

; speed test comparing setting EntityType ent,0 to remove from collisions
; vs HideEntity.  HideEntity of course removes the entity from sight so 
; it doesn't do the same thing.

; verdict - EntityType ent,0 doesn't do anything!
; UpdateWorld still takes the same amount of time. 
; Hell it takes the same amount of time if you don't have any Collisions statement.

 
Graphics3D 640,400,0,0 
toSphere=1:toPoly=2:toBox=3
makeStop=1:fullSlide=2:preventDownSlide=3

Global T_BULLET=1, T_ENEMY=2
Type bullet
	Field model
End Type
 
Global howmany=200
For t = 1 To howmany
	b.bullet=New bullet	
	b\model=CreateSphere(8) 
	EntityType b\model,T_BULLET
	;HideEntity b\model
	ScaleEntity b\model,1,1,1
	PositionEntity b\model,Rnd(100),Rnd(100),Rnd(100)
	EntityRadius b\model,1

	e=CreateCube() 
	EntityType e,T_ENEMY
	ScaleEntity e,1,1,1
	PositionEntity e,Rnd(100),Rnd(100),Rnd(100)
	EntityBox e,1,1,1,1,1,1 
	
Next

Collisions T_BULLET,T_ENEMY,toPoly,fullSlide 
runtest("toPoly, fullslide")
Collisions T_BULLET,T_ENEMY,toBox,fullSlide 
runtest("toBox, fullslide")
Collisions T_BULLET,T_ENEMY,toBox,makeStop 
runtest("toBox, makeStop")
Collisions T_BULLET,T_ENEMY,toSphere,fullSlide 
runtest("toSphere, fullslide")

Function runtest(description$)
	For b.bullet = Each bullet	
		; eventually we either change the entitytype of each entity or we hide them all.
		; the speed increase comes from hiding them.
		; no speed increase by changing the entitytype.
		
		EntityType b\model,0	; -> no speed increase 
		;HideEntity b\model 	; -> speed increase (uncomment this, and comment the line above to compare)

		did=did+1
		s=MilliSecs()
		For x = 1 To 300
			UpdateWorld ; docs claim this is where collision detection happens.
		Next
		e=MilliSecs()-s
		remain=howmany-did
		DebugLog remain+" "+description$+": "+e
	Next
End Function
	
WaitKey




Paul "Taiphoz"(Posted 2004) [#6]
thats a damn good idea.

If entdistance(player,tree_type)=>20 meters then enttype treetype,9999

ie just set the entitytype to soem mad value so that its not being picked up on the coll type1,type2 calls.

Not actually tested this yet, but im sure hes right, has anyone else done this ?


Jeremy Alessi(Posted 2004) [#7]
Just use ResetEntity() so it has no collision type.


Ice9(Posted 2004) [#8]
I turn off collision on the area the player isn't in
and turn on collision for entities in the immediate area.
For complex gemetry I place a quad with entity alpha in
front of it. All entities are indexed by area and stored
in arrays that represent the world. You could also do
a collision BSP. I use the same method for my visible
entities, hiding all those entitities that are off screen.
Great fps increase doing that as well as with collision.

Checking distance on a lot of entities can be costly if you
have a lot of entities.


Boiled Sweets(Posted 2004) [#9]

ClearCollisions clears the list of everything that recently collided, which is the same as doing ResetEntity on all the collided entities. It doesn't clear the list of objects that are checked for collisions. it doesn't do what I want here.



No it does not! It does not clear the list of recently collided entities but clears the internal Blitz list that holds information about which entities collide with each other and how to behave if they collide.

The Blitz documentation is pretty clear on this...


Clears the collision information list.

Whenever you use the Collisions command to enable collisions between two different entity types, information is added to the collision list. This command clears that list, so that no collisions will be detected until the Collisions command is used again.


For example if you call "collision TYPE1, TYPE2" an entry is made in the internal Blitz collision table. This table is checked each UpdateWorld. Calling ClearCollisions clears this list NOT a list of recently collided entites. Yes it will clear ALL collisions but simply set the ones you want up again by calling "Collision TYPE3, TYPE4" etc etc...

Also you may have to be careful if you want to use EntityDistance() to see how far an object is away as calling this lots of times and often will have a major impact on your UpdateWorld FPS. I had a similar problem with the world editor in qoob. I get round it by setting up camerafog and doing a clever cull (HideEntity) based upon EntityDistance() but only if the player has moved a certain distance into the fog...

Hope the above helps...


Zethrax(Posted 2004) [#10]
@Jeremy:- ResetEntity doesn't clear the collision type. It just resets the entity's collision data to whatever position the entity is at. Use it after you teleport an entity, for example, to prevent the entity from being repositioned back to where it collides with any entity it is enabled to collide with.


Damien Sturdy(Posted 2004) [#11]
I use the technique and it is an excelent way of doing things when you do it right. It has enabled me to have 120 ships going around in supernova (mayhem) the chances are you already have a loop iterating through the bullets. Add an extra line of code before updating? its worth it in these instances because youre more than likely going to save more processor time than the commands will use :)


big10p(Posted 2004) [#12]
I'd be surprised if Blitz doesn't do some intelligent culling internally where collisions are concerned. I doubt it simply checks everything against everything in the collisions list. I hope not, anyway.

Are you sure the slowdown isn't surface count related?


Jeremy Alessi(Posted 2004) [#13]
Oh yeah that's right ... I havne't used ResetEntity() in forever ... just read the docs.

Could be quite a few things though slowing your game down.


Damien Sturdy(Posted 2004) [#14]
before i added the entitytype commands during each loop, i could only have ~60 ships at the same speed. i dont know :/


ryan scott(Posted 2004) [#15]
boiled sweets: oops yeah you are right

cygnus: could you explain a little more, maybe example code?

because with the code above, using entitytype commands to remove entities from the collision routines, i get the same results no matter what. it should get faster and faster as i remove entities from collision checking, one would think.

maybe because the entities are not moving around, and there is some special stuff in blitz to not do unecessary collision checking. i think without knowing blitz internals its hard to figure this out.

i would love to solve this, see some kind of benefit or why bother, you know? i'm trying to find an example routine that shows some beneficial effect to using entitytype ENT,0 maybe i set up the experiment wrong.


big10p: Are you sure the slowdown isn't surface count related?

what do you mean, too many entities on the screen at once from a drawing perspective? i'm adding just bullets when i see the slowdown, and they are 8 sided. AND if i turn off collision detection on them, it runs faster.

i do see a slowdown with particles (too), which peak at about 2000 single surface meshes (maybe they are sprites, have to dig into internals). is that too many?


Boiled Sweets(Posted 2004) [#16]
If you are saying you have 2000 seperate surfaces? That sounds bad.


Jeremy Alessi(Posted 2004) [#17]
2000 is too many! Are you using CopyEntity() that should help.


Boiled Sweets(Posted 2004) [#18]
For my qoob editor, by using a little tweaking here are there I have managed to get 15,000 plus entities all with collision detection on screen at the same time running at a renderworld/updateworld of 60 FPS on my laptop (which locks the refresh to 60 FPS).

I use a intelligent cull every second. Basically I hide any entity that cannot ever be seen (ie obscured by other entities). I also use fog and hide any entities that are beyond the fog range.

For the game itself where I had originally (sharp intake of breath) 90,000 surfaces I have now managed to get it down to JUST 6 surfaces :-) I also remove all tris that cannot be seen too.

For speed improvements I would strongly suggest reducing the surface count. Then reduce the visible entity count then try and remove tris where possible. You could also try employing a shorter camera range and use camera fog...

I have found that using EntityDistance too often will kill your FPS too so you certainly don't want to call it too often. I keep an array of stuff that is visible and check that instead as its FAR quicker. I am now thinking of also adding a check to only call the cull routine is the player haas moved far enough into the fog to possible see something that is currently hidden.

I certianly would keep at this problem as my game with 15,000 entites was starting to look impossible to do with Blitz till I employed the above techniques.

Sorry for the rant but hope it helps...


Damien Sturdy(Posted 2004) [#19]
when i get home later, should time be on my side (it normally isnt these days!) i shal build some demo stuff with this. i would truly recomend keeping surface count down. My games fps gets killed when i LoadAnimMesh something huge (which needs doing for "bone" control via script).
Also, optimise camerarange, and have an array to store distance (as entittydistance may be slow, but i havent seen any loss from it yet. I will see about that later too! i am using entitydistance close on *does calculations* *chokes* 128000 a frame (enemies*enemies*2))

then use for example

...at the beginning of the loop....
Objectdistance(o)=entitydistance(player,object(o))

and later:

If objectdistance(o)>TheCameraRange then Entitytype object(o),0


You could also use camerapick command to see if an entity is on screen, but i dont have time to explain that one here.


Catch y'all later


ryan scott(Posted 2004) [#20]
i didn't really have any frame of reference when i took the particles from particle candy and used them just as they were. Those emitters were designed to look purty, all by themselves, but regularly spit out 1,000 particles.

they are separate entities, these particles, so yeah i guess they are separate surfaces too, right? i didn't write it, i don't know that they are doing anything to make it one surface. i emailed and am waiting for a reply.

this is my first 3d proggy so had no idea that 2000 particles would be bad. it doesn't sound like a lot to me when the graphic card is supposed to be able to draw millions of triangles per second, and a particle is only 2 triangles. So, why is 2000 so bad? and you are all talking about 19,000 objects. Should particle candy be rewritten to work with just 1 surface or something?

i tweaked my program and now instead of having 5 individual walls, i make one wall in 3d program that does the job of those 5. its' more complex of an object, but it's 1 surface instead of 5 now?

and i also tweaked in Candy Factory the particle emitters I am using, took out unnecessary parts and tightened it up so each one emitts about 80 particles at max per run, and also allowed for example only 2 smoke emitters on damaged enemy ships (if another needs to be created, erase one of the old ones).

the end result is i'm keeping it down to a max of 500 particles.

and, drumroll please, i'm back in the multi hundred fps range again (yay)

Based on my experiment above which demonstrates no speedup from using

If objectdistance(o)>TheCameraRange then Entitytype object(o),0

And the fact that going from 2000 to 500 particles helped so much, my current thinking is that its a waste of time to try to do zone-oriented entity checking. i would like to be proven wrong, because i am always looking for a way to tighten things up.


Jeremy Alessi(Posted 2004) [#21]
...


Boiled Sweets(Posted 2004) [#22]
Particle Candy is a single surface system. Good work for speeding your game up - looking forward to seeing a demo...


ryan scott(Posted 2004) [#23]
there has got to be some kind of 'sanity checking' built into the collision detection system. for example, if you are going to check something against a polygon, do a box check using meshwidth/height/depth before checking all polys. or something along those lines.

that would be my hope anyway. wouldn't really know unless Mark weighed in, and we rarely see that. So, until BlitzMax, where i'm assuming we can create and use other people's external libraries for collision detection, we are probably going to be guessing/doing trial and error.

too bad - we really should be able to get information on the internals, but only 1 person at blitz really knows the internals and he's obviously busy.


Damien Sturdy(Posted 2004) [#24]
there probrably is, but in supernova, and almost any indoor game, the box checking would be useless because all the entities are within the box check.


Strider Centaur(Posted 2004) [#25]
Also, this may be silly, but dont do speed tests from code run from inside the IDE, it will run alot slower and at some point you will reach a point where no amount of optimizing will make it run faster. Always test outside the IDE.

I had this happen when I was working on a 3D virtual chat client as prelude to another project that was well beyond my teams ability to complete at that time. :/