def processUVs(self, fbxMesh, usdMesh, vertexIndices): for layerIdx in xrange(fbxMesh.GetLayerCount()): fbxLayerUVs = fbxMesh.GetLayer( layerIdx).GetUVs() # get diffuse texture uv-s if fbxLayerUVs is None: continue uvs = [] uvArray = fbxLayerUVs.GetDirectArray() for i in xrange(uvArray.GetCount()): uv = uvArray.GetAt(i) uvs.append(Gf.Vec2f(uv[0], uv[1])) if not any(uvs): continue indices = self.getIndicesWithLayerElements(fbxMesh, fbxLayerUVs) interpolation = self.getInterpolationWithLayerElements(fbxLayerUVs) texCoordSet = 'st' uvSets = fbxMesh.GetLayer(layerIdx).GetUVSets() if len(uvSets) > 0: fbxLayerElementUV = fbxMesh.GetLayer(layerIdx).GetUVSets()[0] texCoordSet = str(fbxLayerElementUV.GetName()) if layerIdx == 0 or texCoordSet == '' or texCoordSet == 'default': texCoordSet = 'st' else: texCoordSet = usdUtils.makeValidIdentifier(texCoordSet) uvPrimvar = usdMesh.CreatePrimvar(texCoordSet, Sdf.ValueTypeNames.Float2Array, interpolation) uvPrimvar.Set(uvs) if len(indices) != 0: uvPrimvar.SetIndices(Vt.IntArray(indices))
def processSkinnedMeshes(self): for fbxNode, skeleton in self.skeletonByNode.iteritems(): fbxSkin = self.getFbxSkin(fbxNode) if skeleton is None: if fbxSkin is None: continue skin = self.fbxSkinToSkin[fbxSkin] skeleton = skin.skeleton nodeName = usdUtils.makeValidIdentifier( fbxNode.GetName().split(":")[-1]) newPath = skeleton.sdfPath + '/' + nodeName if newPath in self.nodePaths: newPath = newPath + str(self.nodeId) self.nodeId = self.nodeId + 1 self.nodePaths[newPath] = newPath self.processMesh(fbxNode, newPath, skeleton, '')
def bindMaterials(self, fbxMesh, usdMesh): for layerIdx in xrange(fbxMesh.GetLayerCount()): fbxLayerMaterials = fbxMesh.GetLayer(layerIdx).GetMaterials() if not fbxLayerMaterials: continue # looks like there is a bug in FBX SDK: # GetDirectArray() does not work if .GetCount() has not been called materialsCount = fbxLayerMaterials.GetDirectArray().GetCount() if fbxLayerMaterials.GetIndexArray().GetCount( ) > 1 and fbxLayerMaterials.GetMappingMode( ) == fbx.FbxLayerElement.eByPolygon: # subsets subsets = [[] for i in range(materialsCount)] for polygonIdx in range( fbxLayerMaterials.GetIndexArray().GetCount()): materialIndex = fbxLayerMaterials.GetIndexArray().GetAt( polygonIdx) subsets[materialIndex].append(polygonIdx) bindingAPI = UsdShade.MaterialBindingAPI(usdMesh) for materialIndex in range(materialsCount): facesCount = len(subsets[materialIndex]) if facesCount > 0: fbxMaterial = fbxLayerMaterials.GetDirectArray().GetAt( materialIndex) materialName = usdUtils.makeValidIdentifier( fbxMaterial.GetName()) subsetName = materialName + '_subset' if self.verbose: print ' subset:', subsetName, 'faces:', facesCount usdSubset = UsdShade.MaterialBindingAPI.CreateMaterialBindSubset( bindingAPI, subsetName, Vt.IntArray(subsets[materialIndex])) usdMaterial = self.usdMaterials[fbxMaterial.GetName()] UsdShade.MaterialBindingAPI(usdSubset).Bind( usdMaterial) elif fbxLayerMaterials.GetIndexArray().GetCount() > 0: # one material for whole mesh fbxMaterial = fbxLayerMaterials.GetDirectArray().GetAt(0) if fbxMaterial is not None and fbxMaterial.GetName( ) in self.usdMaterials: usdMaterial = self.usdMaterials[fbxMaterial.GetName()] UsdShade.Material.Bind(usdMaterial, usdMesh.GetPrim())
def getTextureProperties(self, materialProperty): if materialProperty.GetSrcObjectCount( fbx.FbxCriteria.ObjectType(fbx.FbxFileTexture.ClassId)) > 0: fbxFileTexture = materialProperty.GetSrcObject( fbx.FbxCriteria.ObjectType(fbx.FbxFileTexture.ClassId), 0) texCoordSet = 'st' if fbxFileTexture.UVSet is not None: texCoordSet = str(fbxFileTexture.UVSet.Get()) if texCoordSet == '' or texCoordSet == 'default': texCoordSet = 'st' else: texCoordSet = usdUtils.makeValidIdentifier(texCoordSet) wrapS = 'repeat' wrapT = 'repeat' if fbxFileTexture.GetWrapModeU() == fbx.FbxTexture.eClamp: wrapS = 'clamp' if fbxFileTexture.GetWrapModeV() == fbx.FbxTexture.eClamp: wrapT = 'clamp' return fbxFileTexture.GetFileName(), texCoordSet, wrapS, wrapT elif materialProperty.GetSrcObjectCount( fbx.FbxCriteria.ObjectType(fbx.FbxLayeredTexture.ClassId)) > 0: pass return '', 'st', 'repeat', 'repeat'
def createMesh(self, geomPath, group, groupName, usdStage): if len(group.faceVertexCounts) == 0: return False groupName = usdUtils.makeValidIdentifier(groupName) if self.verbose: print ' creating USD mesh:', groupName, ('(subsets: ' + str(len(group.subsets)) + ')' if len(group.subsets) > 1 else '') usdMesh = UsdGeom.Mesh.Define(usdStage, geomPath + '/' + groupName) usdMesh.CreateSubdivisionSchemeAttr(UsdGeom.Tokens.none) usdMesh.CreateFaceVertexCountsAttr(group.faceVertexCounts) # vertices minVertexIndex = min(group.vertexIndices) maxVertexIndex = max(group.vertexIndices) groupVertices = self.vertices[minVertexIndex:maxVertexIndex+1] usdMesh.CreatePointsAttr(groupVertices) if minVertexIndex == 0: # optimization usdMesh.CreateFaceVertexIndicesAttr(group.vertexIndices) else: usdMesh.CreateFaceVertexIndicesAttr(map(lambda x: x - minVertexIndex, group.vertexIndices)) extent = Gf.Range3f() for pt in groupVertices: extent.UnionWith(Gf.Vec3f(pt)) usdMesh.CreateExtentAttr([extent.GetMin(), extent.GetMax()]) # vertex colors if len(self.colors) == len(self.vertices): colorAttr = usdMesh.CreateDisplayColorPrimvar(UsdGeom.Tokens.vertex) colorAttr.Set(self.colors[minVertexIndex:maxVertexIndex+1]) # texture coordinates minUvIndex = min(group.uvIndices) maxUvIndex = max(group.uvIndices) if minUvIndex >= 0: if group.uvsHaveOwnIndices: uvPrimvar = usdMesh.CreatePrimvar('st', Sdf.ValueTypeNames.TexCoord2fArray, UsdGeom.Tokens.faceVarying) uvPrimvar.Set(self.uvs[minUvIndex:maxUvIndex+1]) if minUvIndex == 0: # optimization uvPrimvar.SetIndices(Vt.IntArray(group.uvIndices)) else: uvPrimvar.SetIndices(Vt.IntArray(map(lambda x: x - minUvIndex, group.uvIndices))) else: uvPrimvar = usdMesh.CreatePrimvar('st', Sdf.ValueTypeNames.TexCoord2fArray, UsdGeom.Tokens.vertex) uvPrimvar.Set(self.uvs[minUvIndex:maxUvIndex+1]) # normals minNormalIndex = min(group.normalIndices) maxNormalIndex = max(group.normalIndices) if minNormalIndex >= 0: if group.normalsHaveOwnIndices: normalPrimvar = usdMesh.CreatePrimvar('normals', Sdf.ValueTypeNames.Normal3fArray, UsdGeom.Tokens.faceVarying) normalPrimvar.Set(self.normals[minNormalIndex:maxNormalIndex+1]) if minNormalIndex == 0: # optimization normalPrimvar.SetIndices(Vt.IntArray(group.normalIndices)) else: normalPrimvar.SetIndices(Vt.IntArray(map(lambda x: x - minNormalIndex, group.normalIndices))) else: normalPrimvar = usdMesh.CreatePrimvar('normals', Sdf.ValueTypeNames.Normal3fArray, UsdGeom.Tokens.vertex) normalPrimvar.Set(self.normals[minNormalIndex:maxNormalIndex+1]) # materials if len(group.subsets) == 1: materialIndex = group.subsets[0].materialIndex if self.verbose: if 0 <= materialIndex and materialIndex < len(self.usdMaterials): print usdUtils.makeValidIdentifier(self.materials[materialIndex]) else: print 'defaultMaterial' UsdShade.MaterialBindingAPI(usdMesh).Bind(self.getUsdMaterial(materialIndex)) else: bindingAPI = UsdShade.MaterialBindingAPI(usdMesh) for subset in group.subsets: materialIndex = subset.materialIndex if len(subset.faces) > 0: materialName = 'defaultMaterial' if 0 <= materialIndex and materialIndex < len(self.usdMaterials): materialName = usdUtils.makeValidIdentifier(self.materials[materialIndex]) subsetName = materialName + 'Subset' if self.verbose: print ' subset:', subsetName, 'faces:', len(subset.faces) usdSubset = UsdShade.MaterialBindingAPI.CreateMaterialBindSubset(bindingAPI, subsetName, Vt.IntArray(subset.faces)) UsdShade.MaterialBindingAPI(usdSubset).Bind(self.getUsdMaterial(materialIndex))
def processNode(self, fbxNode, path, underSkeleton, indent): nodeName = usdUtils.makeValidIdentifier( fbxNode.GetName().split(":")[-1]) newPath = path + '/' + nodeName if newPath in self.nodePaths: newPath = newPath + str(self.nodeId) self.nodeId = self.nodeId + 1 fbxAttributeType = fbx.FbxNodeAttribute.eNone fbxNodeAttribute = fbxNode.GetNodeAttribute() if fbxNodeAttribute: fbxAttributeType = fbxNodeAttribute.GetAttributeType() if fbx.FbxNodeAttribute.eSkeleton == fbxAttributeType: if fbxNodeAttribute.IsSkeletonRoot(): skeleton = self.skinning.findSkeletonByRoot(fbxNode) if skeleton is None: skeleton = self.skinning.findSkeletonByJoint(fbxNode) if skeleton is not None: skeleton.makeUsdSkeleton(self.usdStage, newPath, self.nodeManager) if self.verbose: print indent + "SkelRoot:", nodeName underSkeleton = skeleton if underSkeleton and self.getFbxMesh(fbxNode) is not None: self.skeletonByNode[fbxNode] = underSkeleton elif self.getFbxSkin(fbxNode) is not None: self.skeletonByNode[fbxNode] = None else: # if we have a geometric transformation we shouldn't propagate it to node's children usdNode = None hasGeometricTransform = self.hasGeometricTransform(fbxNode) if underSkeleton is None and hasGeometricTransform and underSkeleton is None: usdNode = UsdGeom.Xform.Define(self.usdStage, newPath) geometryPath = newPath + '/' + nodeName + '_geometry' else: geometryPath = newPath usdGeometry = None if (fbx.FbxNodeAttribute.eMesh == fbxAttributeType or fbx.FbxNodeAttribute.eSubDiv == fbxAttributeType): usdGeometry = self.processMesh(fbxNode, geometryPath, underSkeleton, indent) if underSkeleton is None: if usdGeometry is None: usdGeometry = UsdGeom.Xform.Define(self.usdStage, geometryPath) self.nodePaths[newPath] = newPath if hasGeometricTransform: self.setNodeTransforms(fbxNode, usdNode) self.setGeometricTransform(fbxNode, usdGeometry) self.processNodeAnimations(fbxNode, usdNode) else: self.setNodeTransforms(fbxNode, usdGeometry) self.processNodeAnimations(fbxNode, usdGeometry) # process child nodes recursively if underSkeleton is not None: newPath = path # keep meshes directly under SkelRoot scope for childIdx in xrange(fbxNode.GetChildCount()): self.processNode(fbxNode.GetChild(childIdx), newPath, underSkeleton, indent + ' ')
def overrideGetName(self, fbxNode): return usdUtils.makeValidIdentifier(fbxNode.GetName().split(":")[-1])
def getName(dict, template, id): if 'name' in dict and len(dict['name']) != 0: validName = usdUtils.makeValidIdentifier(dict['name']) if validName != 'defaultIdentifier': return validName return template + str(id)