Get normal vector from terrain

There is still problems in the TerrainQuad getNormal method, but I think I know the reason now. This is the method you call:



[java]

public Vector3f getNormal(Vector2f xz) {

// offset

float x = (float)(((xz.x - getWorldTranslation().x) / getWorldScale().x) + (float)(totalSize-1) / 2f);

float z = (float)(((xz.y - getWorldTranslation().z) / getWorldScale().z) + (float)(totalSize-1) / 2f);

Vector3f normal = getNormal(x, z, xz);



return normal;

}

[/java]



The “-1” in (float)(totalSize-1) / 2f didn’t use to be there, but it was changed recently, because of problems when taking normals near the edges of quads.



Anyways, this method calls another method in turn:



[java]

protected Vector3f getNormal(float x, float z, Vector2f xz) {

x-=0.5f;

z-=0.5f;

float col = FastMath.floor(x);

float row = FastMath.floor(z);

boolean onX = false;

if(1 - (x - col)-(z - row) < 0) // what triangle to interpolate on

onX = true;

// v1–v2 ^

// | / | |

// | / | |

// v3–v4 | Z

// |

// <


Y
// X
Vector3f n1 = getMeshNormal((int) FastMath.ceil(x), (int) FastMath.ceil(z));
Vector3f n2 = getMeshNormal((int) FastMath.floor(x), (int) FastMath.ceil(z));
Vector3f n3 = getMeshNormal((int) FastMath.ceil(x), (int) FastMath.floor(z));
Vector3f n4 = getMeshNormal((int) FastMath.floor(x), (int) FastMath.floor(z));

return n1.add(n2).add(n3).add(n4).normalize();
}
[/java]

The x -= 0.5f and z -= 0.5f needs to be removed now that the first method uses (totalSize - 1) / 2 instead of totalSize/2. That doesn't solve the problem tho.

If I'm not completely misstaken, if the totalSize of a terrain quad is 513, and the location is (0,0,0), and scale is 1, that makes x and z values between -256.5 and 256.5 valid on-terrain locations. Assume that totalSize/2 is used, like before, and the -0.5f's remains, as before, you still may add + 256.5 to a value of -256.5, giving 0 in the first method, then subtract -0.5 in the second method, giving x = -0.5. That in turn becomes -1 when floored.

I think changing (totalSize - 1) / 2 back to totalSize/2, and also remove the x,z -= 0.5f would be the right solution. When I suggested adding the "-1" it was only because getHeight used that in its offset formula and getHeight worked with the exact same indata, but now that I looked at the sub-methods I see they are very different from eachother.

EDIT: Btw seems like everything above n1, n2, .. could be removed. And the Vector2f xz param.
1 Like