usdgeom-mesh-normals-exist#

Code

VG.027

Validator

latest+

Compatibility

core usd

Tags

Summary#

All non-subdivided meshes must have normals.

Description#

Shading of hard edges and smooth surfaces described by non-subdivided meshes in rendering systems requires surface normals. Normals should be authored with the intention to accurately represent the intended surface appearance (e.g. smooth, hard edge, crease, etc.). When converting from other formats, the normals should be preserved or accurately sampled from the source surface.

Normals can be represented by the “normals” or the “primvars:normals” attributes, but only one of these representations should exist on each mesh to avoid confusion. “primvars:normals” is the preferred representation as it allows for indexing.

Why is it required?#

  • Missing normals may lead to unrealistic faceting or soft edges.

  • Automatic generation of normals may not accurately represent the intended surface appearance.

Incorrect

normals_incorrect

Correct

normals_correct

Examples#

#usda 1.0
(
    metersPerUnit = 1
    upAxis = "Z"
)

# Valid Soft edge between to faces

def Mesh "soft"
{
    float3[] extent = [(-0.05, -0.05, -0.025), (0.05, 0.05, 0)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 3, 4, 1, 1, 4, 5, 2]
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    normal3f[] primvars:normals = [(-0.447, 0, 0.894), (-0.447, 0, 0.894), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0.447, 0, 0.894), (0.447, 0, 0.894)] (
        interpolation = "faceVarying"
    )
    uniform token subdivisionScheme = "none"
}

# Valid: Hard edge between to faces

def Mesh "sharp"
{
    float3[] extent = [(-0.05, -0.05, -0.025), (0.05, 0.05, 0)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 3, 4, 1, 1, 4, 5, 2]
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    normal3f[] primvars:normals = [(-0.447, 0, 0.894), (-0.447, 0, 0.894), (-0.447, 0, 0.894), (-0.447, 0, 0.894), (0.447, 0, 0.894), (0.447, 0, 0.894), (0.447, 0, 0.894), (0.447, 0, 0.894)] (
        interpolation = "faceVarying"
    )
    uniform token subdivisionScheme = "none"
}

# Invalid: No normals to define soft or hard edge

def Mesh "none"
{
    float3[] extent = [(-0.05, -0.05, -0.025), (0.05, 0.05, 0)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 3, 4, 1, 1, 4, 5, 2]
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    uniform token subdivisionScheme = "none"
}

# Invalid: Both `normals` and `primvars:normals` exist

def Mesh "both"
{
    float3[] extent = [(-0.05, -0.05, -0.025), (0.05, 0.05, 0)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 3, 4, 1, 1, 4, 5, 2]
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    normal3f[] normals = [(-0.447, 0, 0.894), (-0.447, 0, 0.894), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0.447, 0, 0.894), (0.447, 0, 0.894)] (
        interpolation = "faceVarying"
    )
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    normal3f[] primvars:normals = [(-0.447, 0, 0.894), (0, 0, 1), (0.447, 0, 0.894)] (
        interpolation = "faceVarying"
    )
    int[] primvars:normals:indices = [0, 0, 1, 1, 1, 1, 2, 2]
    uniform token subdivisionScheme = "none"
}

# Valid: Only `primvars:normals` exists

def Mesh "only"
{
    float3[] extent = [(-0.05, -0.05, -0.025), (0.05, 0.05, 0)]
    int[] faceVertexCounts = [4, 4]
    int[] faceVertexIndices = [0, 3, 4, 1, 1, 4, 5, 2]
    point3f[] points = [(-0.05, 0.05, -0.025), (0, 0.05, 0), (0.05, 0.05, -0.025), (-0.05, -0.05, -0.025), (0, -0.05, 0), (0.05, -0.05, -0.025)]
    normal3f[] primvars:normals = [(-0.447, 0, 0.894), (0, 0, 1), (0.447, 0, 0.894)] (
        interpolation = "faceVarying"
    )
    int[] primvars:normals:indices = [0, 0, 1, 1, 1, 1, 2, 2]
    uniform token subdivisionScheme = "none"
}

How to comply#

  • Author normals on all mesh geometry intended for visualization.

  • Author normals that accurately represent the intended surface appearance.

  • Remove normals if both normals and primvars:normals exist on a mesh.

For More Information#