Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to handle terrain holes?
#1
Hi, I'm wondering if there is a way to get obi rope to work with terrain holes. I can't find any mention of it except one other forum post that alluded to support being planned for 2022. If there is still no support, is there any kind of workaround besides disabling the entire obi collider on the terrain?
Reply
#2
(04-09-2024, 04:55 PM)btduser Wrote: Hi, I'm wondering if there is a way to get obi rope to work with terrain holes. I can't find any mention of it except one other forum post that alluded to support being planned for 2022. If there is still no support, is there any kind of workaround besides disabling the entire obi collider on the terrain?

Hi,

Terrain holes are supported since v6.5.1 (see changelog). Let me know if you run into any related issues.

kind regards,
Reply
#3
(04-09-2024, 07:38 PM)josemendez Wrote: Hi,

Terrain holes are supported since v6.5.1 (see changelog). Let me know if you run into any related issues.

kind regards,


Hmm, I'm on 7.0.2 and it doesn't seem to work for me. I thought the issue was related to me changing the hole data at runtime but even if I paint a hole in the terrain before starting the scene, the rope will not pass through. Is there anything particular I need to do? I just have a terrain with an obi collider - am I missing something? See the attached image for reference:

EDIT: Ok I sort of figured it out - in my test scene, I had the heightmap flattened down to zero. I'm looking at the logic in ObiHeightFieldContainer.cs where it reads the hole data but I'm not exactly sure how it explains what I was seeing before. I can work around the issue in practice, but the "invisible floor" at terrain height 0 is unexpected - not sure if it would be considered a bug.


Attached Files Thumbnail(s)
   
Reply
#4
(04-09-2024, 08:34 PM)btduser Wrote: Hmm, I'm on 7.0.2 and it doesn't seem to work for me. I thought the issue was related to me changing the hole data at runtime but even if I paint a hole in the terrain before starting the scene, the rope will not pass through. Is there anything particular I need to do? I just have a terrain with an obi collider - am I missing something? See the attached image for reference:

EDIT: Ok I sort of figured it out - in my test scene, I had the heightmap flattened down to zero. I'm looking at the logic in ObiHeightFieldContainer.cs where it reads the hole data but I'm not exactly sure how it explains what I was seeing before. I can work around the issue in practice, but the "invisible floor" at terrain height 0 is unexpected - not sure if it would be considered a bug.

Hi!

Terrain holes are encoded as the sign of the heightmap values: positive height means solid terrain, negative height means a hole. According to IEEE floating point standard, -0 is equal to 0, which means a hole at height zero is actually considered solid terrain (because -0 is not < 0). The alternative in this case would be to have -0 be less than 0, which would cause all terrain at height zero to be a hole - probably a worse option.

It’s not usual to have completely flat terrain with zero height, maybe in this case a MeshCollider would be a better fit? If you do need flat terrain, increasing its height uniformly to a non-zero value would be a valid workaround.

Let me know if you need further help,

Kind regards
Reply
#5
(04-09-2024, 10:35 PM)josemendez Wrote: Hi!

Terrain holes are encoded as the sign of the heightmap values: positive height means solid terrain, negative height means a hole. According to IEEE floating point standard, -0 is equal to 0, which means a hole at height zero is actually considered solid terrain (because -0 is not < 0). The alternative in this case would be to have -0 be less than 0, which would cause all terrain at height zero to be a hole - probably a worse option.

It’s not usual to have completely flat terrain with zero height, maybe in this case a MeshCollider would be a better fit? If you do need flat terrain, increasing its height uniformly to a non-zero value would be a valid workaround.

Let me know if you need further help,

Kind regards

