Esempio n. 1
0
        /// <summary>
        /// Returns the USD.NET.Scene object for this USD file.
        /// The caller is NOT expected to close the scene.
        /// </summary>
        public Scene GetScene()
        {
            InitUsd.Initialize();

            if (m_lastScene == null || m_lastScene.Stage == null || SceneFileChanged())
            {
                pxr.UsdStage stage = null;
                if (string.IsNullOrEmpty(usdFullPath))
                {
                    return(null);
                }
                if (m_payloadPolicy == PayloadPolicy.DontLoadPayloads)
                {
                    stage = pxr.UsdStage.Open(usdFullPath, pxr.UsdStage.InitialLoadSet.LoadNone);
                }
                else
                {
                    stage = pxr.UsdStage.Open(usdFullPath, pxr.UsdStage.InitialLoadSet.LoadAll);
                }

                m_lastScene      = Scene.Open(stage);
                m_lastPrimMap    = null;
                m_lastAccessMask = null;

                // TODO: This is potentially horrible in terms of performance, LoadAndUnload should be used
                // instead, but the binding is not complete.
                foreach (var payload in GetComponentsInParent <UsdPayload>())
                {
                    var primSrc = payload.GetComponent <UsdPrimSource>();
                    if (payload.IsLoaded && m_payloadPolicy == PayloadPolicy.DontLoadPayloads)
                    {
                        var prim = m_lastScene.GetPrimAtPath(primSrc.m_usdPrimPath);
                        if (prim == null || !prim)
                        {
                            continue;
                        }
                        prim.Load();
                    }
                    else
                    {
                        var prim = m_lastScene.GetPrimAtPath(primSrc.m_usdPrimPath);
                        if (prim == null || !prim)
                        {
                            continue;
                        }
                        prim.Unload();
                    }
                }

                // Re-apply variant selection state, similar to prim load state.
                foreach (var variants in GetComponentsInChildren <UsdVariantSet>())
                {
                    ApplyVariantSelectionState(m_lastScene, variants);
                }
            }

            m_lastScene.Time = m_usdTimeOffset;
            m_lastScene.SetInterpolation(m_interpolation);
            return(m_lastScene);
        }
