I have a terrain that is defined as a trianglestrip mesh. Now I'm trying to calculate the normals of each vertex but I've realised that my normal way of calculating vertex normals only works with triangle meshes. I'm finding it hard to wrap around my head how to get the triangles from trianglestrip to calculate the normal in code. I can imagine it but just can't understand how that translates into code.
Can someone help me with some pseudocode or anything of that matter that demonstrates how I could cycle an array that contains indices used in a trianglestrip to calculate the normals?
EDIT:
I ended up finding this answer on stackoverflow and it looked like a very efficient and easy way to generate normals from a heightmap: https://stackoverflow.com/questions/49640250/calculate-normals-from-heightmap/49640606?noredirect=1#
The question defines the point and it's neighbours as follows for clarity. O being the vertex we're calculating a normal for:
T
L O R
B
Having translated it to my own cordinate system (right handed because of opengl), I ended up with the calculation of a normal of a vertex as:
Vec3 normal = Normalize(Vec3((R-L)/2, 1.0f, (B-T)/2));
I implemented that. Here's the constructor for a terrain in my code (fair warning, I am writing my own engine with its own math library. You should be able to infer the meanings of some things by their names though):
Terrain :: Terrain(unsigned int size)
{
unsigned int xSegments = size;
unsigned int ySegments = size;
srand(time(NULL));
m_NoiseMap = CreateScope<NoiseMap>(xSegments + 1, ySegments + 1);
m_NoiseMap->GenerateNoise(rand() % 9999, 25, 0.015, 0.52, Vec2(0.4), 4);
float dX = (float)size / xSegments;
float dY = (float)size / ySegments;
auto heightMap = *m_NoiseMap;
for (unsigned int y = 0; y <= ySegments; ++y)
{
for (unsigned int x = 0; x <= xSegments; ++x)
{
auto height = heightMap[x][y];
auto position = Vec3(dX * x * 2.0f - 1.0f, height, dY * y * 2.0f - 1.0f);
Positions.push_back(position);
UV.push_back(Vec2(dX * x, 1.0f - y * dY));
float heightR, heightL, heightU, heightD = height;
if (y > 0)
heightU = heightMap[x][y - 1];
if (x > 0)
heightL = heightMap[x - 1][y];
if ( y < ySegments)
heightD = heightMap[x][y + 1];
if (x < xSegments)
heightR = heightMap[x + 1][y];
Normals.push_back(Normalize(Vec3((heightR - heightL) / 2, 1.0f, (heightD - heightU) / 2)));
}
}
bool oddRow = false;
for (int y = 0; y < ySegments; ++y)
{
if (!oddRow)
{
for (int x = 0; x <= xSegments; ++x)
{
Indices.push_back(y * (xSegments + 1) + x);
Indices.push_back((y + 1) * (xSegments + 1) + x);
}
}
else
{
for (int x = xSegments; x >= 0; --x)
{
Indices.push_back((y + 1) * (xSegments + 1) + x);
Indices.push_back(y * (xSegments + 1) + x);
}
}
oddRow = !oddRow;
}
Topology = TRIANGLE_STRIP;
Finalize();
}
Unfortunately, when I do this, I get this as the result once I'm done lighting the mesh:
Which just looks random if you ask me. I've set the normal to be flat in the shader as I'm trying to make low poly terrain and do not need smooth shading. Anyone have any clues where I'm going wrong?
Thank you