Original Post
How can I compute vertex normals for a terrain chunk? Suppose the chunk is 32x32, what should I do?
So far, I am setting the ny to 1 and all other to 0. Any other ways?
Thanks
The 4 adjacent points in a uniform grid: A, B, C, D
B
|
C--0--A
|
D
The ratio of XY-scale to Z-scale: s = Sxy / Sz
The desired normal: N = cross(A,B) + cross(B,C) + cross(C,D) + cross(D,A), (then normalize)
A faster way to get the same answer:
Nx = 2 * s * (Cz - Az)
Ny = 2 * s * (Dz - Bz)
Nz = 4 * s^2
N = normalize( N )
And since N is normalized in the end, it can be divided by 2 * s:
Nx = Cz - Az
Ny = Dz - Bz
Nz = 2 * s
N = normalize( N )
bool CAdvTerrain::CalcNormals()
{
DWORD numVertices;
DWORD numFaces;
// Get face and vertex count
numFaces = m_TerrainFaces;
numVertices = m_TerrainVerts;
WORD* pNumOfSharedPolygons = new WORD[numVertices]; //Array holds how many times this vertex is shared
D3DXVECTOR3* pSumVertexNormal = new D3DXVECTOR3[3 * numFaces]; //Array holds sum of all face normals for shared vertex
ADVT_CUSTOMVERTEX* pVertices;
short* pIndices;
D3DXVECTOR3 vNormal;
//Lock the vertex buffer
m_pTerrainVB->Lock(0, numVertices * sizeof(ADVT_CUSTOMVERTEX),(void **)&pVertices, 0);
m_pTerrainIB->Lock(0, 3 * numFaces * sizeof(short), (void **)&pIndices, 0);
int facenew = 0;
for (DWORD i=0; i < numFaces ; i++)
{
pNumOfSharedPolygons[pIndices[3*i+0]] = 0;
pSumVertexNormal[pIndices[3*i+0]] = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
pSumVertexNormal[pIndices[3*i+1]] = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
pSumVertexNormal[pIndices[3*i+2]] = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
}
for (DWORD i=0; i < numFaces ; i++)
{
D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p;
D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p;
D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;
vNormal = GetTriangeNormal(&v0, &v1, &v2);
pNumOfSharedPolygons[pIndices[3*i+0]]++;
pNumOfSharedPolygons[pIndices[3*i+1]]++;
pNumOfSharedPolygons[pIndices[3*i+2]]++;
pSumVertexNormal[pIndices[3*i+0]] += vNormal;
pSumVertexNormal[pIndices[3*i+1]] += vNormal;
pSumVertexNormal[pIndices[3*i+2]] += vNormal;
}
// Direction vector OF DIRECTIONAL LIGHT TO TEST NORMALS dont need to enable d3d lighting
D3DXVECTOR3 lightpos = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
float factor = 0.0f;
//For each vertex, calculate the average normal
for(i = 0; i < numVertices; i++)
{
vNormal.x = pSumVertexNormal[i].x / pNumOfSharedPolygons[i];
vNormal.y = pSumVertexNormal[i].y / pNumOfSharedPolygons[i];
vNormal.z = pSumVertexNormal[i].z / pNumOfSharedPolygons[i];
D3DXVec3Normalize(&vNormal, &vNormal);
pVertices[i].n = vNormal;
D3DXVec3Normalize(&lightpos, &lightpos);
factor = D3DXVec3Dot(&vNormal, &lightpos);
if (factor < 0)
factor = 0;
float red = 25.0f * factor;
float gre = 185.0f * factor; // terrain green color
float blu = 55.0f * factor;
pVertices[i].d = D3DCOLOR_XRGB((int)red, (int)gre, (int)blu);
}
// Smooting stuff in rows and cols
float k = 0.0f;
m_pTerrainVB->Unlock();
m_pTerrainIB->Unlock();
return true;
}
This topic has been locked by a moderator. New replies are not allowed.
With your permission, GameDev.net uses analytics cookies to understand how people use the platform. You can accept analytics or continue with necessary cookies only. Learn more