Esempio n. 2
0
        /// <summary>
        /// Given a PrimMap, finds all instanced objects and their respective master objects and
        /// instantiates Unity clones using GameObject.Instantiate. Note that this does not result
        /// in GPU instancing.
        /// </summary>
        public static void BuildSceneInstances(PrimMap primMap, SceneImportOptions options)
        {
            if (options.enableGpuInstancing)
            {
                foreach (var masterPath in primMap.GetMasterRootPaths())
                {
                    EnableGpuInstancing(primMap[masterPath]);
                }
            }

            foreach (var instance in primMap.GetInstanceRoots())
            {
                GameObject goInstance = instance.gameObject;
                GameObject goMaster   = primMap[instance.masterPath];
                foreach (Transform child in goMaster.transform)
                {
                    Transform newChild = goInstance.transform.Find(child.name);
                    if (newChild == null)
                    {
                        newChild      = GameObject.Instantiate(child.gameObject).transform;
                        newChild.name = child.name;
                        newChild.transform.SetParent(goInstance.transform, worldPositionStays: false);
                    }

                    primMap.AddInstance(newChild.gameObject);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Imports the USD scene incrementally, setting a fixed time budget per frame for import
        /// operations. Uses StartCoroutine.
        /// </summary>
        public void ImportUsdAsCoroutine(GameObject goRoot,
                                         string usdFilePath,
                                         double time,
                                         SceneImportOptions importOptions,
                                         float targetFrameMilliseconds)
        {
            InitUsd.Initialize();
            var scene = Scene.Open(usdFilePath);

            if (scene == null)
            {
                throw new Exception("Failed to open: " + usdFilePath);
            }

            scene.Time = time;
            if (scene == null)
            {
                throw new Exception("Null USD Scene");
            }

            scene.SetInterpolation(importOptions.interpolate ?
                                   Scene.InterpolationMode.Linear :
                                   Scene.InterpolationMode.Held);
            var primMap  = new PrimMap();
            var importer = SceneImporter.BuildScene(scene,
                                                    goRoot,
                                                    importOptions,
                                                    primMap,
                                                    targetFrameMilliseconds,
                                                    composingSubtree: false);

            StartCoroutine(importer);
        }
Esempio n. 4
0
        static HierInfo[] BuildObjectLists(Scene scene,
                                           GameObject unityRoot,
                                           SdfPath usdRoot,
                                           PrimMap map,
                                           SceneImportOptions options)
        {
            if (map.SkelCache == null)
            {
                // Note that UsdSkelCache is thread safe and can be populated from multiple threads.
                map.SkelCache = new UsdSkelCache();

                // The skelBindings dictionary, however, is not thread safe and must be populated after the
                // hierarchy discovery thread joins, in ProcessPaths.
                map.SkelBindings = new Dictionary <SdfPath, UsdSkelBindingVector>();
            }

#if !UNITY_2017
            BeginReading(scene, usdRoot, map, options).Complete();
#else
            BeginReading(scene, usdRoot, map, options);
#endif

            ProcessPaths(ReadHierJob.result, scene, unityRoot, usdRoot, map, options);

            return(ReadHierJob.result);
        }
Esempio n. 5
0
 public static void ImportUsd(GameObject goRoot,
                              Scene scene,
                              PrimMap primMap,
                              SceneImportOptions importOptions)
 {
     ImportUsd(goRoot, scene, primMap, false, importOptions);
 }
Esempio n. 6
0
 /// <summary>
 /// A private event that fires whenever the USD scene was reimported.
 /// </summary>
 private void OnReload()
 {
     m_lastPrimMap    = null;
     m_lastAccessMask = null;
     if (m_lastScene != null)
     {
         m_lastScene.Close();
         m_lastScene = null;
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Reimports the USD scene, either fully rebuilding every object or updating them in-place.
        /// </summary>
        /// <param name="forceRebuild">Destroys each GameObject before reimporting.</param>
        public void Reload(bool forceRebuild)
        {
            var options = new SceneImportOptions();

            StateToOptions(ref options);

            options.forceRebuild = forceRebuild;

            if (string.IsNullOrEmpty(options.projectAssetPath))
            {
                options.projectAssetPath = "Assets/";
                OptionsToState(options);
            }

            var root = gameObject;

            string assetPath = GetPrefabAssetPath(root);

            // The prefab asset path will be null for prefab instances.
            // When the assetPath is not null, the object is the prefab itself.
            if (!string.IsNullOrEmpty(assetPath))
            {
                if (options.forceRebuild)
                {
                    DestroyAllImportedObjects();
                }

                SceneImporter.ImportUsd(root, GetScene(), new PrimMap(), options);

#if UNITY_EDITOR
                string clipName = Path.GetFileNameWithoutExtension(usdFullPath);
                // As an optimization, we could detect if any meshes or materials were created and only
                // rebuild the prefab in those cases.
                SceneImporter.SavePrefab(root, assetPath, clipName, options);
#endif
            }
            else
            {
                // An instance of a prefab or a vanilla game object.
                // Just reload the scene into memory and let the user decide if they want to send those
                // changes back to the prefab or not.

                if (forceRebuild)
                {
                    // First, destroy all existing USD game objects.
                    DestroyAllImportedObjects();
                }

                m_lastScene      = null;
                m_lastPrimMap    = null;
                m_lastAccessMask = null;

                SceneImporter.ImportUsd(root, GetScene(), new PrimMap(), options);
            }
        }
Esempio n. 8
0
        // Creates ancestors, but note that this method does not apply visibility, since it was
        // designed to create bones, which cannot have visibility opinions in USD.
        static void CreateAncestors(SdfPath path,
                                    PrimMap map,
                                    GameObject unityRoot,
                                    SdfPath usdRoot,
                                    SceneImportOptions options,
                                    out GameObject parentGo)
        {
            var parentPath = path.GetParentPath();

            if (path == parentPath)
            {
                Debug.LogException(new Exception("Parent path was identical to current path: " + path.ToString()));
                parentGo = null;
                return;
            }

            if (map.TryGetValue(parentPath, out parentGo) && parentGo)
            {
                return;
            }

            // Base case.
            if (parentPath == usdRoot)
            {
                map[parentPath] = unityRoot;
                return;
            }

            if (parentPath == kAbsoluteRootPath)
            {
                // Something went wrong.
                Debug.LogException(new Exception(
                                       "Error: unexpected path </> creating ancestors for <" + usdRoot.ToString() + ">"));
            }

            // Recursive case.
            // First, get the grandparent (parent's parent).
            GameObject grandparentGo;

            CreateAncestors(parentPath, map, unityRoot, usdRoot, options, out grandparentGo);
            if (!grandparentGo)
            {
                Debug.LogError("Failed to find ancestor for " + parentPath);
                return;
            }

            // Then find/create the current parent.
            parentGo = FindOrCreateGameObject(grandparentGo.transform,
                                              parentPath,
                                              unityRoot.transform,
                                              map,
                                              options);
        }
        public static void WriteSparseOverrides(Scene scene,
                                                PrimMap primMap,
                                                BasisTransformation changeHandedness,
                                                float tolerance = 0.0001f)
        {
            var oldMode = scene.WriteMode;

            scene.WriteMode = Scene.WriteModes.Over;

            try
            {
                foreach (var path in scene.Find <XformableSample>())
                {
                    GameObject go;
                    if (!primMap.TryGetValue(path, out go))
                    {
                        continue;
                    }

                    var tx    = go.transform;
                    var xfNew = XformSample.FromTransform(tx);
                    var xfOld = new XformSample();

                    scene.Read(path, xfOld);

                    bool areClose = true;
                    for (int i = 0; i < 16; i++)
                    {
                        if (Mathf.Abs(xfNew.transform[i] - xfOld.transform[i]) > tolerance)
                        {
                            areClose = false;
                            break;
                        }
                    }

                    if (areClose)
                    {
                        continue;
                    }

                    if (changeHandedness == BasisTransformation.SlowAndSafe)
                    {
                        xfNew.ConvertTransform();
                    }

                    scene.Write(path, xfNew);
                }
            }
            finally
            {
                scene.WriteMode = oldMode;
            }
        }
Esempio n. 10
0
        static HierInfo[] BuildObjectLists(Scene scene,
                                           GameObject unityRoot,
                                           SdfPath usdRoot,
                                           PrimMap map,
                                           SceneImportOptions options)
        {
#if !UNITY_2017
            BeginReading(scene, usdRoot, map, options).Complete();
#else
            BeginReading(scene, usdRoot, map, options);
#endif

            ProcessPaths(ReadHierJob.result, scene, unityRoot, usdRoot, map, options);

            return(ReadHierJob.result);
        }
Esempio n. 11
0
        /// <summary>
        /// Checks for a child named "name" under the given parent, if it exists it is returned,
        /// else a new child is created with this name.
        /// </summary>
        static GameObject FindOrCreateGameObject(Transform parent,
                                                 SdfPath path,
                                                 Transform unityRoot,
                                                 PrimMap primMap,
                                                 SceneImportOptions options)
        {
            Transform  root = null;
            GameObject go   = null;
            string     name = path.GetName();

            if (parent == null)
            {
                go   = GameObject.Find(name);
                root = go ? go.transform : null;
            }
            else
            {
                root = parent.Find(name);
                go   = root ? root.gameObject : null;
            }

            if (!go)
            {
                // TODO: this should really not construct a game object if ImportHierarchy is false,
                // but it requires all downstream code be driven by the primMap instead of finding prims
                // via the usd scene. In addition, this requies the prim map to store lists of prims by
                // type, e.g. cameras, meshes, cubes, etc.
                go = new GameObject(name);
            }

            if (!go.GetComponent <UsdPrimSource>())
            {
                var ua = go.AddComponent <UsdPrimSource>();
                ua.m_usdPrimPath = path.ToString();
            }

            if (parent != null)
            {
                go.transform.SetParent(parent, worldPositionStays: false);
            }

            Profiler.BeginSample("Add to PrimMap");
            primMap[path] = go;
            Profiler.EndSample();
            return(go);
        }
Esempio n. 12
0
        public static void ImportUsd(GameObject goRoot,
                                     Scene scene,
                                     PrimMap primMap,
                                     bool composingSubtree,
                                     SceneImportOptions importOptions)
        {
            if (scene == null)
            {
                throw new ImportException("Null USD Scene");
            }

            scene.SetInterpolation(importOptions.interpolate ?
                                   Scene.InterpolationMode.Linear :
                                   Scene.InterpolationMode.Held);

            SceneImporter.BuildScene(scene,
                                     goRoot,
                                     importOptions,
                                     primMap,
                                     composingSubtree);
        }
Esempio n. 13
0
 /// <summary>
 /// Rebuilds the USD scene as Unity GameObjects, maintaining a mapping from USD to Unity.
 /// </summary>
 public static PrimMap BuildScene(Scene scene,
                                  GameObject root,
                                  SceneImportOptions importOptions,
                                  PrimMap primMap,
                                  bool composingSubtree)
 {
     try {
         Profiler.BeginSample("USD: Build Scene");
         var builder = BuildScene(scene,
                                  root,
                                  importOptions,
                                  primMap,
                                  0,
                                  composingSubtree);
         while (builder.MoveNext())
         {
         }
         return(primMap);
     } finally {
         Profiler.EndSample();
     }
 }
Esempio n. 14
0
        /// <summary>
        /// Given an array of bone names (HierInfo.skelJoints), creates GameObjects under unityRoot.
        /// </summary>
        static void ExpandSkeleton(HierInfo info,
                                   GameObject unityRoot,
                                   SdfPath usdRoot,
                                   UsdPrim prim,
                                   PrimMap map,
                                   SceneImportOptions options)
        {
            foreach (var joint in info.skelJoints)
            {
                var        path     = joint;
                GameObject parentGo = null;
                if (!map.TryGetValue(path.GetParentPath(), out parentGo))
                {
                    // This will happen when the joints are discontinuous, for example:
                    //
                    //   Foo/Bar
                    //   Foo/Bar/Baz/Qux
                    //
                    // Baz is implicitly defined, which is allowed by UsdSkel.
                    CreateAncestors(path, map, unityRoot, usdRoot, options, out parentGo);
                    if (!parentGo)
                    {
                        Debug.LogException(new Exception("Failed to create ancestors for " + path + " for prim: " +
                                                         prim.GetPath()));
                        continue;
                    }
                }

                Transform child = parentGo.transform.Find(path.GetName());
                if (!child)
                {
                    child = new GameObject(path.GetName()).transform;
                    child.SetParent(parentGo.transform, worldPositionStays: false);
                }

                map[path] = child.gameObject;
            }
        }
Esempio n. 15
0
        static void ProcessPaths(HierInfo[] infos,
                                 Scene scene,
                                 GameObject unityRoot,
                                 SdfPath usdRoot,
                                 PrimMap map,
                                 SceneImportOptions options)
        {
            Profiler.BeginSample("Process all paths");
            foreach (var info in infos)
            {
                var prim = info.prim;
                var path = info.prim.GetPath();

                if (info.skelBindings != null)
                {
                    // Collect all discovered skelBindings back into the PrimMap.
                    map.SkelBindings.Add(info.prim.GetPath(), info.skelBindings);
                }

                GameObject go;
                if (path == usdRoot)
                {
                    go = unityRoot;
                }
                else
                {
                    GameObject parentGo = null;
                    CreateAncestors(path, map, unityRoot, usdRoot, options, out parentGo);

                    if (!parentGo)
                    {
                        Debug.LogWarning("Parent path not found for child: " + path.ToString());
                        continue;
                    }

                    var parent = parentGo ? parentGo.transform : null;
                    if (!map.TryGetValue(path, out go))
                    {
                        go = FindOrCreateGameObject(parent,
                                                    path,
                                                    unityRoot.transform,
                                                    map,
                                                    options);
                    }
                }

                if (options.importSceneInstances)
                {
                    Profiler.BeginSample("Add Scene Instance Root");
                    if (prim.IsInstance())
                    {
                        map.AddInstanceRoot(prim.GetPath(), go, prim.GetMaster().GetPath());
                    }
                    Profiler.EndSample();
                }

                if (!options.importHierarchy)
                {
                    continue;
                }

                ApplySelfVisibility(go, prim);

                try {
                    Profiler.BeginSample("Add Model Root");
                    AddModelRoot(go, info);
                    Profiler.EndSample();

                    Profiler.BeginSample("Add Variant Set");
                    AddVariantSet(go, prim);
                    Profiler.EndSample();

                    Profiler.BeginSample("Add Payload");
                    AddPayload(go, info, options);
                    Profiler.EndSample();
                } catch (Exception ex) {
                    Debug.LogException(new Exception("Error processing " + prim.GetPath(), ex));
                }
            }
            Profiler.EndSample();
        }
Esempio n. 16
0
        /// <summary>
        /// Map all UsdPrims and build Unity GameObjects, reconstructing the parent relationship.
        /// </summary>
        /// <remarks>
        /// When forceRebuild is true, game objects will be destroyed and recreated. If buildHierarchy
        /// is false, the primMap will be populated, but missing game objects will not be created.
        /// </remarks>
        static public PrimMap BuildGameObjects(Scene scene,
                                               GameObject unityRoot,
                                               SdfPath usdRoot,
                                               IEnumerable <SdfPath> paths,
                                               PrimMap map,
                                               SceneImportOptions options)
        {
            map[usdRoot] = unityRoot;

            // Like all GameObjects imported from USD, ensure the root has a UsdPrimSource.
            if (unityRoot.GetComponent <UsdPrimSource>() == null)
            {
                var ua = unityRoot.AddComponent <UsdPrimSource>();
                ua.m_usdPrimPath = usdRoot.ToString();
            }

            Profiler.BeginSample("Build Object Lists");
            var hierInfo = BuildObjectLists(scene, unityRoot, usdRoot, map, options);

            Profiler.EndSample();

            // TODO: Should recurse to discover deeply nested instancing.
            // TODO: Generates garbage for every prim, but we expect few masters.
            if (options.importPointInstances || options.importSceneInstances)
            {
                Profiler.BeginSample("Build Masters");
                foreach (var masterRootPrim in scene.Stage.GetMasters())
                {
                    var goMaster = FindOrCreateGameObject(unityRoot.transform,
                                                          masterRootPrim.GetPath(),
                                                          unityRoot.transform,
                                                          map,
                                                          options);

                    goMaster.hideFlags = HideFlags.HideInHierarchy;
                    goMaster.SetActive(false);
                    map.AddMasterRoot(masterRootPrim.GetPath(), goMaster);
                    try {
                        var info = new HierInfo();
                        info.prim = masterRootPrim;
                        ReadModelInfo(ref info);
                        AddModelRoot(goMaster, info);
                        AddVariantSet(goMaster, masterRootPrim);
                    } catch (Exception ex) {
                        Debug.LogException(new Exception("Error processing " + masterRootPrim.GetPath(), ex));
                    }

                    foreach (var usdPrim in masterRootPrim.GetDescendants())
                    {
                        var       parentPath = usdPrim.GetPath().GetParentPath();
                        Transform parentXf   = null;
                        if (parentPath == masterRootPrim.GetPath())
                        {
                            parentXf = goMaster.transform;
                        }
                        else
                        {
                            parentXf = map[parentPath].transform;
                        }

                        var goPrim = FindOrCreateGameObject(parentXf,
                                                            usdPrim.GetPath(),
                                                            unityRoot.transform,
                                                            map,
                                                            options);
                        ApplySelfVisibility(goPrim, usdPrim);

                        if (usdPrim.IsInstance())
                        {
                            map.AddInstanceRoot(usdPrim.GetPath(), goPrim, usdPrim.GetMaster().GetPath());
                        }

                        try {
                            var info = new HierInfo();
                            info.prim = usdPrim;
                            ReadModelInfo(ref info);
                            AddModelRoot(goPrim, info);
                            AddVariantSet(goPrim, usdPrim);
                        } catch (Exception ex) {
                            Debug.LogException(new Exception("Error processing " + usdPrim.GetPath(), ex));
                            continue;
                        }
                    }
                }
                Profiler.EndSample();
            }

            if (options.importSkinning)
            {
                Profiler.BeginSample("Expand Skeletons");
                foreach (var info in hierInfo)
                {
                    if (info.skelJoints == null || info.skelJoints.Length == 0)
                    {
                        continue;
                    }

                    try {
                        ExpandSkeleton(info, unityRoot, usdRoot, info.prim, map, options);
                    } catch (Exception ex) {
                        Debug.LogException(new Exception("Error expanding skeleton at " + info.prim.GetPath(), ex));
                    }
                }
                Profiler.EndSample();
            }

            return(map);
        }
Esempio n. 17
0
        static JobHandle BeginReading(Scene scene,
                                      SdfPath usdRoot,
                                      PrimMap map,
                                      SceneImportOptions options)
        {
            FindPathsJob.usdRoot = usdRoot;
            FindPathsJob.scene   = scene;
            FindPathsJob.results = new SdfPath[9][];
            FindPathsJob.queries = new FindPathsJob.IQuery[9];

            if (options.ShouldBindMaterials)
            {
                FindPathsJob.queries[0] = (FindPathsJob.IQuery) new FindPathsJob.Query <MaterialSample>();
            }

            if (options.importCameras)
            {
                FindPathsJob.queries[1] = (FindPathsJob.IQuery) new FindPathsJob.Query <CameraSample>();
            }

            if (options.importMeshes)
            {
                FindPathsJob.queries[2] = (FindPathsJob.IQuery) new FindPathsJob.Query <MeshSample>();
                FindPathsJob.queries[3] = (FindPathsJob.IQuery) new FindPathsJob.Query <CubeSample>();
                FindPathsJob.queries[4] = (FindPathsJob.IQuery) new FindPathsJob.Query <SphereSample>();
            }

            FindPathsJob.queries[5] = (FindPathsJob.IQuery) new FindPathsJob.Query <SkelRootSample>();

            if (options.importSkinning)
            {
                FindPathsJob.queries[6] = (FindPathsJob.IQuery) new FindPathsJob.Query <SkeletonSample>();
            }

            if (options.importTransforms)
            {
                FindPathsJob.queries[7] = (FindPathsJob.IQuery) new FindPathsJob.Query <XformSample>();
            }

            FindPathsJob.queries[8] = (FindPathsJob.IQuery) new FindPathsJob.Query <ScopeSample>();

            var findPathsJob = new FindPathsJob();
            var findHandle   = findPathsJob.Schedule(FindPathsJob.queries.Length, 1);

            findHandle.Complete();

            // Note that Scope prims are taken into account when building the hierarchy but not added to the PrimMap
            // This is because Scopes don't need specific import/export logic for now:
            //   * they don't hold any data ton convert on the way in
            //   * being represented as Xforms in Unity they get automatically exported (as Xform) as part of the parent hierarchy of any
            //     valid prim
            // This will need to change if/when we want proper round tripping.
            map.Materials = FindPathsJob.results[0];
            map.Cameras   = FindPathsJob.results[1];
            map.Meshes    = FindPathsJob.results[2];
            map.Cubes     = FindPathsJob.results[3];
            map.Spheres   = FindPathsJob.results[4];
            map.SkelRoots = FindPathsJob.results[5];
            map.Skeletons = FindPathsJob.results[6];
            map.Xforms    = FindPathsJob.results[7];

            ReadHierJob.paths     = FindPathsJob.results.Where(i => i != null).SelectMany(i => i).ToArray();
            ReadHierJob.result    = new HierInfo[ReadHierJob.paths.Length];
            ReadHierJob.scene     = scene;
            ReadHierJob.skelCache = map.SkelCache;
            var readHierInfo = new ReadHierJob();

            return(readHierInfo.Schedule(ReadHierJob.paths.Length, 8, dependsOn: findHandle));
        }
Esempio n. 18
0
        BeginReading(Scene scene,
                     SdfPath usdRoot,
                     PrimMap map,
                     SceneImportOptions options)
        {
            FindPathsJob.usdRoot = usdRoot;
            FindPathsJob.scene   = scene;
            FindPathsJob.results = new SdfPath[8][];
            FindPathsJob.queries = new FindPathsJob.IQuery[8];

            if (options.ShouldBindMaterials)
            {
                FindPathsJob.queries[0] = (FindPathsJob.IQuery) new FindPathsJob.Query <MaterialSample>();
            }
            if (options.importCameras)
            {
                FindPathsJob.queries[1] = (FindPathsJob.IQuery) new FindPathsJob.Query <CameraSample>();
            }
            if (options.importMeshes)
            {
                FindPathsJob.queries[2] = (FindPathsJob.IQuery) new FindPathsJob.Query <MeshSample>();
                FindPathsJob.queries[3] = (FindPathsJob.IQuery) new FindPathsJob.Query <CubeSample>();
                FindPathsJob.queries[4] = (FindPathsJob.IQuery) new FindPathsJob.Query <SphereSample>();
            }

            FindPathsJob.queries[5] = (FindPathsJob.IQuery) new FindPathsJob.Query <SkelRootSample>();

            if (options.importSkinning)
            {
                FindPathsJob.queries[6] = (FindPathsJob.IQuery) new FindPathsJob.Query <SkeletonSample>();
            }
            if (options.importTransforms)
            {
                FindPathsJob.queries[7] = (FindPathsJob.IQuery) new FindPathsJob.Query <XformSample>();
            }

            var findPathsJob = new FindPathsJob();

#if !UNITY_2017
            var findHandle = findPathsJob.Schedule(FindPathsJob.queries.Length, 1);
            findHandle.Complete();
#else
            findPathsJob.Run();
#endif

            map.Materials = FindPathsJob.results[0];
            map.Cameras   = FindPathsJob.results[1];
            map.Meshes    = FindPathsJob.results[2];
            map.Cubes     = FindPathsJob.results[3];
            map.Spheres   = FindPathsJob.results[4];
            map.SkelRoots = FindPathsJob.results[5];
            map.Skeletons = FindPathsJob.results[6];
            map.Xforms    = FindPathsJob.results[7];

            ReadHierJob.paths     = FindPathsJob.results.Where(i => i != null).SelectMany(i => i).ToArray();
            ReadHierJob.result    = new HierInfo[ReadHierJob.paths.Length];
            ReadHierJob.scene     = scene;
            ReadHierJob.skelCache = map.SkelCache;
            var readHierInfo = new ReadHierJob();
#if !UNITY_2017
            return(readHierInfo.Schedule(ReadHierJob.paths.Length, 8, dependsOn: findHandle));
#else
            readHierInfo.Run();
            return;
#endif
        }
Esempio n. 19
0
        public static void BuildSkinnedMesh(string meshPath,
                                            string skelPath,
                                            SkeletonSample skeleton,
                                            UsdSkelSkinningQuery skinningQuery,
                                            GameObject go,
                                            PrimMap primMap,
                                            SceneImportOptions options)
        {
            // The mesh renderer must already exist, since hte mesh also must already exist.
            var smr = go.GetComponent <SkinnedMeshRenderer>();

            if (!smr)
            {
                throw new Exception(
                          "Error importing "
                          + meshPath
                          + " SkinnnedMeshRenderer not present on GameObject"
                          );
            }

            // Get and validate the joint weights and indices informations.
            UsdGeomPrimvar jointWeights = skinningQuery.GetJointWeightsPrimvar();
            UsdGeomPrimvar jointIndices = skinningQuery.GetJointIndicesPrimvar();

            if (!jointWeights.IsDefined() || !jointIndices.IsDefined())
            {
                throw new Exception("Joints information (indices and/or weights) are missing for: " + meshPath);
            }

            // TODO: Both indices and weights attributes can be animated. It's not handled yet.
            // TODO: Having something that convert a UsdGeomPrimvar into a PrimvarSample could help simplify this code.
            int[] indices            = IntrinsicTypeConverter.FromVtArray((VtIntArray)jointIndices.GetAttr().Get());
            int   indicesElementSize = jointIndices.GetElementSize();

            pxr.TfToken indicesInterpolation = jointIndices.GetInterpolation();

            if (indices.Length == 0 ||
                indicesElementSize == 0 ||
                indices.Length % indicesElementSize != 0 ||
                !pxr.UsdGeomPrimvar.IsValidInterpolation(indicesInterpolation))
            {
                throw new Exception("Joint indices information are invalid or empty for: " + meshPath);
            }

            float[] weights            = IntrinsicTypeConverter.FromVtArray((VtFloatArray)jointWeights.GetAttr().Get());
            int     weightsElementSize = jointWeights.GetElementSize();

            pxr.TfToken weightsInterpolation = jointWeights.GetInterpolation();

            if (weights.Length == 0 ||
                weightsElementSize == 0 ||
                weights.Length % weightsElementSize != 0 ||
                !pxr.UsdGeomPrimvar.IsValidInterpolation(weightsInterpolation))
            {
                throw new Exception("Joints weights information are invalid or empty for: " + meshPath);
            }

            // Get and validate the local list of joints.
            VtTokenArray jointsAttr = new VtTokenArray();

            skinningQuery.GetJointOrder(jointsAttr);

            // If jointsAttr wasn't define, GetJointOrder return an empty array and FromVtArray as well.
            string[] joints = IntrinsicTypeConverter.FromVtArray(jointsAttr);

            // WARNING: Do not mutate skeleton values.
            string[] skelJoints = skeleton.joints;

            if (joints == null || joints.Length == 0)
            {
                if (skelJoints == null || skelJoints.Length == 0)
                {
                    throw new Exception("Joints array empty: " + meshPath);
                }
                else
                {
                    joints = skelJoints;
                }
            }

            var mesh = smr.sharedMesh;

            // TODO: bind transform attribute can be animated. It's not handled yet.
            Matrix4x4 geomXf = UnityTypeConverter.FromMatrix(skinningQuery.GetGeomBindTransform());

            // If the joints list is a different length than the bind transforms, then this is likely
            // a mesh using a subset of the total bones in the skeleton and the bindTransforms must be
            // reconstructed.
            var bindPoses = skeleton.bindTransforms;

            if (!JointsMatch(skeleton.joints, joints))
            {
                var boneToPose = new Dictionary <string, Matrix4x4>();
                bindPoses = new Matrix4x4[joints.Length];
                for (int i = 0; i < skelJoints.Length; i++)
                {
                    boneToPose[skelJoints[i]] = skeleton.bindTransforms[i];
                }
                for (int i = 0; i < joints.Length; i++)
                {
                    bindPoses[i] = boneToPose[joints[i]];
                }
            }

            // When geomXf is identity, we can take a shortcut and just use the exact skeleton bindPoses.
            if (!ImporterBase.ApproximatelyEqual(geomXf, Matrix4x4.identity))
            {
                // Note that the bind poses were transformed when the skeleton was imported, but the
                // geomBindTransform is per-mesh, so it must be transformed here so it is in the same space
                // as the bind pose.
                XformImporter.ImportXform(ref geomXf, options);

                // Make a copy only if we haven't already copied the bind poses earlier.
                if (bindPoses == skeleton.bindTransforms)
                {
                    var newBindPoses = new Matrix4x4[skeleton.bindTransforms.Length];
                    Array.Copy(bindPoses, newBindPoses, bindPoses.Length);
                    bindPoses = newBindPoses;
                }

                // Concatenate the geometry bind transform with the skeleton bind poses.
                for (int i = 0; i < bindPoses.Length; i++)
                {
                    // The geometry transform should be applied to the points before any other transform,
                    // hence the right hand multiply here.
                    bindPoses[i] = bindPoses[i] * geomXf;
                }
            }
            mesh.bindposes = bindPoses;

            var bones       = new Transform[joints.Length];
            var sdfSkelPath = new SdfPath(skelPath);

            for (int i = 0; i < joints.Length; i++)
            {
                var jointPath = new SdfPath(joints[i]);

                if (joints[i] == "/")
                {
                    jointPath = sdfSkelPath;
                }
                else if (jointPath.IsAbsolutePath())
                {
                    Debug.LogException(new Exception("Unexpected absolute joint path: " + jointPath));
                    jointPath = new SdfPath(joints[i].TrimStart('/'));
                    jointPath = sdfSkelPath.AppendPath(jointPath);
                }
                else
                {
                    jointPath = sdfSkelPath.AppendPath(jointPath);
                }
                var jointGo = primMap[jointPath];
                if (!jointGo)
                {
                    Debug.LogError("Error importing " + meshPath + " "
                                   + "Joint not found: " + joints[i]);
                    continue;
                }
                bones[i] = jointGo.transform;
            }
            smr.bones = bones;

            bool isConstant = weightsInterpolation.GetString() == pxr.UsdGeomTokens.constant;

            // Unity 2019 supports many-bone rigs, older versions of Unity only support four bones.
#if UNITY_2019
            var bonesPerVertex = new NativeArray <byte>(mesh.vertexCount, Allocator.Persistent);
            var boneWeights1   = new NativeArray <BoneWeight1>(mesh.vertexCount * weightsElementSize, Allocator.Persistent);
            for (int i = 0; i < mesh.vertexCount; i++)
            {
                int unityIndex = i * weightsElementSize;
                int usdIndex   = isConstant
                     ? 0
                     : unityIndex;

                bonesPerVertex[i] = (byte)weightsElementSize;

                for (int wi = 0; wi < weightsElementSize; wi++)
                {
                    var bw = boneWeights1[unityIndex + wi];
                    bw.boneIndex = indices[usdIndex + wi];
                    bw.weight    = weights[usdIndex + wi];
                    boneWeights1[unityIndex + wi] = bw;
                }
            }
            // TODO: Investigate if bone weights should be normalized before this line.
            mesh.SetBoneWeights(bonesPerVertex, boneWeights1);
            bonesPerVertex.Dispose();
            boneWeights1.Dispose();
#else
            var boneWeights = new BoneWeight[mesh.vertexCount];
            for (int i = 0; i < boneWeights.Length; i++)
            {
                // When interpolation is constant, the base usdIndex should always be zero.
                // When non-constant, the offset is the index times the number of weights per vertex.
                int usdIndex = isConstant
                     ? 0
                     : i * weightsElementSize;

                var boneWeight = boneWeights[i];

                if (usdIndex >= indices.Length)
                {
                    Debug.Log("UsdIndex out of bounds: " + usdIndex
                              + " indices.Length: " + indices.Length
                              + " boneWeights.Length: " + boneWeights.Length
                              + " mesh: " + meshPath);
                }

                boneWeight.boneIndex0 = indices[usdIndex];
                boneWeight.weight0    = weights[usdIndex];

                if (indicesElementSize >= 2)
                {
                    boneWeight.boneIndex1 = indices[usdIndex + 1];
                    boneWeight.weight1    = weights[usdIndex + 1];
                }
                if (indicesElementSize >= 3)
                {
                    boneWeight.boneIndex2 = indices[usdIndex + 2];
                    boneWeight.weight2    = weights[usdIndex + 2];
                }
                if (indicesElementSize >= 4)
                {
                    boneWeight.boneIndex3 = indices[usdIndex + 3];
                    boneWeight.weight3    = weights[usdIndex + 3];
                }

                // If weights are less than 1, Unity will not automatically renormalize.
                // If weights are greater than 1, Unity will renormalize.
                // Only normalize when less than one to make it easier to diff bone weights which were
                // round-tripped and were being normalized by Unity.
                float sum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3;
                if (sum < 1)
                {
                    boneWeight.weight0 /= sum;
                    boneWeight.weight1 /= sum;
                    boneWeight.weight2 /= sum;
                    boneWeight.weight3 /= sum;
                }

                boneWeights[i] = boneWeight;
            }

            mesh.boneWeights = boneWeights;
#endif
        }
Esempio n. 20
0
        public static void BuildSkinnedMesh(string meshPath,
                                            string skelPath,
                                            SkeletonSample skeleton,
                                            SkelBindingSample meshBinding,
                                            GameObject go,
                                            PrimMap primMap,
                                            SceneImportOptions options)
        {
            string[] joints = meshBinding.joints;

            // WARNING: Do not mutate skeleton values.
            string[] skelJoints = skeleton.joints;
            bool     isConstant = meshBinding.jointWeights.interpolation == PrimvarInterpolation.Constant;

            if (joints == null || joints.Length == 0)
            {
                if (skelJoints == null || skelJoints.Length == 0)
                {
                    throw new Exception("Joints array empty: " + meshPath);
                }
                else
                {
                    joints = skelJoints;
                }
            }

            // The mesh renderer must already exist, since hte mesh also must already exist.
            var smr = go.GetComponent <SkinnedMeshRenderer>();

            if (!smr)
            {
                throw new Exception("Error importing " + meshPath
                                    + " SkinnnedMeshRenderer not present on GameObject");
            }

            var mesh   = smr.sharedMesh;
            var geomXf = meshBinding.geomBindTransform.value;

            // If the joints list is a different length than the bind transforms, then this is likely
            // a mesh using a subset of the total bones in the skeleton and the bindTransforms must be
            // reconstructed.
            var bindPoses = skeleton.bindTransforms;

            if (!JointsMatch(skeleton.joints, joints))
            {
                var boneToPose = new Dictionary <string, Matrix4x4>();
                bindPoses = new Matrix4x4[joints.Length];
                for (int i = 0; i < skelJoints.Length; i++)
                {
                    boneToPose[skelJoints[i]] = skeleton.bindTransforms[i];
                }
                for (int i = 0; i < joints.Length; i++)
                {
                    bindPoses[i] = boneToPose[joints[i]];
                }
            }

            // When geomXf is identity, we can take a shortcut and just use the exact skeleton bindPoses.
            if (!ImporterBase.ApproximatelyEqual(geomXf, Matrix4x4.identity))
            {
                // Note that the bind poses were transformed when the skeleton was imported, but the
                // geomBindTransform is per-mesh, so it must be transformed here so it is in the same space
                // as the bind pose.
                XformImporter.ImportXform(ref geomXf, options);

                // Make a copy only if we haven't already copied the bind poses earlier.
                if (bindPoses == skeleton.bindTransforms)
                {
                    var newBindPoses = new Matrix4x4[skeleton.bindTransforms.Length];
                    Array.Copy(bindPoses, newBindPoses, bindPoses.Length);
                    bindPoses = newBindPoses;
                }

                // Concatenate the geometry bind transform with the skeleton bind poses.
                for (int i = 0; i < bindPoses.Length; i++)
                {
                    // The geometry transform should be applied to the points before any other transform,
                    // hence the right hand multiply here.
                    bindPoses[i] = bindPoses[i] * geomXf;
                }
            }
            mesh.bindposes = bindPoses;

            var bones       = new Transform[joints.Length];
            var sdfSkelPath = new SdfPath(skelPath);

            for (int i = 0; i < joints.Length; i++)
            {
                var jointPath = new SdfPath(joints[i]);

                if (joints[i] == "/")
                {
                    jointPath = sdfSkelPath;
                }
                else if (jointPath.IsAbsolutePath())
                {
                    Debug.LogException(new Exception("Unexpected absolute joint path: " + jointPath));
                    jointPath = new SdfPath(joints[i].TrimStart('/'));
                    jointPath = sdfSkelPath.AppendPath(jointPath);
                }
                else
                {
                    jointPath = sdfSkelPath.AppendPath(jointPath);
                }
                var jointGo = primMap[jointPath];
                if (!jointGo)
                {
                    Debug.LogError("Error importing " + meshPath + " "
                                   + "Joint not found: " + joints[i]);
                    continue;
                }
                bones[i] = jointGo.transform;
            }
            smr.bones = bones;

            int[]   indices = meshBinding.jointIndices.value;
            float[] weights = meshBinding.jointWeights.value;

            // Unity 2019 supports many-bone rigs, older versions of Unity only support four bones.
#if UNITY_2019
            var bonesPerVertex = new NativeArray <byte>(mesh.vertexCount, Allocator.Persistent);
            var boneWeights1   = new NativeArray <BoneWeight1>(mesh.vertexCount * meshBinding.jointWeights.elementSize, Allocator.Persistent);
            for (int i = 0; i < mesh.vertexCount; i++)
            {
                int unityIndex = i * meshBinding.jointWeights.elementSize;
                int usdIndex   = isConstant
                     ? 0
                     : unityIndex;

                bonesPerVertex[i] = (byte)meshBinding.jointWeights.elementSize;

                for (int wi = 0; wi < meshBinding.jointWeights.elementSize; wi++)
                {
                    var bw = boneWeights1[unityIndex + wi];
                    bw.boneIndex = indices[usdIndex + wi];
                    bw.weight    = weights[usdIndex + wi];
                    boneWeights1[unityIndex + wi] = bw;
                }
            }
            mesh.SetBoneWeights(bonesPerVertex, boneWeights1);
            bonesPerVertex.Dispose();
            boneWeights1.Dispose();
#else
            var boneWeights = new BoneWeight[mesh.vertexCount];
            for (int i = 0; i < boneWeights.Length; i++)
            {
                // When interpolation is constant, the base usdIndex should always be zero.
                // When non-constant, the offset is the index times the number of weights per vertex.
                int usdIndex = isConstant
                     ? 0
                     : i * meshBinding.jointWeights.elementSize;

                var boneWeight = boneWeights[i];

                if (usdIndex >= indices.Length)
                {
                    Debug.Log("UsdIndex out of bounds: " + usdIndex
                              + " indices.Length: " + indices.Length
                              + " boneWeights.Length: " + boneWeights.Length
                              + " mesh: " + meshPath);
                }

                boneWeight.boneIndex0 = indices[usdIndex];
                boneWeight.weight0    = weights[usdIndex];

                if (meshBinding.jointIndices.elementSize >= 2)
                {
                    boneWeight.boneIndex1 = indices[usdIndex + 1];
                    boneWeight.weight1    = weights[usdIndex + 1];
                }
                if (meshBinding.jointIndices.elementSize >= 3)
                {
                    boneWeight.boneIndex2 = indices[usdIndex + 2];
                    boneWeight.weight2    = weights[usdIndex + 2];
                }
                if (meshBinding.jointIndices.elementSize >= 4)
                {
                    boneWeight.boneIndex3 = indices[usdIndex + 3];
                    boneWeight.weight3    = weights[usdIndex + 3];
                }

                // If weights are less than 1, Unity will not automatically renormalize.
                // If weights are greater than 1, Unity will renormalize.
                // Only normalize when less than one to make it easier to diff bone weights which were
                // round-tripped and were being normalized by Unity.
                float sum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3;
                if (sum < 1)
                {
                    boneWeight.weight0 /= sum;
                    boneWeight.weight1 /= sum;
                    boneWeight.weight2 /= sum;
                    boneWeight.weight3 /= sum;
                }

                boneWeights[i] = boneWeight;
            }

            mesh.boneWeights = boneWeights;
#endif
        }
Esempio n. 21
0
 /// <summary>
 /// Clear internal data.
 /// Call to <see cref="GetScene">GetScene()</see> to update them with the latest USD data.
 /// </summary>
 private void ClearLastData()
 {
     m_lastScene      = null;
     m_lastPrimMap    = null;
     m_lastAccessMask = null;
 }
Esempio n. 22
0
        public static void BuildPointInstances(Scene scene,
                                               PrimMap primMap,
                                               string pointInstancerPath,
                                               PointInstancerSample sample,
                                               GameObject root,
                                               SceneImportOptions options)
        {
            Matrix4x4[] transforms = sample.ComputeInstanceMatrices(scene, pointInstancerPath);
            int         i          = 0;

            foreach (var protoRoot in sample.prototypes.targetPaths)
            {
                GameObject go;
                if (!primMap.TryGetValue(new pxr.SdfPath(protoRoot), out go))
                {
                    Debug.LogWarning("Proto not found in PrimMap: " + protoRoot);
                    continue;
                }

                go.SetActive(false);
                if (options.enableGpuInstancing)
                {
                    EnableGpuInstancing(go);
                }
            }

            var inactiveIds = new System.Collections.Generic.HashSet <long>();

            /*
             * Disabled until this bug is resolved:
             * https://github.com/PixarAnimationStudios/USD/issues/639
             *
             * if (sample.inactiveIds != null) {
             * foreach (long id in sample.inactiveIds.GetExplicitItems()) {
             *  inactiveIds.Add(id);
             * }
             * }
             */

            foreach (var index in sample.protoIndices)
            {
                if (inactiveIds.Contains(index))
                {
                    continue;
                }

                if (index >= sample.prototypes.targetPaths.Length)
                {
                    Debug.LogWarning("ProtoIndex out of bounds: [" + index + "] " +
                                     "for instancer: " + pointInstancerPath);
                    continue;
                }

                var targetPath = sample.prototypes.targetPaths[index];

                GameObject goMaster;
                if (!primMap.TryGetValue(new pxr.SdfPath(targetPath), out goMaster))
                {
                    Debug.LogWarning("Proto not found in PrimMap: " + targetPath);
                    continue;
                }

                if (i >= transforms.Length)
                {
                    Debug.LogWarning("No transform for instance index [" + i + "] " +
                                     "for instancer: " + pointInstancerPath);
                    break;
                }

                var xf         = transforms[i];
                var goInstance = GameObject.Instantiate(goMaster, root.transform);
                goInstance.SetActive(true);
                goInstance.name = goMaster.name + "_" + i;
                XformImporter.BuildXform(xf, goInstance, options);

                i++;
            }
        }
Esempio n. 23
0
 public void BeginReading(Scene scene, PrimMap primMap)
 {
     m_readMeshesJob = new ReadAllJob <MeshSample>(scene, primMap.Meshes);
     m_readMeshesJob.Schedule(primMap.Meshes.Length, 2);
 }
Esempio n. 24
0
        /// <summary>
        /// Rebuilds the USD scene as Unity GameObjects, with a limited budget per update.
        /// </summary>
        public static IEnumerator BuildScene(Scene scene,
                                             GameObject root,
                                             SceneImportOptions importOptions,
                                             PrimMap primMap,
                                             float targetFrameMilliseconds,
                                             bool composingSubtree)
        {
            var timer       = new System.Diagnostics.Stopwatch();
            var usdPrimRoot = new pxr.SdfPath(importOptions.usdRootPath);

            // Setting an arbitrary fudge factor of 20% is very non-scientific, however it's better than
            // nothing. The correct way to hit a deadline is to predict how long each iteration actually
            // takes and then return early if the estimated time is over budget.
            float targetTime = targetFrameMilliseconds * .8f;

            timer.Start();

            // Reconstruct the USD hierarchy as Unity GameObjects.
            // A PrimMap is returned for tracking the USD <-> Unity mapping.
            Profiler.BeginSample("USD: Build Hierarchy");
            if (importOptions.importHierarchy || importOptions.forceRebuild)
            {
                // When a USD file is fully RE-imported, all exsiting USD data must be removed. The old
                // assumption was that the root would never have much more than the UsdAsset component
                // itself, however it's now clear that the root may also have meaningful USD data added
                // too.
                //
                // TODO(jcowles): This feels like a workaround. What we really want here is an "undo"
                // process for changes made to the root GameObject. For example, to clean up non-USD
                // components which may have been added (e.g. what if a mesh is imported to the root?
                // currently the MeshRenderer etc will remain after re-import).
                RemoveComponent <UsdAssemblyRoot>(root);
                RemoveComponent <UsdVariantSet>(root);
                RemoveComponent <UsdModelRoot>(root);
                RemoveComponent <UsdLayerStack>(root);
                RemoveComponent <UsdPayload>(root);
                RemoveComponent <UsdPrimSource>(root);

                primMap.Clear();
                HierarchyBuilder.BuildGameObjects(scene,
                                                  root,
                                                  usdPrimRoot,
                                                  scene.Find(usdPrimRoot.ToString(), "UsdSchemaBase"),
                                                  primMap,
                                                  importOptions);
            }
            Profiler.EndSample();

            if (ShouldYield(targetTime, timer))
            {
                yield return(null); ResetTimer(timer);
            }

            Profiler.BeginSample("USD: Post Process Hierarchy");
            foreach (var processor in root.GetComponents <IImportPostProcessHierarchy>())
            {
                try {
                    processor.PostProcessHierarchy(primMap, importOptions);
                } catch (System.Exception ex) {
                    Debug.LogException(ex);
                }
            }
            Profiler.EndSample();

            if (ShouldYield(targetTime, timer))
            {
                yield return(null); ResetTimer(timer);
            }

            //
            // Pre-process UsdSkelRoots.
            //

            var skelRoots = new List <pxr.UsdSkelRoot>();

            if (importOptions.importSkinning)
            {
                Profiler.BeginSample("USD: Process UsdSkelRoots");
                foreach (var path in primMap.SkelRoots)
                {
                    try {
                        var skelRootPrim = scene.GetPrimAtPath(path);
                        if (!skelRootPrim)
                        {
                            Debug.LogWarning("SkelRoot prim not found: " + path);
                            continue;
                        }
                        var skelRoot = new pxr.UsdSkelRoot(skelRootPrim);
                        if (!skelRoot)
                        {
                            Debug.LogWarning("SkelRoot prim not SkelRoot type: " + path);
                            continue;
                        }

                        skelRoots.Add(skelRoot);
                        GameObject go = primMap[path];
                        ImporterBase.GetOrAddComponent <Animator>(go, true);
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error pre-processing SkelRoot <" + path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();
            }

            //
            // Import known prim types.
            //

            // Materials.
            Profiler.BeginSample("USD: Build Materials");
            if (importOptions.ShouldBindMaterials)
            {
                foreach (var pathAndSample in scene.ReadAll <MaterialSample>(primMap.Materials))
                {
                    try {
                        var mat = MaterialImporter.BuildMaterial(scene,
                                                                 pathAndSample.path,
                                                                 pathAndSample.sample,
                                                                 importOptions);
                        if (mat != null)
                        {
                            importOptions.materialMap[pathAndSample.path] = mat;
                        }
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing material <" + pathAndSample.path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
            }
            Profiler.EndSample();

            //
            // Start threads.
            //
            ReadAllJob <XformSample> readXforms;

            if (importOptions.importTransforms)
            {
                readXforms = new ReadAllJob <XformSample>(scene, primMap.Xforms);
#if UNITY_2018_1_OR_NEWER
                readXforms.Schedule(primMap.Xforms.Length, 4);
#else
                readXforms.Run();
#endif
            }
            if (importOptions.importMeshes)
            {
                ActiveMeshImporter.BeginReading(scene, primMap);
            }
#if UNITY_2018_1_OR_NEWER
            JobHandle.ScheduleBatchedJobs();
#endif


            // Xforms.
            //
            // Note that we are specifically filtering on XformSample, not Xformable, this way only
            // Xforms are processed to avoid doing that work redundantly.
            if (importOptions.importTransforms)
            {
                Profiler.BeginSample("USD: Build Xforms");
                foreach (var pathAndSample in readXforms)
                {
                    try {
                        if (pathAndSample.path == usdPrimRoot)
                        {
                            // Never read the xform from the USD root, that will be authored in Unity.
                            continue;
                        }
                        GameObject go = primMap[pathAndSample.path];
                        NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                        XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }

                foreach (var pathAndSample in scene.ReadAll <XformSample>(primMap.SkelRoots))
                {
                    try {
                        if (pathAndSample.path == usdPrimRoot)
                        {
                            // Never read the xform from the USD root, that will be authored in Unity.
                            continue;
                        }
                        GameObject go = primMap[pathAndSample.path];
                        NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                        XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }

                if (importOptions.importSkinning)
                {
                    foreach (var pathAndSample in scene.ReadAll <XformSample>(primMap.Skeletons))
                    {
                        try {
                            if (pathAndSample.path == usdPrimRoot)
                            {
                                // Never read the xform from the USD root, that will be authored in Unity.
                                continue;
                            }
                            GameObject go = primMap[pathAndSample.path];
                            NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                            XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                        } catch (System.Exception ex) {
                            Debug.LogException(
                                new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                        }

                        if (ShouldYield(targetTime, timer))
                        {
                            yield return(null); ResetTimer(timer);
                        }
                    }
                }

                Profiler.EndSample();
            }

            // Meshes.
            if (importOptions.importMeshes)
            {
                Profiler.BeginSample("USD: Build Meshes");
                IEnumerator it = ActiveMeshImporter.Import(scene, primMap, importOptions);

                while (it.MoveNext())
                {
                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();

                // Cubes.
                Profiler.BeginSample("USD: Build Cubes");
                foreach (var pathAndSample in scene.ReadAll <CubeSample>(primMap.Cubes))
                {
                    try {
                        GameObject go = primMap[pathAndSample.path];
                        NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                        XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                        CubeImporter.BuildCube(pathAndSample.sample, go, importOptions);
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing cube <" + pathAndSample.path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();
            }

            // Cameras.
            if (importOptions.importCameras)
            {
                Profiler.BeginSample("USD: Cameras");
                foreach (var pathAndSample in scene.ReadAll <CameraSample>(primMap.Cameras))
                {
                    try {
                        GameObject go = primMap[pathAndSample.path];
                        NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                        XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);

                        // The camera has many value-type parameters that need to be handled correctly when not
                        // not animated. For now, only the camera transform will animate, until this is fixed.
                        if (scene.AccessMask == null || scene.IsPopulatingAccessMask)
                        {
                            CameraImporter.BuildCamera(pathAndSample.sample, go, importOptions);
                        }
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing camera <" + pathAndSample.path + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();
            }

            // Build out masters for instancing.
            Profiler.BeginSample("USD: Build Instances");
            foreach (var masterRootPath in primMap.GetMasterRootPaths())
            {
                try {
                    Transform masterRootXf = primMap[masterRootPath].transform;

                    // Transforms
                    if (importOptions.importTransforms)
                    {
                        Profiler.BeginSample("USD: Build Xforms");
                        foreach (var pathAndSample in scene.ReadAll <XformSample>(masterRootPath))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                            }
                        }

                        foreach (var pathAndSample in scene.ReadAll <XformSample>(masterRootPath))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                            }
                        }

                        foreach (var pathAndSample in scene.ReadAll <XformSample>(primMap.Skeletons))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing xform <" + pathAndSample.path + ">", ex));
                            }
                        }
                        Profiler.EndSample();
                    }

                    // Meshes.
                    if (importOptions.importMeshes)
                    {
                        Profiler.BeginSample("USD: Build Meshes");
                        foreach (var pathAndSample in scene.ReadAll <MeshSample>(masterRootPath))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                                var subsets = MeshImporter.ReadGeomSubsets(scene, pathAndSample.path);
                                MeshImporter.BuildMesh(pathAndSample.path, pathAndSample.sample, subsets, go, importOptions);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing mesh <" + pathAndSample.path + ">", ex));
                            }
                        }
                        Profiler.EndSample();

                        // Cubes.
                        Profiler.BeginSample("USD: Build Cubes");
                        foreach (var pathAndSample in scene.ReadAll <CubeSample>(masterRootPath))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                                CubeImporter.BuildCube(pathAndSample.sample, go, importOptions);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing cube <" + pathAndSample.path + ">", ex));
                            }
                        }
                        Profiler.EndSample();
                    }

                    // Cameras.
                    if (importOptions.importCameras)
                    {
                        Profiler.BeginSample("USD: Build Cameras");
                        foreach (var pathAndSample in scene.ReadAll <CameraSample>(masterRootPath))
                        {
                            try {
                                GameObject go = primMap[pathAndSample.path];
                                NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);
                                XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                                CameraImporter.BuildCamera(pathAndSample.sample, go, importOptions);
                            } catch (System.Exception ex) {
                                Debug.LogException(
                                    new ImportException("Error processing camera <" + pathAndSample.path + ">", ex));
                            }
                        }
                        Profiler.EndSample();
                    }
                } catch (System.Exception ex) {
                    Debug.LogException(
                        new ImportException("Error processing master <" + masterRootPath + ">", ex));
                }

                if (ShouldYield(targetTime, timer))
                {
                    yield return(null); ResetTimer(timer);
                }
            } // Instances.
            Profiler.EndSample();

            //
            // Post-process dependencies: materials and bones.
            //

            Profiler.BeginSample("USD: Process Material Bindings");
            try {
                // TODO: Currently ProcessMaterialBindings runs too long and will go over budget for any
                // large scene. However, pulling the loop into this code feels wrong in terms of
                // responsibilities.

                // Process all material bindings in a single vectorized request.
                MaterialImporter.ProcessMaterialBindings(scene, importOptions);
            } catch (System.Exception ex) {
                Debug.LogException(new ImportException("Failed in ProcessMaterialBindings", ex));
            }
            Profiler.EndSample();

            if (ShouldYield(targetTime, timer))
            {
                yield return(null); ResetTimer(timer);
            }

            //
            // SkinnedMesh bone bindings.
            //
            if (importOptions.importSkinning)
            {
                Profiler.BeginSample("USD: Build Skeletons");
                var skeletonSamples = new Dictionary <pxr.SdfPath, SkeletonSample>();
                foreach (var skelRoot in skelRoots)
                {
                    try {
                        var bindings = new pxr.UsdSkelBindingVector();
                        if (!primMap.SkelBindings.TryGetValue(skelRoot.GetPath(), out bindings))
                        {
                            Debug.LogWarning("No bindings found skelRoot: " + skelRoot.GetPath());
                        }

                        if (bindings.Count == 0)
                        {
                            Debug.LogWarning("No bindings found skelRoot: " + skelRoot.GetPath());
                        }

                        foreach (var skelBinding in bindings)
                        {
                            // The SkelRoot will likely have a skeleton binding, but it's inherited, so the bound
                            // skeleton isn't actually known until it's queried from the binding. Still, we would
                            // like not to reprocess skeletons redundantly, so skeletons are cached into a
                            // dictionary.

                            Profiler.BeginSample("Build Bind Transforms");
                            var            skelPath   = skelBinding.GetSkeleton().GetPath();
                            SkeletonSample skelSample = null;
                            if (!skeletonSamples.TryGetValue(skelPath, out skelSample))
                            {
                                skelSample = new SkeletonSample();

                                Profiler.BeginSample("Read Skeleton");
                                scene.Read(skelPath, skelSample);
                                Profiler.EndSample();

                                skeletonSamples.Add(skelPath, skelSample);

                                // Unity uses the inverse bindTransform, since that's actually what's needed for
                                // skinning. Do that once here, so each skinned mesh doesn't need to do it
                                // redundantly.
                                SkeletonImporter.BuildBindTransforms(skelPath, skelSample, importOptions);

                                var bindXforms = new pxr.VtMatrix4dArray();

                                var prim = scene.GetPrimAtPath(skelPath);
                                var skel = new pxr.UsdSkelSkeleton(prim);

                                Profiler.BeginSample("Get SkelQuery");
                                pxr.UsdSkelSkeletonQuery skelQuery = primMap.SkelCache.GetSkelQuery(skel);
                                Profiler.EndSample();

                                Profiler.BeginSample("Get JointWorldBind Transforms");
                                if (!skelQuery.GetJointWorldBindTransforms(bindXforms))
                                {
                                    throw new ImportException("Failed to compute binding trnsforms for <" + skelPath + ">");
                                }
                                Profiler.EndSample();

                                SkeletonImporter.BuildDebugBindTransforms(skelSample, primMap[skelPath], importOptions);
                            }
                            Profiler.EndSample();

                            if (importOptions.importSkinWeights)
                            {
                                //
                                // Apply skinning weights to each skinned mesh.
                                //
                                Profiler.BeginSample("Apply Skin Weights");
                                foreach (var skinningQuery in skelBinding.GetSkinningTargetsAsVector())
                                {
                                    var meshPath = skinningQuery.GetPrim().GetPath();
                                    try {
                                        var skelBindingSample = new SkelBindingSample();
                                        var goMesh            = primMap[meshPath];

                                        scene.Read(meshPath, skelBindingSample);

                                        Profiler.BeginSample("Build Skinned Mesh");
                                        SkeletonImporter.BuildSkinnedMesh(
                                            meshPath,
                                            skelPath,
                                            skelSample,
                                            skelBindingSample,
                                            goMesh,
                                            primMap,
                                            importOptions);
                                        Profiler.EndSample();

                                        // In terms of performance, this is almost free.
                                        goMesh.GetComponent <SkinnedMeshRenderer>().rootBone = primMap[skelPath].transform.GetChild(0);
                                    } catch (System.Exception ex) {
                                        Debug.LogException(new ImportException("Error skinning mesh: " + meshPath, ex));
                                    }
                                }
                                Profiler.EndSample();
                            }
                        }
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing SkelRoot <" + skelRoot.GetPath() + ">", ex));
                    }
                } // foreach SkelRoot
                Profiler.EndSample();

                if (ShouldYield(targetTime, timer))
                {
                    yield return(null); ResetTimer(timer);
                }

                //
                // Bone transforms.
                //
                Profiler.BeginSample("USD: Pose Bones");
                foreach (var pathAndSample in skeletonSamples)
                {
                    var skelPath = pathAndSample.Key;

                    try {
                        var prim = scene.GetPrimAtPath(skelPath);
                        var skel = new pxr.UsdSkelSkeleton(prim);

                        pxr.UsdSkelSkeletonQuery skelQuery = primMap.SkelCache.GetSkelQuery(skel);
                        var joints     = skelQuery.GetJointOrder();
                        var restXforms = new pxr.VtMatrix4dArray();
                        var time       = scene.Time.HasValue ? scene.Time.Value : pxr.UsdTimeCode.Default();

                        Profiler.BeginSample("Compute Joint Local Transforms");
                        if (!skelQuery.ComputeJointLocalTransforms(restXforms, time, atRest: false))
                        {
                            throw new ImportException("Failed to compute bind trnsforms for <" + skelPath + ">");
                        }
                        Profiler.EndSample();

                        Profiler.BeginSample("Build Bones");
                        for (int i = 0; i < joints.size(); i++)
                        {
                            var jointPath = scene.GetSdfPath(joints[i]);
                            if (joints[i] == "/")
                            {
                                jointPath = skelPath;
                            }
                            else if (jointPath.IsAbsolutePath())
                            {
                                Debug.LogException(new System.Exception("Unexpected absolute joint path: " + jointPath));
                                jointPath = new pxr.SdfPath(joints[i].ToString().TrimStart('/'));
                                jointPath = skelPath.AppendPath(jointPath);
                            }
                            else
                            {
                                jointPath = skelPath.AppendPath(jointPath);
                            }
                            var goBone = primMap[jointPath];

                            Profiler.BeginSample("Convert Matrix");
                            var restXform = UnityTypeConverter.FromMatrix(restXforms[i]);
                            Profiler.EndSample();

                            Profiler.BeginSample("Build Bone");
                            SkeletonImporter.BuildSkeletonBone(skelPath, goBone, restXform, joints, importOptions);
                            Profiler.EndSample();
                        }
                        Profiler.EndSample();
                    } catch (System.Exception ex) {
                        Debug.LogException(
                            new ImportException("Error processing SkelRoot <" + skelPath + ">", ex));
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();
            }

            //
            // Apply instancing.
            //
            if (importOptions.importSceneInstances)
            {
                Profiler.BeginSample("USD: Build Scene-Instances");
                try {
                    // Build scene instances.
                    InstanceImporter.BuildSceneInstances(primMap, importOptions);
                } catch (System.Exception ex) {
                    Debug.LogException(new ImportException("Failed in BuildSceneInstances", ex));
                }
                Profiler.EndSample();
            }

            if (ShouldYield(targetTime, timer))
            {
                yield return(null); ResetTimer(timer);
            }

            // Build point instances.
            if (importOptions.importPointInstances)
            {
                Profiler.BeginSample("USD: Build Point-Instances");
                // TODO: right now all point instancer data is read, but we only need prototypes and indices.
                foreach (var pathAndSample in scene.ReadAll <PointInstancerSample>())
                {
                    try {
                        GameObject instancerGo = primMap[pathAndSample.path];

                        // Now build the point instances.
                        InstanceImporter.BuildPointInstances(scene,
                                                             primMap,
                                                             pathAndSample.path,
                                                             pathAndSample.sample,
                                                             instancerGo,
                                                             importOptions);
                    } catch (System.Exception ex) {
                        Debug.LogError("Error processing point instancer <" + pathAndSample.path + ">: " + ex.Message);
                    }

                    if (ShouldYield(targetTime, timer))
                    {
                        yield return(null); ResetTimer(timer);
                    }
                }
                Profiler.EndSample();
            }

            //
            // Apply root transform corrections.
            //
            Profiler.BeginSample("USD: Build Root Transforms");
            if (!composingSubtree)
            {
                if (!root)
                {
                    // There is no single root,
                    // Apply root transform corrections to all imported root prims.
                    foreach (KeyValuePair <pxr.SdfPath, GameObject> kvp in primMap)
                    {
                        if (kvp.Key.IsRootPrimPath() && kvp.Value != null)
                        {
                            // The root object at which the USD scene will be reconstructed.
                            // It may need a Z-up to Y-up conversion and a right- to left-handed change of basis.
                            XformImporter.BuildSceneRoot(scene, kvp.Value.transform, importOptions);
                        }
                    }
                }
                else
                {
                    // There is only one root, apply a single transform correction.
                    XformImporter.BuildSceneRoot(scene, root.transform, importOptions);
                }
            }
            Profiler.EndSample();

            Profiler.BeginSample("USD: Post Process Components");
            foreach (var processor in root.GetComponents <IImportPostProcessComponents>())
            {
                try {
                    processor.PostProcessComponents(primMap, importOptions);
                } catch (System.Exception ex) {
                    Debug.LogException(ex);
                }
            }
            Profiler.EndSample();
        }
Esempio n. 25
0
 public void BeginReading(Scene scene, PrimMap primMap)
 {
     m_readMeshesJob = new ReadAllJob <MeshSample>(scene, primMap.Meshes);
     m_readMeshesJob.Run();
 }
Esempio n. 26
0
        public System.Collections.IEnumerator Import(Scene scene,
                                                     PrimMap primMap,
                                                     SceneImportOptions importOptions)
        {
            if (importOptions.importSkinning)
            {
                Profiler.BeginSample("USD: Populate SkelCache");
                foreach (var path in primMap.SkelRoots)
                {
                    var prim = scene.GetPrimAtPath(path);
                    if (!prim)
                    {
                        continue;
                    }

                    var skelRoot = new UsdSkelRoot(prim);
                    if (!skelRoot)
                    {
                        continue;
                    }
                }
                Profiler.EndSample();
            }

            System.Reflection.MemberInfo faceVertexCounts  = null;
            System.Reflection.MemberInfo faceVertexIndices = null;
            System.Reflection.MemberInfo orientation       = null;
            System.Reflection.MemberInfo purpose           = null;
            System.Reflection.MemberInfo visibility        = null;

            if (scene.AccessMask != null && scene.IsPopulatingAccessMask)
            {
                var meshType = typeof(MeshSample);
                faceVertexCounts  = meshType.GetMember("faceVertexCounts")[0];
                faceVertexIndices = meshType.GetMember("faceVertexIndices")[0];
                orientation       = meshType.GetMember("orientation")[0];
                purpose           = meshType.GetMember("purpose")[0];
                visibility        = meshType.GetMember("visibility")[0];
            }

            foreach (var pathAndSample in m_readMeshesJob)
            {
                if (scene.AccessMask != null && scene.IsPopulatingAccessMask)
                {
                    HashSet <System.Reflection.MemberInfo> members;
                    if (scene.AccessMask.Included.TryGetValue(pathAndSample.path, out members))
                    {
                        if (members.Contains(faceVertexCounts) ||
                            members.Contains(orientation) ||
                            members.Contains(faceVertexIndices))
                        {
                            members.Add(faceVertexCounts);
                            members.Add(faceVertexIndices);
                            members.Add(orientation);
                        }

                        if (pathAndSample.sample.purpose != Purpose.Default && !members.Contains(purpose))
                        {
                            members.Add(purpose);
                        }

                        if (pathAndSample.sample.visibility != Visibility.Inherited && !members.Contains(visibility))
                        {
                            members.Add(visibility);
                        }
                    }
                }

                Profiler.BeginSample("USD: Build Meshes");
                try {
                    GameObject go = primMap[pathAndSample.path];
                    NativeImporter.ImportObject(scene, go, scene.GetPrimAtPath(pathAndSample.path), importOptions);

                    if (importOptions.importTransforms)
                    {
                        Profiler.BeginSample("Build Mesh Xform");
                        XformImporter.BuildXform(pathAndSample.path, pathAndSample.sample, go, importOptions, scene);
                        Profiler.EndSample();
                    }

                    Profiler.BeginSample("Read Mesh Subsets");
                    MeshImporter.GeometrySubsets subsets = null;
                    if (primMap == null || !primMap.MeshSubsets.TryGetValue(pathAndSample.path, out subsets))
                    {
                        subsets = MeshImporter.ReadGeomSubsets(scene, pathAndSample.path);
                    }
                    Profiler.EndSample();

                    UsdSkelSkinningQuery skinningQuery;
                    if (importOptions.importHierarchy)
                    {
                        if (importOptions.importSkinning && primMap.SkelCache != null)
                        {
                            // This is pre-cached as part of calling skelCache.Populate and IsValid indicates if we
                            // have the data required to setup a skinned mesh.
                            Profiler.BeginSample("Get Skinning Query");
                            skinningQuery = new UsdSkelSkinningQuery();
                            primMap.SkinningQueries[pathAndSample.path] = primMap.SkelCache.GetSkinningQuery(scene.GetPrimAtPath(pathAndSample.path));
                            Profiler.EndSample();
                        }
                        if (importOptions.importMeshes)
                        {
                            primMap.MeshSubsets[pathAndSample.path] = MeshImporter.ReadGeomSubsets(scene, pathAndSample.path);
                        }
                    }

                    if (importOptions.importSkinning)
                    {
                        primMap.SkinningQueries.TryGetValue(pathAndSample.path, out skinningQuery);

                        /*
                         * Profiler.BeginSample("Get Skinning Query");
                         * skinningQuery = primMap.SkelCache.GetSkinningQuery(scene.GetPrimAtPath(pathAndSample.path));
                         * Profiler.EndSample();
                         */
                    }

                    if (importOptions.importSkinning &&
                        primMap.SkelCache != null &&
                        primMap.SkinningQueries.TryGetValue(pathAndSample.path, out skinningQuery) &&
                        skinningQuery.IsValid())
                    {
                        Profiler.BeginSample("USD: Build Skinned Mesh");
                        m_skinnedMeshImporter(pathAndSample.path,
                                              pathAndSample.sample,
                                              subsets, go, importOptions);
                        Profiler.EndSample();
                    }
                    else
                    {
                        Profiler.BeginSample("USD: Build Mesh");
                        m_meshImporter(pathAndSample.path,
                                       pathAndSample.sample,
                                       subsets, go, importOptions);
                        Profiler.EndSample();
                    }
                } catch (Exception ex) {
                    Debug.LogException(
                        new SceneImporter.ImportException(
                            "Error processing mesh <" + pathAndSample.path + ">", ex));
                }

                Profiler.EndSample();
                yield return(null);
            } // foreach mesh
        }