How to make a hole in an object?

I have a GeoMipTerrain and I want to make an entrance to a cave. How do I make a hole at that point? AI suggested using a texture with alpha channel, is that the way to go?

Similar question: how to make a bunker, that is a building half-buried in the ground? The floor level will be below the ground level. How do I remove the ground inside the bunker?

I was thinking of hacking the depth buffer. If the walls are always rendered over the ground, it will not be visible. However the example created by AI didn’t work. How to make Panda always render one object over another?

First of all, don’t listen to AI. It doesn’t know what it’s talking about. (Literally, in fact.)

And indeed, looking at its response… no, that wouldn’t work, I do believe.

Or at least, not alone, and somewhat depending on whether you want to actually enter the cave, or just look into it.

In short, a GeoMipTerrain is, to the best of my knowledge, just a heightmap: it essentially records a single height-value for each point, and generates a mesh to match those heights. As such, it doesn’t allow for things like overhangs–or caves.

Now, you could generate a hole in your terrain via a few different approaches–but that still wouldn’t get you an actual cave in there: you’d just see emptiness behind the terrain mesh.

One way or another, you would want to produce geometry for the cave interior, likely without using a GeoMipTerrain (e.g. by modelling it in a program like Blender).

(Theoretically you probably could make your cave via… I’d guess two GeomMipTerrains. But that seems likely to be finicky to get right.)

Simply put, you would alter your heightmap to account for the space occupied by the building, I believe.

Here I’d suggest taking a look at the manual page on how to control render order, as well as this thread regarding a similar question.

It’s also possible that the stencil buffer might be of use, although I don’t have much experience of that myself, and so don’t have much to offer regarding it.

I will try to do it through render to texture. I’ll draw the cave interior, make one polygon representing its entry and put it on the terrain where it should be.

This doesn’t solve the bunker question though. If the cave is fully underground it will work, but if the terrain level is in the middle of the room, it will still be drawn.

1 Like

That should work, I believe–although you would end up with a polygonal “entrance”. This could be covered up with a bit of custom geometry, however, I daresay.

You could also potentially use the stencil buffer, I think–or the trick that I linked to in my second link above.

As I said: design your heightmap to account for the bunker: leave a flat space where you intend the bunker to be.

After all, you’re presumably either working with a heighmap image that’s produced outside of your code–in which case you can simply edit it–or you’re generating a heightmap in your code–in which case you can potentially modify it in code.

Now, if you want to account for the bunker being placed by the player in an arbitrary position, then things get a little more complicated.

You could perhaps again use one of the above-mentioned tricks to visually “cut out” a piece of the terrain. Or you could apply a shader that allows you to modify vertices within a specified region, maybe. Or, if you’re already using render-to-texture, you could use that on the door of the bunker.

My terrain is enormous and I’m using 513 size square, scaled up horizontally. A single polygon in the terrain is of the order of several meters in game scale. I need a bunker that is much finer, where smallest details are 10cm in game scale maybe, and sometimes it needs to be rotated at angle relative to the terrain grid. Editing the heightmap won’t do, I looks like a punch hole where someone put the bunker in. I could make the soil touching the bunker walls as part of the model itself, but it will be too much work.

I’m thinking I will do the same render to texture trick with a bunker. When the player is in the bunker the terrain visibility is disabled, it is rendered to a buffer instead and the texture is painted at windows and doors, so the player can look outside.

I must say I get weird effects when I play with rendering order. I will check out the stencil buffer thing. Is it possible to manually alter the depth bufer? Not merely disable it, but write own values.

1 Like

Yup, it can do some odd things at times!

Which can on occasion be useful…

I don’t think so, but I stand to be corrected.

However, depending on your requirements, you could perhaps just have some geometry that’s set to render only to the depth buffer, and maybe that has depth-testing disabled–or maybe that has a significant depth-bias applied.

The depth buffer approach is not a bad one. What you would need to do is render the entrance as a piece of geometry, possibly slightly higher than the terrain (or with a depth offset effect added), but disable color write on it, so that it only affects the depth buffer.

The tricky part is making sure that you don’t render the terrain at that spot but do render the bunker interior. Here’s one way to accomplish that:

  1. Render the bunker.
  2. Render the invisible entrance (make it invisible to the color buffer with a ColorWriteAttrib).
  3. Render the terrain. Render it with a DepthTestAttrib such such that it won’t re-render the terrain if there is already something in the depth buffer at the same depth. Or apply a depth offset to the invisible entrance.

You can accomplish this using cull bins. For example. the bunker could be rendered with setBin('background', 1) and the entrance with setBin('background', 2).

The disadvantage is that the bunker interior is always rendered, even if you’re not looking down the entrance. If you are bottlenecked on pixel fill, this may be a performance issue. If this becomes an issue, you could try and see if you can render the terrain first, then cut out the tunnel entrance in the depth buffer, by rendering it with a very low depth value, but with depth testing disabled. (The terrain will still be rendered at the tunnel entrance, but the bunker will be rendered over it.) Then you render the bunker.

Stencil attributes give you a little bit more control, but they are more complicated to set up.

Yes, you can have a shader that writes to gl_FragDepth.

1 Like

Ah, of course–I stand gladly corrected! :slight_smile:

Pyvista provides boolean operations on mesh. It may not be real-time.

The surest option is to change the GeoMipTerrain class so that it has a hole map. The principle is very simple: if pixels are marked, then vertices are not created in this place.

1 Like

It occurs to me that one could also write a fragment shader that uses a map, or a list of locations, to generate cutouts in the rendering.

However, there are nuances when choosing shaders as an implementation. The issue of collisions remains unclear.

True.

But even if taking the approach of modifying GeomMipTerrain, I suspect that supporting collision would call for more than just preventing certain polygons from being generated.

I suspect that, internally, it accesses the heightmap for vertical positions, rather than the polygons.

Further, as soon as the player got past the removed polygons, I would expect GeomMipTerrain-based collision to start moving them up to terrain-height.

So either way, some extra thought seems likely to be called for when dealing with collisions…

(Which might be as simple as "disable GeoMipTerrain collision when the player enters a “hole”.)

I meant it. That is, a collision system, not physics.

terrain = GeoMipTerrain ("terrain")
geoms = terrain.get_root().find_al_matches("+GeomNode")
1 Like

Oh, sorry–I think that I somehow missed your mention of collision in your previous post! Sorry about that! ^^;