Search Unity

Resolved What are mesh.normals, exactly

Discussion in 'General Graphics' started by Ne0mega, Jul 14, 2021.

  1. Ne0mega

    Ne0mega

    Joined:
    Feb 18, 2018
    Posts:
    755
    I sampled some of them from my procedural terrain mesh, and they all carry one digit precision floats (0.1, -0.3)

    I understand that the x is left right angle, y is up direction, and z is forward/back. So most of the normals, (for the terrain) were (0.0, 1.0, 0.0)

    What I dont get is why the un-precision? Why are they all like "0.3", "0.1"and not "0.354678276252518"? and "0.1762591723592" like what I would expect to be normal normalized float values.

    I am hoping to use the normals for easy steepness data, so I can adjust speeds and calculate building placement restrictions quickly and painlessly.
     
  2. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    How do you sample them? If you're just printing them out, the string conversion of Vector3 only uses 1 digit precision (2 in recent versions). Either use custom string formatting on the values, or look at them in a debugger.
     
    Ne0mega likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Try this:
    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [ExecuteInEditMode]
    6. public class DebugLogTest : MonoBehaviour
    7. {
    8.     public Vector3 value = new Vector3(0.0001f, 0.1234567f, 0.1666667f);
    9.  
    10.     void Update()
    11.     {
    12.         Debug.Log("Default Vector3 formatting: " + value);
    13.         Debug.Log("Individual components: (" + value.x + ", " + value.y + ", " + value.z + ")");
    14.  
    15.         // https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
    16.         Debug.Log("Explicit Vector3 formatting: " + value.ToString("G"));
    17.     }
    18. }
    That should print out something like this:
    The problem is Unity's default
    ToString()
    for the Vector3 class prints each component using the format
    "F1"
    which limits the number of decimal places to show to 1.
    https://github.com/Unity-Technologi...ob/master/Runtime/Export/Math/Vector3.cs#L466
    https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings

    The built in c# numerical types, like
    float
    , default to showing as many decimals as appropriate for that type's precision. This is equivalent to using the format
    "G"
    . For
    float
    that's 7 decimal places, which is the limit of that format's precision, hence why the entirety of
    0.1234567
    displays. You can override Unity's default formatting for
    Vector3
    by using the
    .ToString()
    function with an explicit format string. Using
    "G"
    here results in the same 7 decimal places because internally the
    Vector3
    is a
    struct
    of 3
    float
    values.
     
    Ne0mega likes this.
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    That all said, lets answer the original question in the thread title of "What are mesh.normals exactly".

    They're generally a normalized (a length of 1.0)
    Vector3
    /
    float3
    in the average direction of the triangles that are connected to that vertex. The intent would be to use them with another normalized
    float3
    value of the light direction to calculate the lighting using a dot product. The dot product of two normalized vectors results in the cosine of the angle difference between the two vectors. Which is also what Lambertian shading is. It's also used for other lighting calculations, which all also use at least one dot product at some point, and often several, with several different normalized vectors.
     
    Ne0mega likes this.