I am working with a plane model which I am offsetting the vertices on the up axis to look like waves by using the function:
Sin(vertex.x * frequency) * amplitude + Cos(vertex.y * frequency) * amplitude
Previously, I did this with a single variable and was able to confirm my normal directions were correct by getting the derivative, taking the tangent direction from that, and getting the perpendicular direction to the tangent in order to get my normal direction. I then just flipped them so they were facing the right way.
Now that I have added in the second, y, variable I have tried to take a similar approach. Where I take the two partial derivatives, get the tangent direction for each, get the normal for each from that, and then add the normals together to get my final normal direction. However, it seems that the results I am getting are different from those of the Unity calculation, which is correct.
Here is an image comparing my results to the correct Unity calculation:
Does anyone know where about I am going wrong in my calculation? I think it may be related to where and when I am normalizing, but I have tested out a bunch of different options and can't seem to get it to look correct and am now questioning if perhaps my method for combining the two normals is wrong. Thanks for any input. Below is a snippet of the code I am using to do this.
offsetAmount = Mathf.Sin(vertices[i].x * _Frequency) * _Amplitude + Mathf.Cos(vertices[i].y * _Frequency) * _Amplitude;
private void DifferentiateNormals()
{
// Loop through every normal and calculate it manually
for (int i = 0; i < vertices.Length; i++)
{
// The derivative is also an equation for the slope of a tangent line
float offsetAmountDerivative = Mathf.Cos(_Frequency * vertices[i].x) * (_Frequency * _Amplitude);
float offsetAmountDerivative2 = Mathf.Sin(_Frequency * vertices[i].y) * -(_Frequency * _Amplitude);
// Rise / Run => Rise is the derivative function, run is 1
Vector2 tangent = new Vector2(1, offsetAmountDerivative);
tangent.Normalize();
Vector2 tangent2 = new Vector2(1, offsetAmountDerivative2);
tangent2.Normalize();
// The perpendicular of tangent direction (x,y) is (y,-x)
Vector3 normal = new Vector3(tangent.y, 0, -tangent.x);
normal.Normalize();
Vector3 normal2 = new Vector3(tangent2.y, 0, -tangent2.x);
normal2.Normalize();
// Flip the normals to be the correct direction (up)
normal = -normal;
normal2 = -normal2;
Vector3 finalNormal = normal + normal2;
//Vector3 finalNormal = new Vector3(_Amplitude * _Frequency * Mathf.Cos(_Frequency * vertices[i].x), -(_Amplitude * _Frequency) * Mathf.Sin(_Frequency * vertices[i].y), -1);
finalNormal.Normalize();
//finalNormal = -finalNormal;
if (direction == ModelUpDirection.Y_Up)
{
// Works for Unity Plane
normals[i] = new Vector3(finalNormal.x, finalNormal.z, 0.0f);
}
else if (direction == ModelUpDirection.Z_Up)
{
// Works for 100x100 Plane
normals[i] = new Vector3(finalNormal.x, 0.0f, finalNormal.z);
}
}
mesh.normals = normals;
}