示例#1
0
        private static async UniTask Build(StateObject state, Model3D model, Model3DLoadMeshDelegate load)
        {
            var(file, ct) = state;
            var screen = model.GetValidScreen();

            ct.ThrowIfCancellationRequested();

            await UniTask.SwitchToThreadPool();

            ct.ThrowIfCancellationRequested();

            using var verticesBuffer = new UnsafeBufferWriter <Vertex>();
            using var indicesBuffer  = new UnsafeBufferWriter <int>();
            ParseFromFile(file, verticesBuffer, indicesBuffer);

            await screen.TimingPoints.Update.Next(ct);

            load.Invoke(verticesBuffer.WrittenSpan, indicesBuffer.WrittenSpan);
        }
示例#2
0
        private static async UniTask Build(StateObject state, Model3D model, Model3DLoadMeshDelegate load)
        {
            //var (resourceLoader, name, token) = obj;
            var(file, token) = state;
            var screen       = model.GetValidScreen();
            var timingPoints = screen.TimingPoints;

            token.ThrowIfCancellationRequested();

            await UniTask.SwitchToThreadPool();     // ↓ thread pool --------------------------------------

            token.ThrowIfCancellationRequested();

            // Parse fbx file
            using var fbx = FbxSemanticParser <SkinnedVertex> .ParseUnsafe(file.GetStream(), false, token);

            await timingPoints.Update.Next(token);        // ↓ main thread --------------------------------------

            await CreateTexture(file, fbx, model);

            // Create a skeleton component
            if (fbx.Skeletons.IsEmpty == false)
            {
                var skeletonIndex = 0;
                var skeleton      = new HumanoidSkeleton();
                model.AddComponent(skeleton);
                using var bones = new ValueTypeRentMemory <Bone>(fbx.Skeletons[skeletonIndex].BoneCount, false);
                fbx.Skeletons[skeletonIndex].CreateBones(bones.AsSpan());
                await skeleton.LoadAsync(bones, timingPoints, cancellationToken : token);
            }

            load.Invoke(fbx.Vertices, fbx.Indices);
            await UniTask.SwitchToThreadPool();         // ↓ thread pool --------------------------------------

            // 'using' scope ends here. Dispose resources on a thread pool.
            // Nobody knows the thread if exceptions are thrown in this method,
            // but I don't care about that.
        }
示例#3
0
        private static async UniTask LoadToModel(PMXObject pmx, Model3D model, Model3DLoadMeshDelegate load, ModelState obj)
        {
            // ------------------------------
            //      ↓ thread pool
            Debug.Assert(Engine.IsThreadMain == false);
            var screen = model.GetValidScreen();

            // Don't make the followings parallel like UniTask.WhenAll.
            // ModelData will be disposed when an exception is throw, but another parallel code could not know that.
            using var vertices = GetVertices(pmx);
            using var bones    = GetBones(pmx);
            await BuildTexture(pmx, obj.File, model, vertices, obj.CancellationToken);

            await UniTask.SwitchToThreadPool();

            var skeleton = new HumanoidSkeleton();

            model.AddComponent(skeleton);
            await skeleton.LoadAsync(bones.AsSpanLike(), screen.TimingPoints, obj.CancellationToken);

            //      ↑ thread pool
            // ------------------------------
            await screen.TimingPoints.Update.NextOrNow(obj.CancellationToken);

            // ------------------------------
            //      ↓ main thread
            Debug.Assert(Engine.CurrentContext == screen);
            Debug.Assert(model.LifeState == LifeState.Activating);

            model.Shader ??= new PmxModelShader();

            // load vertices and indices
            load.Invoke(vertices.AsSpan().AsReadOnly(), pmx.SurfaceList.AsSpan().MarshalCast <Surface, int>());

            //      ↑ main thread
            // ------------------------------
        }