Thread: Normals/Tangent Calculation Optimization.

1. Normals/Tangent Calculation Optimization.

I was tired of the normal calculation hogging Unity. So I came up with this idea:

Now the normal calculation for each vertex is relayed on sampling the height map. But that's not necessary for all the vertex on the patch.
Almost all the data needed to calculate normals is on the grid itself. But you need to sample the height map for the ones on the borders since we don't have the info of the surrounding patches. So I came up with this Calculate value method:

Code:
public void CalculateValues()
{
var normals = new Vector3[mesh.vertexCount];
var tangents = new Vector4[mesh.vertexCount];
for (int i = 0; i < mesh.vertexCount; i++)
{

if (i < size || i % size == 0 || (i + 1) % size == 0 || i > (size * (size - 1)))
{
var vertex = mesh.vertices[i];
vertex += position;
normals[i] = CalculateSampleNormal(vertex);
tangents[i] = CalculateTangents(vertex);
}
else
{
var ul = mesh.vertices[i + size];
ul += position;
var ur = mesh.vertices[i + size + 1];
ur += position;
var dl = mesh.vertices[i - size];
dl += position;
var dr = mesh.vertices[i - size - 1];
dr += position;
var lt = mesh.vertices[i - 1];
lt += position;
var rt = mesh.vertices[i + 1];
rt += position;

var u = (ul.y + ur.y) / 2;
var d = (dl.y + dr.y) / 2;

normals[i] = new Vector3(lt.y - rt.y, spacing, d - u).normalized;
tangents[i] = new Vector4(spacing, u - d, 0, -1).normalized;
}
}
mesh.normals = normals;
mesh.tangents = tangents;
}
The if statement is where the magic occurs. It's responsible for identifying the vertex at the border of the patch.

I can't check if this is calculated correctly since I can't compare with a Maya import (I don't have MAYA here)

But if everything is Alright I've decreased the starting time of the level from 7.686s to 2.609s

With this settings:
PatchRowCount = 5
PatchVertexCount = 33
PatchVertexSpacing = 2

Hope this helps.
Last edited by xavierk; 04-20-2011 at 02:46 PM.  Reply With Quote

2. Yay someone figured it out. Was wondering who'd get it first, good work.

This is the principle that the vertex cache that I'm putting together for you guys is based on. But instead of just looking up the vertices in its own patch and doing the calculations for the edge verts. The vertex cache will calculate the heights, normals and tangents for each new vertex added to the cache and each patch will get its info from there so each vertex will only need to be calculate once instead of the current worst case of 20 times for a corner vertex. Should be a huge time savings and greatly smooth out patch load times.  Reply With Quote

3. I was thinking in a new class for the vertex position calculation from whom all the patches should call to create the grid, then I realized that this class should calculate the vertex for the whole area that is being created, but then I had the same issues with the borders of that area. Maybe calculating an extra loop of vertices may do the trick. And also I don't know how much that would take.
I'm still wondering how are you rendering the vast terrain you showed us in your last Terrain R&D pictures.  Reply With Quote

4. Learning C# Join Date
Apr 2009
Location
Rochester, MN
Posts
179
I like this. It really helps to save as much time on my poor laptop when I'm using it instead of my desktop. Thanks for taking the time to figure this out.  Reply With Quote

5. Nice job.   Reply With Quote Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•