Search code examples
pythonvirtual-realitytexture-mappingusdzusd

Python for USD – Map a texture on a cube so every face have the same image


back of the cube with wrong mapping texture

I have a simple mesh cube, and I want the same image to be applied on each face of the cube : Here is what I have so far (front face is ok but not the others)

# create mesh with texture coordinates
stage.DefinePrim('/' + assetName + '/Geom', 'Scope')
mesh = UsdGeom.Mesh.Define(stage, '/' + assetName + '/Geom/cube')
mesh.CreateSubdivisionSchemeAttr().Set(UsdGeom.Tokens.none)
mesh.CreatePointsAttr([(-x/2, -y/2, z/2), (x/2, -y/2, z/2), (-x/2, y/2, z/2), (x/2, y/2, z/2), (-x/2, y/2, -z/2), (x/2, y/2, -z/2), (-x/2, -y/2, -z/2), (x/2, -y/2, -z/2)])
mesh.CreateExtentAttr(UsdGeom.PointBased(mesh).ComputeExtent(mesh.GetPointsAttr().Get()))
mesh.CreateNormalsAttr([(0,0,1), (0,1,0), (0,0,-1), (0,-1,0), (1,0,0), (-1,0,0)])
mesh.SetNormalsInterpolation(UsdGeom.Tokens.uniform)

mesh.CreateFaceVertexCountsAttr([4, 4, 4, 4, 4, 4])
mesh.CreateFaceVertexIndicesAttr([0,1,3,2, 2,3,5,4, 4,5,7,6, 6,7,1,0, 1,7,5,3, 6,0,2,4]) # per-face vertex indices
    
texCoords = mesh.CreatePrimvar('st', Sdf.ValueTypeNames.TexCoord2fArray, UsdGeom.Tokens.faceVarying) # a 'faceVarying' mesh attribute is stored per-face per-vertex
texCoords.Set([(0, 0),(1, 0), (1,1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0)])

texCoords.SetIndices(Vt.IntArray([0,1,2,3, 3,2,4,5, 5,4,6,7, 7,6,8,9, 1,10,11,2, 12,0,3,13]))

Front face has the texture as intended, but others are weird. I don't understand how texture Coordinates are defined.

Thanks for helping.


Solution

  • USDA Python scripting

    I have the following solution, but it has incorrect mapping (you should reconstruct this cube primitive from scratch). However, this example clearly shows you how the texture is mapped into each individual face of the USDA model.

    enter image description here

    #usda 1.0
    (
        defaultPrim = "Cube"
        upAxis = "Y"
    )
    
    def Xform "Cube" (kind = "component")
    {
        def Mesh "polyCube"
        {    
            float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)]    
            int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]    
            int[] faceVertexIndices = [ 0, 1, 3, 2,  2, 3, 5, 4,  4, 5, 7, 6, 
                                        6, 7, 1, 0,  1, 7, 5, 3,  6, 0, 2, 4 ]
    
            point3f[] points = [ (-0.5,-0.5, 0.5), (0.5,-0.5, 0.5), 
                                 (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), 
                                 (-0.5, 0.5,-0.5), (0.5, 0.5,-0.5), 
                                 (-0.5,-0.5,-0.5), (0.5,-0.5,-0.5) ]
    
            texCoord2f[] primvars:st = [ (0, 0), (0, 1), (1, 0), (1, 1), (0, 0), 
                                         (0, 1), (1, 0), (1, 1), (0, 0), (0, 1), 
                                         (1, 0), (1, 1), (0, 0), (0, 1) ] (    
                interpolation = "faceVarying"
            )
    
            int[] primvars:st:indices = [ 0, 1, 2, 3,   3, 2, 4, 5,    5, 4, 6, 7, 
                                          7, 6, 8, 9,   1, 10, 11, 2,  12, 0, 3, 13 ]
    
            color3f[] primvars:displayColor = [(0.75, 0.75, 0.75)]
            rel material:binding = </Texturing/Material>
        } 
    }
    

    Here's a shader:

    def Xform "Texturing" 
    {
        def Material "Material"
        {
            token outputs:surface.connect = </Texturing/Material/Surface.outputs:surface>
    
            def Shader "Surface"
            {
                uniform token info:id = "UsdUVTexture"
                asset inputs:file = @image.jpg@
    
                token inputs:wrapS = "repeat"
                token inputs:wrapT = "repeat"
                token outputs:rgb
    
                color3f inputs:diffuseColor.connect = </Texturing/Material/Surface.outputs:rgb>    
                token outputs:surface
            }
        }
    }