Cutting holes in the terrain

Does current Terrain component support cutting holes in it? Say for making cave entrance. API does not suggest anything obvious, but maybe there is some smart trick to achieve this?

Graphics is simple.
Physics is average.
Navigation etc - I don’t know.

1 Like

FYI: How to make Bullet work with holes in terrain:

  1. Inherit from btHeightfieldTerrainShape
  2. Override processAllTriangles
  3. Somehow drop triangles: use mask array or sentinel height. I’ve just copy-pasted content of processAllTriangles.
  4. Use your own height field shape.
1 Like

Maybe you could use several terrains, leaving a gap between them?

I thought of that. It would likely be easiest approach, but then these two terrains would not be stitched together and lesser problem is gaps would be allowed only at terrain boundaries.

@Eugene thanks for pointers. Any idea if sentinel height value could be used with heightmap itself? I tried naive thing (discarding vertices here) and it ended up being a royal mess because clearly i have no idea what im doing.

Uhm, looking at terrain just these days…
I found, for instance, BlenderGis, which allows you to get multimapping; one could use heightmap as usual, and slope and aspect to get direction of movement for characters for recast/detour I think… or for intentional movement inside a cave…
Anyway terrain basically is a flat plane and doing st like cave sounds like voxels… the normal solution is using point of interests and teleporting somewhere else…
But of course this is not continuos movement like probably you’re looking for…

It’s hard to combine stable geometry discarding, sentinel heights and geomipmapping.
Even PhysX use material index instead of height to mask cells as gaps.
I recommend you to hold the idea about sentinel heights and revise it if it become important.

Another approach is to just use something other than heightmap terrain, like regular 3D models.
You can also mix it up with terrain, leaving a low height hole where you want to place your 3D model cave, so the terrain is below the cave.

a workaround with terrain is to have some sort of transition between the cave and the terrain, like a door.

1 Like

@Enhex my primary reason why i looked at terrain component is that it handles stitching and all that. Using 3D model would probably be akin to making own terrain system.

On a closer look at terrain component i noticed these:

void SetNorthNeighbor(Terrain* north);
void SetSouthNeighbor(Terrain* south);
void SetWestNeighbor(Terrain* west);
void SetEastNeighbor(Terrain* east);

Does terrain component handle stitching of multiple Terrain components together? Not just TerrainPatches within Terrain? If so that brings me to your original suggestion.

Take a following picture as example:
Each rectangle represents Terrain component. Each green border represents neighbour relationship being set. Red border represents no neighbour relationship.

Am i right to think that in this setup terrain would not be stitched together at the red border? If so then adjacent tiles could have different height (which would be a very steep cliff if stitched together) and create a hole when no stitching is applied to that border.

AFAIK, terrain wouldn’t be stiched unless you stich it manually. I mean, it depends on values in heightmap.
But I find this approach very limited to be useful.

What does SetXXNeighbor(Terrain*) do then?

Ensures that geomipmapping won’t make any unexpected holes

Excuse my ignorance, but that sounds very much like stitching up terrains. Could you please elaborate?

Separate terrains don’t have any shared data, so they couldn’t stich themselves without explicit user intention.

Neigbors are used to ensure that terrain patches on the edges has valid topology and there won’t be any gap caused by mismatching LODs.

You don’t have to handle stitching with a 3D model, just let it intersect with the terrain and you won’t have gaps.

I am experimenting with setting up multiple terrains. Docs are sparse on this topic and there seem to be hidden requirements for making entire thing work.

What is supposed to be a heightmap format? I noticed that terrain skips 1 pixel at the edges of heightmap, thus for creating 16x16 units terrain i need to use 17x17 heigthmap. Whats the purpose of skipped edge?

How exactly am i supposed to use SetXXXNeighbor()? My test code:

        auto terrain = scene_->CreateChild()->CreateComponent<Terrain>();
        terrain->SetSpacing({1, 1.f / 255.f, 1.f});

        auto terrain2 = scene_->CreateChild()->CreateComponent<Terrain>();
        terrain2->SetSpacing({1, 1.f / 255.f, 1.f});
        terrain2->GetNode()->SetPosition({16, 0, 0});

And a heightmap. I scaled it up by 800% for demo purposes. Actual image used by code is 17x17.

Test code aligns terrain tiles like so:

On the right edge of terrain i expected to get seamless transition between terrains, however it looks like this:

Notice crack between points painted in white on heightmap. Also neighbour terrains are not taken into account when calculating tiles.

So whats the right way to use terrain in this case?

Do you mean 16x16 quads?

If you want two terrains be seamlessly connected, you should set them as neighbors for each other.

I mean entire terrain being 16x16 quad.

Edit: i suppose 1 pixel in heightmap means one vertex. In order to get 1x1 tile terrain i would need 2x2 heightmap, because one quad needs 4 vertices at the corners. So 16x16 terrain needx 17x17 pixels. Right?

Like so?


Because it produces exactly same visual result.

I think so.

Well, that’s strange. Maybe terrains have different scale?
They must have connected geometry. Could you check the grid?

Do you mean seeing debug geometry? Terrain does not have built in debug info rendering on purpose. I added it myself bit it isnt exactly revealing.

They are of exactly same scale. Snippet i pasted previously - its pretty much all the code setting up scene. Other stuff is just setting up viewport, camera and creating scene object. You can take a look at entire thing:

I just noticed that white pixel on the right was tiny bit darker than white pixel on the left. That caused height mismatch. But there is still normal issue which makes lighting look weird. Is terrain supposed to take into account neighbouring terrains when calculating normals?