-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Hi,
first of all, thanks for maintaining this editor, it’s extremely useful for working with AutoDrive in FS25.
Regarding the known issue #6, point 4 (“Nodes floating above ground or below ground – heightmap data not at the same resolution as the terrain map”):
I noticed that node heights in the editor seem to be quantized in roughly 1 m steps (maybe depending on map height range), which suggests that the effective height resolution might be reduced to about 256 levels, even though the heightmap itself has higher precision.
While looking through the code, I found a potential cause in getYValueFromHeightMap(double worldX, double worldZ).
Currently it looks like this (shortened):
Color color = new Color(heightMapImage.getRGB((int)x, (int)y));
BigDecimal bd = new BigDecimal(Double.toString(
(float)((color.getRed()<<8) + color.getGreen()) / 256
));
bd = bd.setScale(3, RoundingMode.HALF_UP);
return bd.doubleValue() / heightMapScale;
This reconstructs a 16‑bit value from red/green, but then divides by 256, which effectively limits the result to 256 steps before scaling with heightMapScale. That would match the ~1m step size seen in practice.
A possible alternative would be to use the full 16‑bit range and, when available, the 16‑bit heightmap data (heightMapPixelData), for example:
public static double getYValueFromHeightMap(double worldX, double worldZ) {
if (heightMapImage != null) {
double x, y;
double scaleX = (double) pdaImage.getWidth() / (double) heightMapImage.getWidth();
double scaleY = (double) pdaImage.getHeight() / (double) heightMapImage.getHeight();
x = ((double)heightMapImage.getWidth() / 2)
+ (int) Math.floor((worldX / mapScale) / scaleX);
y = ((double)heightMapImage.getHeight() / 2)
+ (int) Math.floor((worldZ / mapScale) / scaleY);
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > heightMapImage.getWidth() - 1) x = heightMapImage.getWidth() - 1;
if (y > heightMapImage.getHeight() - 1) y = heightMapImage.getHeight() - 1;
if (heightmapType == HeightmapFormat.USHORT_GREY && heightMapPixelData != null) {
// 16-Bit
int pixelIndex = (int)(y * heightMapImage16bit.getWidth() + x);
int raw = heightMapPixelData[pixelIndex] & 0xFFFF; // 0..65535
double normalized = raw / 65535.0; // 0..1
return normalized * heightMapScale; // scaled height
} else {
// 8-Bit
Color color = new Color(heightMapImage.getRGB((int)x, (int)y));
float hValue = ((color.getRed() << 8) + color.getGreen()) / 256.0f;
return hValue / heightMapScale;
}
}
return -1;
}
In short: instead of dividing by 256, this uses the full 0–65535 range, normalizes to 0–1, and then scales with heightMapScale. In theory this should avoid the ~1 m quantization steps and bring node heights to the actual terrain surface.