Point visibility [SOLVED]

Hi all!

I want to implement the effect of bullets leaving marks on walls when they hit them. To do this I’ll save every position (in world space) of every bullet that has collided with walls.

Later on, I just want to get the positions that are within the camera’s frustum, so that I can draw a textured quad in those positions. I’ve read about base.cam.isInView(point), but I was wondering if there’s a faster way to get the positions that are within the frustum.

Maybe by directly using or attaching info into the scenegraph. I mean, is there a way I can get the nodepaths that are being viewed by the camera? Furthermore is there a way I can get only custom nodepaths (the ones from my bullets marks) that are being viewed by the camera?

Any ideas?

Thank you very much,

Not easily. You could perhaps do it if you were willing to write some C++ code, and subclass PandaNode. There are some other tricks you could do at the Python level, but none of them will be faster than querying isInView().

David

Sounds like you’re asking for some kind of generic clipper and projector. I’ve been toying with this idea myself, but I haven’t had time to come up with anything.

My idea was to prototype something in Python for arbitrary decals, and then later re-write it as a C++ class. (A specialized PandaNode sounds about right.) However, in my game, decals are not played in realtime, so the project-and-clip phase occurs before the level renders. You’d need something that would be able to run at realtime, hence sticking to C++ code.

The concepts are pretty simple, it just isn’t going to be fast enough at a Python level.

Thanks for the answer!

So what is the recommended approach without having to enter C++ realms? (Sorry I wrote this line before reading FenrirWolf reply)

My game’s gameplay will be based on leaving marks around the world. So for instance, I will shoot a weapon and when a bullet collides with a wall (or any geometry for that matter), I will need to mark the wall in that position, meaning that a textured quad will need to appear on that position each time it’s within the camera’s frustum.

Thanks!

I’ll be more precise:

The effect I’m trying to accomplish is that of leaving marks on the precise
locations where geometry has been hit by bullets. The wall example is the
simplest I can imagine of, so I’ll stick with it.

Imagine a wall, and the player has a weapon. When he shoots, and the bullet collides with the wall, a mark should be left on the exact location of the collision.

A teacher of mine suggested saving all the positions in world space of the
locations where bullets have collided with geometry. Later on, each time the camera is moved, I will need to just take into consideration the positions within the frustum, and generate textured quads on those positions on the fly.

Later on I will setup a camera that will only see this quads, and will render
the quads to an auxiliary buffer. I want to do this so that I can expose a
texture (mask) to a shader, for further processing, that will only have the
quads drawn in it.

I need to know what do you think of this approach, or if you can imagine
another way in which this will be more efficient.

hmm, why do you need to check that? that’s done by the renderer automatically. you may want to segment the world into chunks, and attach the bullethole at the chunks, calling flattenstrong on them. that should optimize the rendering prozess if you have a lot of bulletholes.

# sample code

segmentSize = 10 # make this so the world is split up into maybe 100 chunks, do some fps testing with different segmentSizes
bulletNPs = dict()
for x in xrange(worldSizeX%segmentSize):
  for y in xrange(worldSizeY%segmentSize):
    for z in xrange(worldSizeZ%segmentSize):
      bulletNPs[(x,y,z)] = render.attachNewNode('%i%i%i-bulletNP' %(x,y,z))

...

bulletPos = ... # holds the position of the collision
bulletMdl = loader.loadModel('bulletCube.egg')
segmentId = (
    bulletPos[0]%segementSize, 
    bulletPos[1]%segementSize, 
    bulletPos[2]%segementSize )
bulletMdl.reparentTo( bulletNPs[segmentId] )
bulletMdl.flattenStrong()

what do others think of this concept?

edit: maybe subtract some of the ray’s direction from the collision spot, so the quad is 0.1 in front of the wall?

If your walls are perfectly flat, you can just create a quad at the collision point, facing in the same direction as the collision normal. That could be done in Python, using just CardMaker (to generate a quad).

There’s no need to do any kind of world partitioning or keep track of what quads are within the view frustum; If they’re ordinary PandaNodes, Panda3d will do this for you. Just create the quad at collision time, position it, and then forget about it.

Then, when you need to generate the mask, just use a camera mask to make those quads render to your auxiliary buffer.

However, this method breaks down if the geometry you want to render decals against is not perfectly flat.

i dont completely agree with you FenrirWolf, but it depends on the amount of individual nodes that are on screen. if you have several hundert or thousands of on screen a segmentation and flattening is required to keep the framerate acceptable. also a plane that is created at the exact same spot as the collision aligned to the normal will have z-fighting problems. if you render it to a separate buffer you have to render the quads as well as the level geometry, the level in a different color (black) without textures, so you can combine the results without seeing quads trough walls.

correct me if i’m wrong, but the i’ve done some works that required these methods i describe here.

Thanks for your answers!

I’ve been playing around a bit, following your advice, and what I did is to directly attach my quads to the node of the model where a bullet collided. In that way, Panda3D will take care of the quad’s visibility.

My scenegraph looks like this:

render
–modelsNode - all my models are added to this mode
----wall - a wall
------quads - the places where bullets have collided with the wall, and quads must be created

Now I need the quads to only be visible to a second camera, so that I can use what the camera sees, as a mask in a fragment shader. I hide my quads from the main camera with this line quads.hide(BitMask32.bit(0)), but I was wondering how can I make those same quads only visible in the second camera. I mean, all models, except quads, should be excluded from the second camera.

I tried something like this:

modelsNode.hide(BitMask32.bit(1))
quads.show(BitMask32.bit(1))

That is, I hide all models from the second camera, but I “override” that setting for quads. This doesn’t seem to work, and as the manual says, “Any object that is parented to the object that is hidden will also be hidden.”, so I was wondering if it is possible to override “hide”, for a node’s children.

By trying to do this, I’m probably making terrible use of the scene graph, so please excuse my ignorance.

Any suggestions?

Thanks,

Nope, there is exactly a feature for this in the scene graph. You just need to do:

modelsNode.hide(BitMask32.bit(1))
quads.showThrough(BitMask32.bit(1))

“showThrough” is specifically designed to override a parent’s “hide”.

David

Thanks! That works beautifully!