// Returns the gltf mesh that corresponds to the payload, or null. // Currently, null is only returned if the payload's 'geometry pool is empty. // Pass a localXf to override the default, which is to use base.xform public GlTF_Node ExportMeshPayload( SceneStatePayload payload, BaseMeshPayload meshPayload, [CanBeNull] GlTF_Node parent, Matrix4x4?localXf = null) { var node = ExportMeshPayload_NoMaterial(meshPayload, parent, localXf); if (node != null) { IExportableMaterial exportableMaterial = meshPayload.exportableMaterial; if (!G.materials.ContainsKey(exportableMaterial)) { var prims = node.m_mesh?.primitives; var attrs = (prims != null && prims.Count > 0) ? prims[0].attributes : null; if (attrs != null) { ExportMaterial(payload, meshPayload.MeshNamespace, exportableMaterial, attrs); Debug.Assert(G.materials.ContainsKey(exportableMaterial)); } } } return(node); }
// Doesn't do material export; for that see ExportMeshPayload private GlTF_Node ExportMeshPayload_NoMaterial( BaseMeshPayload mesh, [CanBeNull] GlTF_Node parent, Matrix4x4?localXf = null) { ObjectName meshNameAndId = new ObjectName(mesh.legacyUniqueName); GeometryPool pool = mesh.geometry; Matrix4x4 xf = localXf ?? mesh.xform; // Create a Node and (usually) a Mesh, both named after meshNameAndId. // This is safe because the namespaces for Node and Mesh are distinct. // If we have already seen the GeometryPool, the Mesh will be reused. // In this (less common) case, the Node and Mesh will have different names. // We don't actually ever use the "VERTEXID" attribute, even in gltf1. // It's time to cut it away. // Also, in gltf2, it needs to be called _VERTEXID anyway since it's a custom attribute GlTF_VertexLayout gltfLayout = new GlTF_VertexLayout(G, pool.Layout); int numTris = pool.NumTriIndices / 3; if (numTris < 1) { return(null); } NumTris += numTris; GlTF_Mesh gltfMesh; // Share meshes for any repeated geometry pool. if (!m_meshCache.TryGetValue(pool, out gltfMesh)) { gltfMesh = new GlTF_Mesh(G); gltfMesh.name = GlTF_Mesh.GetNameFromObject(meshNameAndId); gltfMesh.PresentationNameOverride = mesh.geometryName; m_meshCache.Add(pool, gltfMesh); // Populate mesh data only once. AddMeshDependencies(meshNameAndId, mesh.exportableMaterial, gltfMesh, gltfLayout); gltfMesh.Populate(pool); G.meshes.Add(gltfMesh); } // The mesh may or may not be shared, but every mesh will have a distinct node to allow them // to have unique transforms. GlTF_Node node = GlTF_Node.GetOrCreate(G, meshNameAndId, xf, parent, out _); node.m_mesh = gltfMesh; node.PresentationNameOverride = mesh.nodeName; return(node); }
// This writes out payload.xform static FbxNode ExportMeshPayload_Global( FbxExportGlobals G, BaseMeshPayload payload, FbxNode parentNode) { // If these aren't unique, either FBX or Unity will uniquify them for us -- not sure which. // So roll payload.id into the name. FbxNode fbxNode = FbxNode.Create(G.m_manager, payload.nodeName); fbxNode.SetLocalTransform(payload.xform); fbxNode.SetNodeAttribute(G.GetOrCreateFbxMesh(payload)); fbxNode.AddMaterial(G.GetOrCreateFbxMaterial( payload.MeshNamespace, payload.exportableMaterial)); parentNode.AddChild(fbxNode); return(fbxNode); }