Possible to detect texture collision?

Blitz3D Forums/Blitz3D Programming/Possible to detect texture collision?

Jeroen(Posted 2003) [#1]
Hi!

I was wondering: I'm trying to make a footstep system. E.g: grass, snow, brick, etc. The problem is that the level is just one big mesh. It would be great if Blitz could recognise which texture I'm colliding with...perhaps technically impossible :P
What would be a good approach?

Thank you.


sswift(Posted 2003) [#2]
Each texture needs to be on a different surface. So you need to find out which surface you collided with. CollisionSurface() returns the pointer to said surface.

Hopefully this pointer will be the same as the pointer that you get when you try to get a surface handle to manipulate it. If so, then you can store which texture is applied to specific surfaces in the mesh.

Ie, when you load the mesh, surface 1 should always be the same surface. You can get the pointer to this surface, and then compare that pointer with the pointer returned by collisionsurface. As surface 1 always gets the same material, you'll know which material is applied to surface 1. You'll have to manually store this of course. There MIGHT be a way to get the texture filename applied to that surface but I can't help you there.


skidracer(Posted 2003) [#3]
Version 1.85 of Blitz3D features the useful commands:

brush=GetSurfaceBrush( surface )
texture=GetBrushTexture( brush[,index] )
name$=TextureName$( texture )

Remember to use FreeBrush and FreeTexture after you have finished using the results to avoid memory leaks.


Rob(Posted 2003) [#4]
When you do

texture=GetBrushTexture( brush[,index] )

is this an actual pointer to the live texture or a copy?


Beaker(Posted 2003) [#5]
A copy.


skidracer(Posted 2003) [#6]
It's a copy of the handle not the texture, the reference / handle count of the actual texture is incremented hence the need for the Free.


jfk EO-11110(Posted 2003) [#7]
HOwever, if you track it down to the texture filename you can easily decide what sound should be used. SSwift was wrong when he said the order of surfeces loads always the same (you said that, did you?), because (no idea why) the order is randomly choosen, everytime diffrent, so yo never know "surface number 1 is grass.jpg"...

Using skidracers tipp you can assign a sound to each surface, you should do this one time right after loading and not multiple times in the game loop.


semar(Posted 2003) [#8]
@Jeroen,
another way could be the use of Droplet (or another way) to place fixed pivot on the mesh. Each pivot will have a circle assigned, which determines the terrain composition.

Depending on the distance between the main character and each pivot, you can decide which sfx to use.

Sergio.


Jeroen(Posted 2003) [#9]
Hi,

Hmmmm interesting point of debate :)
The game has much height difference as well, so I think the pivot system as Semar suggested is not precise enough.

I hoped that it worked the same as alpha channels: Blitz basic looks for filename suffixes like alpha_blah.png...

I'll try Sswift's suggestion, but the first tries were unsuccesful


(tu) sinu(Posted 2003) [#10]
@jeroen i've been doing this too, using similar methods to above, where all ground textures have a _grass, _wood etc prefix and then i parse the surface the player is on to decide which sound to play.
Had problems with it though and haven't thought much of it till your post.

"HOwever, if you track it down to the texture filename you can easily decide what sound should be used. SSwift was wrong when he said the order of surfeces loads always the same (you said that, did you?), because (no idea why) the order is randomly choosen, everytime diffrent, so yo never know "surface number 1 is grass.jpg"... "

finally, at least i now know they're chosen randomly, thought it was a bug or was doing something wrong. Mayb i can get my footsteps working properly.


SabataRH(Posted 2003) [#11]
finally, at least i now know they're chosen randomly, thought it was a bug or was doing something wrong. Mayb i can get my footsteps working properly.



Yup they are choosen randomly, you may get the same order 10 times in a row then all of sudden poof! they are diffrent.. This is a MAJOR thorn in the side as many things could be possible if the order was not randomly tossed about.. I suppose Mark has his reasonings behind this.. But none this less - its still a major 'holdback'.


sswift(Posted 2003) [#12]
JFK:
HOwever, if you track it down to the texture filename you can easily decide what sound should be used. SSwift was wrong when he said the order of surfeces loads always the same (you said that, did you?)


I said "SHOULD" be the same. Not is the same. :-)

I don't know how in the hell Mark managed to make it random without actually TRYING to do so. It's completely unfathomable to me how that could occur.


Okay so say you can't figure out the texture on a particular surface for whatever reason.

Another thing you could do is make a second copy of the mesh, and set the vertex colors and use those to determine what the texture at that location is.

But this is a big pain to do, and I think you can get the texture thing to work with these commands that the others described:

brush=GetSurfaceBrush( surface )
texture=GetBrushTexture( brush[,index] )
name$=TextureName$( texture )

Just remember as they said to free the texture and brush after you get the texture name each time.

But don't do what I said, they said the surfaces will be random, so you can't just rely on the surface number being the same, or the polygon having the same number and what not. You NEED to get the texture name.

So do this:


SURFACE_Level = CollisionSurface(MESH_Level, Collision_Index)
BRUSH_Level = GetSurfaceBrush(SURFACE_Level)
TEX_Level = GetBrushTexture(BRUSH_Level)

TextureName$ = TextureName$(TEX_Level)

FreeBrush(BRUSH_Level)
FreeTexture(TEX_Level)


And TextureName$ will now contain the filename of the texture that the entity that collided with the level, which has the COllision_Index specified. (In other words, it was the first, or tenth entity to be detected colliding with the level. You have to find out the collision index when the collision is determined)

You can also specify a specific texture layer on GetBrushTexture if you have textures your level with two or more textures at once. If you haven't, or the texture you want is the first texture applied to the level then you need not worry about that.


jfk EO-11110(Posted 2003) [#13]
ehm - I think it is faster when you parse trough all surfaces and assign a sound vector to an array before the game starts, right after loading. So finally you only have to check the collided Surface and find its sound in a small array.

something like:
snd_grass=loadsound("grassstep.wav")
snd_street=loadsound("streetstep.wav")
snd_water=loadsound("waterstep.wav")
snd_wood=loadsound("woodstep.wav")

global numsurfs=countsurfaces(level)
dim footsound(numsurfs,1)
for i=1 to numsurfs
  footsound(i,0)=getsurface(level,i)
  footsound(i,1)=snd_street ; default

  brush = GetSurfaceBrush(getsurface(level,i)) 
  tex = GetBrushTexture(brush) 
  name$ = TextureName$(tex) 
  FreeBrush(brush) 
  FreeTexture(tex) 

  ; here you need to insert a fuction call that will strip 
  ; the path and leave the filename without path (because 
  ; TextureName$ delivers the complete path)

  select name$
    case "grass.jpg"
      footsound(i,1)=snd_grass
    case "wood.jpg"
      footsound(i,1)=snd_wood
    case "water.jpg"
      footsound(i,1)=snd_water
  end select
next

;...

while game
  snd_to_play=snd_street ; default
  collsurf = CollisionSurface(Level,Collision_Index)
  for i=1 to numsurfs
    if collsurf=footsound(i,0)
      snd_to_play=footsound(i,1)
      exit()
    endif
  next
  playsound snd_to_play
  ;...


of course you might use a Type Structure as well.


sswift(Posted 2003) [#14]
Asuuming that will even work, (cause blitz pointers are funny) it is a silly optimization.

You won't even save a fraction of a second over comparing a few texture names per frame.

In this case, I say go with the simplest most straightforward method.


jfk EO-11110(Posted 2003) [#15]
try this:

a$=""
for i=0 to 1000000
a$=a$+" "
next

you can easily go for a cup of coffee meanwhile...


sswift(Posted 2003) [#16]
A$ = A$ + " "
is not the same as
if A$ = B$

You're allocating a million bytes of ram there, a few bytes at a time.

Try this:

a$=""
For i=0 To 1000000
If a$="blah.bmp" Then Print "Blah"
Next

It's virtually instantaneous. Or close enough anyhow. You're not gonna compare the string a million times a frame. You'll be lucky if you compare it against 100 strings a frame.


jfk EO-11110(Posted 2003) [#17]
Yes, of course. But I think you CAN use Surface Handles since they will not change after Loading unless you mess around with them.


sswift(Posted 2003) [#18]
If you can get the handle to a texture that a brush uses and it won't be the same handle you got when you loaded the texture, what makes you think that the handle you get from the collision surface function will be the same as the handle you get when enumarating the surfaces in the object initially?

Besides, it's easier to just use the method I outlined and store the texture names than to make a bunch of arrays and surface indexing code.


Beaker(Posted 2003) [#19]
Uuh! they will be the same surface IDs. Trust me. :)


Mustang(Posted 2003) [#20]
How about doing it like this (My planned way of doing it):

-get/pick the surface
-get/pick the UV pos
-check "mask" texture UV value
-play sound

Mask texture would be basically a copy of your texture map, but instead of textures it has only plain color areas - and in can/will be much smaller of course since it does not change the way how UV values work. These colored areas would define what sound you should play... nice thing is that if you have a texture that has many materials like wood, metal or glass you can still play the approriate sound... for example if you have a floor texture that looks like metal plates supported by wooden frame, then you would get mostly "metal" sounds, but occasionally "wood" sound when you step on the wooden frame. Picked color value can corrspond directly to the sound array value for speeed "optimization".

Nice thing here is that same method will work also for shooting/hit sounds... :)

Above assuming that you do your texturing "right" ie pack a lot of smaller textures to a bigger one.


Jeroen(Posted 2003) [#21]
hmmmm seems like hard solutions :(
I wonder how other programmers which succesfully implemented this managed to handle this.


jfk EO-11110(Posted 2003) [#22]
sswift - nevertheless - the method that will track it down each time an information is required is shurely much slower, and the reason why is:

brush=GetSurfaceBrush( surface )
texture=GetBrushTexture( brush[,index] )
name$=TextureName$( texture )

will create a copy of the texture and of the brush.

I have approx. 400 Surfaces in a complete Level including Items and loaded Interior Meshes. Now should I create 400 Textures each loop?

I doupt this would be usable. Instead I quickly compare 400 Ints in no time.

@Mustang - seems to be a pretty flexible solution, but I agree wuth Jeroen as well, seems to be a lot of work.

@Jeroen some time ago, when there were no Texture-trackdown Commands like the mentioned ones I wrote a silly brute-force comparing function for wmaass. It created a copy of the mesh and textured each surface manually with all of the Textures which were found by parsing the file. It created an additional Quad for every Surface in front of the camera while the Mesh itself was somewhere off the plot. It rendered then both, first the original and then the copy. The copy was rendered with each possible texture applied until the checksums of both rendered images matched.

As I said: pretty complicated and pretty silly - at least it worked.


SabataRH(Posted 2003) [#23]
I wonder how other programmers which succesfully implemented this managed to handle this.


They spend $1000's and $1000's on a commerical, feature enriched graphics engine.


Beaker(Posted 2003) [#24]
I'm with jfk on this. It works for me as well.


simonh(Posted 2003) [#25]
I use the new V1.85 commands (GetBrush etc) to assign different amounts of friction to different textures in Super Hamster Ball. Before starting the level, I parse all the texture names that are returned by GetBrushTexture, and assign the current surface handle they are attached to, to a friction value. Then when playing, I check the current collision surface against the one stored earlier, and apply the friction value. Works every time.