This is just a side effect of my test scene, so it's not really an issue as my terrain would normally be elevated. That being said, I was fiddling around noticed that the current logic of "GetOrCreateHeightField" assigns the the height value multiplied by -1 or 1 depending on if there is solid terrain or holes, respectively. This means that at height zero it results in 0 * -1 = -0 which is not <0 as you point out. I changed the logic to instead just assign the height value if there is solid terrain, or a constant -1 if there is a hole, and it seems to behave as expected. Is this a viable solution or are there any negative implications of this I'm not aware of?
Reply
#6
(04-09-2024, 11:04 PM)btduser Wrote: This means that at height zero it results in 0 * -1 = -0 which is not <0 as you point out. I changed the logic to instead just assign the height value if there is solid terrain, or a constant -1 if there is a hole, and it seems to behave as expected. Is this a viable solution or are there any negative implications of this I'm not aware of?

Hi,

This will break collision detection in all cases, except when all surrounding neighbors of the hole (as well as the hole itself) have a height of 1. The reason is the terrain's collision geometry is built as quads, whose vertices' heights are read from the height map. So even if a quad if marked as a hole (its first sample having a negative height) we still need the actual height value for its neighbor quads to be correct, that's why we take the absolute value of the heights for building the quads after testing for holes:

Code:
if (h1 < 0) continue; // this would be a hole, skip quad
h1 = math.abs(h1);
h2 = math.abs(h2);
h3 = math.abs(h3);
h4 = math.abs(h4);

Let's say this happens on flat terrain, all samples having a height of 5. This quad's h1 (bottom left) sample is also its bottom left neighbor's top right sample. If h1 is -1 the current quad will be ignored, however the bottom left neighbor will have its top right corner incorrectly slanted down towards 1, yielding incorrect collision geometry around the hole. This is a crude diagram of the problem, "H" would be the current quad which is a hole, and "T" would be its bottom left neighbor which is solid terrain:

Code:
Incorrect:
       5-----5
       |  H  |   
5-----1-----5
|  T  |     
5-----5

Correct:
       5-----5
       |  H  |   
5-----5-----5
|  T  |     
5-----5


kind regards,
Reply
#7
(05-09-2024, 07:53 AM)josemendez Wrote: Hi,

This will break collision detection in all cases, except when all surrounding neighbors of the hole (as well as the hole itself) have a height of 1. The reason is the terrain's collision geometry is built as quads, whose vertices' heights are read from the height map. So even if a quad if marked as a hole (its first sample having a negative height) we still need the actual height value for its neighbor quads to be correct, that's why we take the absolute value of the heights for building the quads after testing for holes:

Code:
if (h1 < 0) continue; // this would be a hole, skip quad
h1 = math.abs(h1);
h2 = math.abs(h2);
h3 = math.abs(h3);
h4 = math.abs(h4);

Let's say this happens on flat terrain, all samples having a height of 5. This quad's h1 (bottom left) sample is also its bottom left neighbor's top right sample. If h1 is -1 the current quad will be ignored, however the bottom left neighbor will have its top right corner incorrectly slanted down towards 1, yielding incorrect collision geometry around the hole. This is a crude diagram of the problem, "H" would be the current quad which is a hole, and "T" would be its bottom left neighbor which is solid terrain:

Code:
Incorrect:
       5-----5
       |  H  |   
5-----1-----5
|  T  |     
5-----5

Correct:
       5-----5
       |  H  |   
5-----5-----5
|  T  |     
5-----5


kind regards,

Got it, thanks for the explanation. So considering that the issue is really only when the height is exactly zero, would it be reasonable to do the following?

Code:
if (!isHole){
    value = height;
}
else{
    value = (height == 0) ? -1e-7f : -height);
}
Reply
#8
(05-09-2024, 02:28 PM)btduser Wrote: Got it, thanks for the explanation. So considering that the issue is really only when the height is exactly zero, would it be reasonable to do the following?

Code:
if (!isHole){
    value = height;
}
else{
    value = (height == 0) ? -1e-7f : -height);
}

Hi,

That should be fine, I've tested it and seems to work fine. Only issue is a very small slope in the terrain surrounding the hole which causes particles to slowly roll away from the hole when using a completely frictionless material and no sleep threshold, but that's rather unusual. For most practical purposes the terrain remains flat.

Will consider adding this modification to the asset. Thanks!

kind regards
Reply