Closed blitzcoder closed 1 year ago
The height, in LoadTerrain, is determined by the brightness of the pixel in the map picture, that can range from 0 to 255. Internally, the value is stored in the "height" array, that is a float and can range from 0 to 1. When the terrain is rendered, that value is multiplied by vsize, that by default is set to 30, and then to the scale factor. The variable vsize is set inside the function CreateTerrain, so if you change the line:
terr->vsize=30;
to
terr->vsize=1;
You should achieve the same behavior of Blitz3D. Let me know if it works (I wouldn't consider this issue a bug, only a difference from Blitz3D)
Yes, that seem to achieve the same behavior with vsize to 1, but this actually points to and linked with TerrainY and Scaled Terrains, might apply to TerrainX and TerrainZ as well.
What is the issue you have with TerrainX, TerrainZ and TerrainY?
What is the issue you have with TerrainX, TerrainZ and TerrainY?
It's not working when the terrain is scaled: https://github.com/angros47/OpenB3D/issues/9
TerrainY in particular.
I have a suspect of what can cause the bug. Do this experiment: if you have a line like
TerrainY(terrain, x, y, z)
replace it with
TerrainY(terrain, x, y, -z)
(obviously, if you have any other expression or variable in place of z, just change its sign in the same way). Check if it works as expected, in this way, at least for a terrain in position 0,0,0 and not rotated
Also, test if, in terrain.cpp, this patch may help:
float Terrain::TerrainY (float x, float y, float z){ TFormPoint(x, y, z, 0, this); float p0[3],p1[3],p2[3]; p0[0]=(int)tformed_x; p0[2]=(int)-tformed_z; p0[1]=height[(int)((int)tformed_xsize-tformed_z)] vsize;
p2[0]=(int)tformed_x+1;
p2[2]=(int)-tformed_z;
p2[1]=height[(int)(((int)(tformed_x+1)*size)- tformed_z)] * vsize;
if (tformed_x-floor(tformed_x)-tformed_z+floor(tformed_z)<.5){
p1[0]=(int)tformed_x;
p1[2]=(int)-tformed_z-1;
p1[1]=height[(int)(((int)tformed_x*size)- tformed_z-1)] * vsize;
}else
{
p1[0]=(int)tformed_x+1;
p1[2]=(int)-tformed_z-1;
p1[1]=height[(int)(((int)(tformed_x+1)*size)- tformed_z-1)] * vsize;
}
float A = p0[1] *(p1[2] - p2[2]) + p1[1] *(p2[2] - p0[2]) + p2[1] *(p0[2] - p1[2]);
float B = p0[2] *(p1[0] - p2[0]) + p1[2] *(p2[0] - p0[0]) + p2[2] *(p0[0] - p1[0]);
float C = p0[0] *(p1[1] - p2[1]) + p1[0] *(p2[1] - p0[1]) + p2[0] *(p0[1] - p1[1]);
float D = -(p0[0] *(p1[1] * p2[2] - p2[1] * p1[2]) + p1[0] *(p2[1]* p0[2] - p0[1]* p2[2]) + p2[0] *(p0[1] *p1[2] - p1[1] *p0[2]));
if (B==0.0) B=0.0001;
return -(D+A*tformed_x-C*tformed_z)/B;
}
float Terrain::TerrainZ (float x, float y, float z){ TFormPoint(x, y, z, 0, this); return -tformed_z; }
(I haven't tested it, but it might be related with the issue you are talking about)
I did apply the cpp changes, but still the same result with TerrainY not getting accurate ground height when scaled.
Just to be sure: if terrain is NOT scaled, but it is moved and/or rotated, do TerrainX, TerrainY and TerrainZ return the expected result? (with the original version, or with the patched version?) If the terrain is scaled, does the scaling affect only TerrainY, or all? And what happens if you scale the terrain on x and z axis, but not on y?
Also: by multiplying the result of TerrainY with EntityScaleY(terrain, true) do you get the correct value?
Yes, this seems to solve the problem and same with X and Z to show correct results, closing related issue #9
So, please let me know: X and Z show the correct values with or without the patch? And Y shows the correct value (after multiplying it with the scale factor) with or without the patch? So I can fix the official version
reverted back and nothing to do with previous solutions, just multiplying TerrainY with EntityScaleY, applies the same with X and Z.
So, terrainX, terrainy and terrainz have to be multiplied by EntityScaleX/Y/Z to behave like in Blitz3D?
Yes, that should do it.
to behave like in Blitz3D?
It's the only way, unless you don't use TerrainY or other possible affected commands with a Scaled Terrain which seems to be a rare case.
Then, I would not consider it an issue, but just another difference from Blitz3D. In my opinion, in fact, would make more sense to have the TerrainX and TerrainZ referring to the unscaled terrain, so they could be easily used as coordinates for ModifyTerrain (for example, to lower the terrain under the player when the player is digging). And of course, TerrainY should refer to unscaled terrain, too, for consistence
No problem, the main thing is it's related and the issue has been pointed out and resolved. Thanks and closing.
When Blitz3D loads a terrain, the terrain is always flat or at original scale.
LoadTerrain should not determine the height and it should be user defined with ScaleEntity.
Terrain x and z initial sizes are also smaller compared to B3D counter part.