private void ConvertCompoundColliders()
        {
            Profiler.BeginSample("ConvertCompoundColliders");

            m_nativeColliders  = new NativeList <Collider>(128, Allocator.TempJob);
            m_nativeTransforms = new NativeList <RigidTransform>(128, Allocator.TempJob);
            m_compoundRanges   = new NativeList <int2>(128, Allocator.TempJob);

            //Step 1: Find all colliders and construct parallel arrays
            m_authorings.Clear();
            Entities.WithNone <DontConvertColliderTag>().ForEach((LatiosColliderAuthoring colliderAuthoring) =>
            {
                //Do stuff
                if (colliderAuthoring.colliderType == AuthoringColliderTypes.None)
                {
                    return;
                }
                if (colliderAuthoring.generateFromChildren)
                {
                    m_unityColliders.Clear();
                    colliderAuthoring.GetComponentsInChildren(m_unityColliders);
                    try
                    {
                        CreateChildrenColliders(colliderAuthoring, m_unityColliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges);
                    }
                    catch (Exception e)
                    {
                        DisposeAndThrow(e);
                    }
                }
                else
                {
                    try
                    {
                        CreateChildrenColliders(colliderAuthoring, colliderAuthoring.colliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges);
                    }
                    catch (Exception e)
                    {
                        DisposeAndThrow(e);
                    }
                }
                m_authorings.Add(colliderAuthoring);
            });

            if (m_authorings.Count > 0)
            {
                using (var computationContext = new BlobAssetComputationContext <CompoundColliderComputationData, CompoundColliderBlob>(BlobAssetStore, 128, Allocator.Temp))
                {
                    //Step 2: Compute hashes
                    var hashes = new NativeArray <ColliderTransformHashPair>(m_compoundRanges.Length, Allocator.TempJob);
                    new ComputeCompoundHashesJob
                    {
                        colliders  = m_nativeColliders,
                        transforms = m_nativeTransforms,
                        ranges     = m_compoundRanges,
                        hashes     = hashes
                    }.ScheduleParallel(m_compoundRanges.Length, 1, default).Complete();

                    //Step 3: Check hashes against computationContext to see if blobs need to be built
                    for (int i = 0; i < m_authorings.Count; i++)
                    {
                        var hash = hashes.ReinterpretLoad <Hash128>(i);
                        computationContext.AssociateBlobAssetWithUnityObject(hash, m_authorings[i].gameObject);
                        if (computationContext.NeedToComputeBlobAsset(hash))
                        {
                            computationContext.AddBlobAssetToCompute(hash, new CompoundColliderComputationData
                            {
                                hash  = hash,
                                index = i
                            });
                        }
                    }

                    //Step 4: Dispatch builder job
                    using (var computationData = computationContext.GetSettings(Allocator.TempJob))
                    {
                        new ComputeCompoundBlobs
                        {
                            colliders       = m_nativeColliders,
                            transforms      = m_nativeTransforms,
                            ranges          = m_compoundRanges,
                            computationData = computationData
                        }.ScheduleParallel(computationData.Length, 1, default).Complete();

                        foreach (var data in computationData)
                        {
                            computationContext.AddComputedBlobAsset(data.hash, data.blob);
                        }
                    }

                    //Step 5: Build Collider component
                    var index = 0;
                    Entities.ForEach((LatiosColliderAuthoring colliderAuthoring) =>
                    {
                        computationContext.GetBlobAsset(hashes.ReinterpretLoad <Hash128>(index++), out var blob);

                        var targetEntity = GetPrimaryEntity(colliderAuthoring);

                        float3 scale = colliderAuthoring.transform.lossyScale;
                        if (scale.x != scale.y || scale.x != scale.z)
                        {
                            throw new InvalidOperationException(
                                $"GameObject Conversion Error: Failed to convert {colliderAuthoring}. Only uniform scale is permitted on Compound colliders.");
                        }

                        Collider icdCompound = new CompoundCollider
                        {
                            compoundColliderBlob = blob,
                            scale = scale.x
                        };
                        DstEntityManager.AddComponentData(targetEntity, icdCompound);
                    });

                    hashes.Dispose();
                }
            }

            m_nativeColliders.Dispose();
            m_nativeTransforms.Dispose();
            m_compoundRanges.Dispose();

            Profiler.EndSample();
        }
Exemple #2
0
        protected override void OnUpdate()
        {
            var processBlobAssets    = new NativeList <Hash128>(Constants.PositionCount, Allocator.Temp);
            var blobFactoryPositions = new NativeList <float3>(Allocator.TempJob);
            var blobLength           = 0;
            int currentIndex         = 0;

            using (var positionContext = new BlobAssetComputationContext <SequenceSettings, SequentialPositionsBlobAsset>(BlobAssetStore, 32, Allocator.Temp)) {
                Entities.ForEach((T spawner) =>
                {
                    var filePathHash = (uint)spawner.FilePath.GetHashCode();
                    var isFirst      = true;
                    var dataLength   = -1;
                    for (var i = 0; i < Constants.PositionCount; ++i)
                    {
                        var hash = new Hash128(filePathHash, (uint)i, 0, 0);
                        processBlobAssets.Add(hash);
                        positionContext.AssociateBlobAssetWithUnityObject(hash, spawner.gameObject);
                        if (positionContext.NeedToComputeBlobAsset(hash))
                        {
                            if (isFirst)
                            {
                                isFirst       = false;
                                currentIndex  = blobLength;
                                var readToEnd = File.ReadAllLines(Path.Combine(Application.streamingAssetsPath, spawner.FilePath));
                                dataLength    = readToEnd.Length - (spawner.HasHeader ? 1 : 0);
                                blobLength   += Constants.PositionCount * dataLength;
                                blobFactoryPositions.Resize(blobLength, NativeArrayOptions.UninitializedMemory);
                                Fill(blobFactoryPositions, readToEnd, spawner.HasHeader, currentIndex);
                            }
                            var sequentialSettings = new SequenceSettings
                            {
                                Hash       = hash,
                                StartIndex = currentIndex + i * dataLength,
                                Count      = dataLength
                            };
                            positionContext.AddBlobAssetToCompute(hash, sequentialSettings);
                        }
                    }
                });

                using (var positionSettings = positionContext.GetSettings(Allocator.TempJob)) {
                    var positionJob = new ComputeSequentialPositionAssetJob(positionSettings, blobFactoryPositions);
                    positionJob.Schedule(positionJob.Settings.Length, 1).Complete();
                    for (var i = 0; i < positionSettings.Length; ++i)
                    {
                        positionContext.AddComputedBlobAsset(positionSettings[i].Hash, positionJob.BlobAssets[i]);
                    }
                    positionJob.BlobAssets.Dispose();
                }

                blobFactoryPositions.Dispose();

                var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, BlobAssetStore);
                var index    = 0;
                Entities.ForEach((T spawner) =>
                {
                    var prefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(spawner.Prefab, settings);
                    DstEntityManager.AddComponent <SequenceIndex>(prefab);
                    DstEntityManager.AddComponentData(prefab, new SequenceFrequency {
                        Value = spawner.FrequencyOfSequence
                    });
                    using (var instances = DstEntityManager.Instantiate(prefab, Constants.PositionCount, Allocator.Temp)) {
                        for (var i = 0; i < instances.Length; ++i)
                        {
                            positionContext.GetBlobAsset(processBlobAssets[index], out var positionBlob);
                            DstEntityManager.AddComponentData(instances[i], new SequentialPositions {
                                BlobData = positionBlob,
                                Parent   = GetPrimaryEntity(spawner)
                            });
                            ++index;
                        }
                        InitHelenHayes(instances);
                    }
                });

                processBlobAssets.Dispose();
            }
        }
    protected override void OnUpdate()
    {
        var blobFactoryPoints = new NativeList <float3>(Allocator.TempJob);
        int curPointIndex     = 0;
        var vertices          = new List <Vector3>(4096);
        var processBlobAssets = new NativeList <Hash128>(32, Allocator.Temp);

        Profiler.BeginSample("Conv_BuildHashAndPush");

        using (var context = new BlobAssetComputationContext <MeshBBFactorySettings, MeshBBBlobAsset>(BlobAssetStore, 128, Allocator.Temp))
        {
            // First step: for all changed GameObjects we compute the hash of their blob asset then get the asset or register its computation
            Entities.ForEach((MeshToBoundingBoxAuthoring auth) =>
            {
                // Compute the blob asset hash based on Authoring properties
                var hasMesh      = auth.Mesh != null;
                var meshHashCode = hasMesh ? auth.Mesh.GetHashCode() : 0;
                var hash         = new Hash128((uint)meshHashCode, (uint)auth.MeshScale.GetHashCode(), 0, 0);

                // Query the context to determine if we need to build the BlobAsset
                processBlobAssets.Add(hash);
                context.AssociateBlobAssetWithUnityObject(hash, auth.gameObject);
                if (context.NeedToComputeBlobAsset(hash))
                {
                    Profiler.BeginSample("CopyVertices");

                    float xp = float.MinValue, yp = float.MinValue, zp = float.MinValue;
                    float xn = float.MaxValue, yn = float.MaxValue, zn = float.MaxValue;

                    // Copy the mesh vertices into the point array
                    if (hasMesh)
                    {
                        auth.Mesh.GetVertices(vertices);
                        for (int i = 0; i < vertices.Count; i++)
                        {
                            var p = vertices[i];
                            xp    = math.max(p.x, xp);
                            yp    = math.max(p.y, yp);
                            zp    = math.max(p.z, zp);
                            xn    = math.min(p.x, xn);
                            yn    = math.min(p.y, yn);
                            zn    = math.min(p.z, zn);
                            blobFactoryPoints.Add(new float3(p.x, p.y, p.z));
                        }
                    }
                    else
                    {
                        xp = yp = zp = xn = yn = zn = 0;
                    }

                    Profiler.EndSample();

                    // Record this blob asset for computation
                    var vertexCount = hasMesh ? auth.Mesh.vertexCount : 0;
                    var setting     = new MeshBBFactorySettings {
                        Hash = hash, MeshScale = auth.MeshScale, PointStartIndex = curPointIndex, PointCount = vertexCount, MinBoundingBox = new float3(xn, yn, zn), MaxBoundingBox = new float3(xp, yp, zp)
                    };
                    curPointIndex += vertexCount;

                    context.AddBlobAssetToCompute(hash, setting);
                }
            });

            Profiler.EndSample();

            Profiler.BeginSample("Conv_CreateBlobAssets");

            using (var settings = context.GetSettings(Allocator.TempJob))
            {
                // Step two, compute BlobAssets
                var job = new ComputeMeshBBAssetJob(settings, blobFactoryPoints.AsArray());
                job.Schedule(job.Settings.Length, 1).Complete();

                for (int i = 0; i < settings.Length; i++)
                {
                    context.AddComputedBlobAsset(settings[i].Hash, job.BlobAssets[i]);
                }
                job.BlobAssets.Dispose();
            }

            Profiler.EndSample();

            Profiler.BeginSample("Conv_CreateECS");

            // Third step, create the ECS component with the associated blob asset
            var index = 0;
            Entities.ForEach((MeshToBoundingBoxAuthoring auth) =>
            {
                context.GetBlobAsset(processBlobAssets[index++], out var blob);

                // Create the ECS component for the given GameObject
                var entity = GetPrimaryEntity(auth);

                DstEntityManager.AddComponentData(entity, new MeshBBComponent(blob));
                DstEntityManager.AddComponentData(entity, new Translation {
                    Value = auth.transform.position
                });
            });

            Profiler.EndSample();
            blobFactoryPoints.Dispose();
            processBlobAssets.Dispose();
        }
    }
        void ConvertBatchedClips()
        {
            var clipList = new List <AudioClip>();

            using (var computationContext = new BlobAssetComputationContext <AudioClipComputationData, AudioClipBlob>(BlobAssetStore, 128, Allocator.Temp))
            {
                var hashes     = new NativeList <Hash128>(Allocator.Persistent);
                var jobs       = new List <ComputeAudioClipHashesJob>();
                var jobHandles = new NativeList <JobHandle>(Allocator.Persistent);
                Entities.ForEach((AudioSourceAuthoring authoring) =>
                {
                    if (authoring.clip != null)
                    {
                        int frequency = authoring.clip.frequency;
                        var arr       = new float[authoring.clip.samples * authoring.clip.channels];
                        authoring.clip.GetData(arr, 0);
                        var job = new ComputeAudioClipHashesJob
                        {
                            samples   = new NativeArray <float>(arr, Allocator.Persistent),
                            hash      = new NativeReference <uint2>(Allocator.Persistent),
                            frequency = frequency
                        };
                        jobs.Add(job);
                        jobHandles.Add(job.Schedule());
                    }
                });
                JobHandle.CompleteAll(jobHandles);
                jobHandles.Dispose();

                int index = 0;
                Entities.ForEach((AudioSourceAuthoring authoring) =>
                {
                    if (authoring.clip != null)
                    {
                        var hash =
                            new Hash128(jobs[index].hash.Value.x, jobs[index].hash.Value.y, (uint)authoring.clip.channels, (uint)math.select(0, authoring.voices,
                                                                                                                                             authoring.looping));
                        computationContext.AssociateBlobAssetWithUnityObject(hash, authoring.gameObject);
                        if (computationContext.NeedToComputeBlobAsset(hash))
                        {
                            computationContext.AddBlobAssetToCompute(hash, new AudioClipComputationData {
                                hash = hash, index = index
                            });
                        }
                        index++;
                        clipList.Add(authoring.clip);
                        hashes.Add(hash);
                    }
                });
                foreach (var job in jobs)
                {
                    job.samples.Dispose();
                    job.hash.Dispose();
                }
                using (var computationDataArray = computationContext.GetSettings(Allocator.TempJob))
                {
                    var samples       = new NativeList <float>(Allocator.TempJob);
                    var ranges        = new NativeArray <int2>(computationDataArray.Length, Allocator.TempJob);
                    var rates         = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var channelCounts = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var offsets       = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var names         = new NativeArray <FixedString128>(computationDataArray.Length, Allocator.TempJob);
                    for (int i = 0; i < computationDataArray.Length; i++)
                    {
                        var clip           = clipList[computationDataArray[i].index];
                        var samplesManaged = new float[clip.samples * clip.channels];
                        clip.GetData(samplesManaged, 0);
                        var samplesUnmanaged = new NativeArray <float>(samplesManaged, Allocator.Temp);
                        ranges[i] = new int2(samples.Length, samplesUnmanaged.Length);
                        samples.AddRange(samplesUnmanaged);
                        rates[i]         = clip.frequency;
                        channelCounts[i] = clip.channels;
                        offsets[i]       = (int)computationDataArray[i].hash.Value.w;
                        names[i]         = clip.name;
                    }
                    new ComputeAudioClipBlobsJob
                    {
                        samples              = samples,
                        ranges               = ranges,
                        rates                = rates,
                        channelCounts        = channelCounts,
                        computationDataArray = computationDataArray,
                        offsetCounts         = offsets,
                        names                = names
                    }.ScheduleParallel(ranges.Length, 1, default).Complete();
                    foreach (var data in computationDataArray)
                    {
                        computationContext.AddComputedBlobAsset(data.hash, data.blob);
                    }
                    samples.Dispose();
                    ranges.Dispose();
                    rates.Dispose();
                    channelCounts.Dispose();
                    offsets.Dispose();
                    names.Dispose();

                    index = 0;
                    Entities.ForEach((AudioSourceAuthoring authoring) =>
                    {
                        if (authoring.clip != null)
                        {
                            var hash = hashes[index];
                            computationContext.GetBlobAsset(hash, out var blob);

                            var entity = GetPrimaryEntity(authoring);
                            if (!authoring.looping)
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceOneShot
                                {
                                    clip            = blob,
                                    innerRange      = authoring.innerRange,
                                    outerRange      = authoring.outerRange,
                                    rangeFadeMargin = authoring.rangeFadeMargin,
                                    volume          = authoring.volume
                                });
                                if (authoring.autoDestroyOnFinish)
                                {
                                    DstEntityManager.AddComponent <AudioSourceDestroyOneShotWhenFinished>(entity);
                                }
                            }
                            else
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceLooped
                                {
                                    m_clip          = blob,
                                    innerRange      = authoring.innerRange,
                                    outerRange      = authoring.outerRange,
                                    rangeFadeMargin = authoring.rangeFadeMargin,
                                    volume          = authoring.volume,
                                });
                            }
                            if (authoring.useCone)
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceEmitterCone
                                {
                                    cosInnerAngle         = math.cos(math.radians(authoring.innerAngle)),
                                    cosOuterAngle         = math.cos(math.radians(authoring.outerAngle)),
                                    outerAngleAttenuation = authoring.outerAngleVolume
                                });
                            }
                            index++;
                        }
                    });
                }
                hashes.Dispose();
            }
        }
Exemple #5
0
        protected override void OnUpdate()
        {
            var simpleMeshContext = new BlobAssetComputationContext <UMeshSettings, SimpleMeshData>(BlobAssetStore, 128, Allocator.Temp);
            var litMeshContext    = new BlobAssetComputationContext <UMeshSettings, LitMeshData>(BlobAssetStore, 128, Allocator.Temp);

            JobHandle combinedJH  = new JobHandle();
            int       simpleIndex = 0;
            int       litIndex    = 0;

            // Init blobasset arrays
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                CheckForMeshLimitations(uMesh);
                var entity = GetPrimaryEntity(uMesh);
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleIndex++;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litIndex++;
                }
            });
            NativeArray <BlobAssetReference <SimpleMeshData> > simpleblobs = new NativeArray <BlobAssetReference <SimpleMeshData> >(simpleIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <LitMeshData> >    litblobs    = new NativeArray <BlobAssetReference <LitMeshData> >(litIndex, Allocator.TempJob);

            simpleIndex = 0;
            litIndex    = 0;

            // Check which blob assets to re-compute
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var hash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(), (uint)uMesh.subMeshCount.GetHashCode(), 0);

                var entity = GetPrimaryEntity(uMesh);

                //Schedule blob asset recomputation jobs
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleMeshContext.AssociateBlobAssetWithUnityObject(hash, uMesh);
                    if (simpleMeshContext.NeedToComputeBlobAsset(hash))
                    {
                        var singleMeshData = new UMeshDataCache();
                        singleMeshData.RetrieveSimpleMeshData(uMesh);

                        UMeshSettings uMeshSettings = new UMeshSettings(hash, uMesh, simpleIndex++);
                        simpleMeshContext.AddBlobAssetToCompute(hash, uMeshSettings);
                        var job    = new SimpleMeshConversionJob(uMeshSettings, singleMeshData, simpleblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litMeshContext.AssociateBlobAssetWithUnityObject(hash, uMesh);
                    if (litMeshContext.NeedToComputeBlobAsset(hash))
                    {
                        var litMeshData = new UMeshDataCache();
                        if (DstEntityManager.HasComponent <NeedGenerateGPUSkinnedMeshRenderer>(entity))
                        {
                            litMeshData.RetrieveLitSkinnedMeshData(uMesh, entity, DstEntityManager);
                        }
                        else
                        {
                            litMeshData.RetrieveLitMeshData(uMesh);
                        }

                        UMeshSettings uMeshSettings = new UMeshSettings(hash, uMesh, litIndex++);
                        litMeshContext.AddBlobAssetToCompute(hash, uMeshSettings);
                        var job    = new LitMeshConversionJob(uMeshSettings, litMeshData, litblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }
            });

            // Re-compute the new blob assets
            combinedJH.Complete();

            // Update the BlobAssetStore
            using (var simpleMeshSettings = simpleMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < simpleMeshSettings.Length; i++)
                {
                    simpleMeshContext.AddComputedBlobAsset(simpleMeshSettings[i].hash, simpleblobs[simpleMeshSettings[i].blobIndex]);
                }
            }
            using (var litMeshSettings = litMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < litMeshSettings.Length; i++)
                {
                    litMeshContext.AddComputedBlobAsset(litMeshSettings[i].hash, litblobs[litMeshSettings[i].blobIndex]);
                }
            }

            // Use blob assets in the conversion
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var entity     = GetPrimaryEntity(uMesh);
                bool addBounds = false;
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleMeshContext.GetBlobAsset(new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(), (uint)uMesh.subMeshCount.GetHashCode(), 0), out var blob);
                    DstEntityManager.AddComponentData(entity, new SimpleMeshRenderData()
                    {
                        Mesh = blob
                    });
                    addBounds = true;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litMeshContext.GetBlobAsset(new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(), (uint)uMesh.subMeshCount.GetHashCode(), 0), out var blob);
                    DstEntityManager.AddComponentData(entity, new LitMeshRenderData()
                    {
                        Mesh = blob
                    });
                    addBounds = true;
                }
                if (addBounds)
                {
                    DstEntityManager.AddComponentData(entity, new MeshBounds
                    {
                        Bounds = new AABB
                        {
                            Center  = uMesh.bounds.center,
                            Extents = uMesh.bounds.extents
                        }
                    });
                }
            });

            simpleMeshContext.Dispose();
            litMeshContext.Dispose();
            simpleblobs.Dispose();
            litblobs.Dispose();
        }
        protected override void OnUpdate()
        {
            var simpleMeshContext  = new BlobAssetComputationContext <UMeshSettings, SimpleMeshData>(BlobAssetStore, 128, Allocator.Temp);
            var litMeshContext     = new BlobAssetComputationContext <UMeshSettings, LitMeshData>(BlobAssetStore, 128, Allocator.Temp);
            var blendShapeContext  = new BlobAssetComputationContext <UMeshSettings, BlendShapeData>(BlobAssetStore, 128, Allocator.Temp);
            var skinnedMeshContext = new BlobAssetComputationContext <UMeshSettings, SkinnedMeshData>(BlobAssetStore, 128, Allocator.Temp);

            JobHandle combinedJH       = new JobHandle();
            int       simpleIndex      = 0;
            int       litIndex         = 0;
            int       blendShapeIndex  = 0;
            int       skinnedMeshIndex = 0;

            // Init blobasset arrays
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                CheckForMeshLimitations(uMesh);
                var entity = GetPrimaryEntity(uMesh);
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleIndex++;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litIndex++;
                }
                if (uMesh.blendShapeCount > 0)
                {
                    blendShapeIndex++;
                }
                if (uMesh.boneWeights.Length > 0)
                {
                    skinnedMeshIndex++;
                }
            });
            NativeArray <BlobAssetReference <SimpleMeshData> >  simpleblobs      = new NativeArray <BlobAssetReference <SimpleMeshData> >(simpleIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <LitMeshData> >     litblobs         = new NativeArray <BlobAssetReference <LitMeshData> >(litIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <BlendShapeData> >  blendshapeblobs  = new NativeArray <BlobAssetReference <BlendShapeData> >(blendShapeIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <SkinnedMeshData> > skinnedMeshBlobs = new NativeArray <BlobAssetReference <SkinnedMeshData> >(litIndex, Allocator.TempJob);

            simpleIndex      = 0;
            litIndex         = 0;
            blendShapeIndex  = 0;
            skinnedMeshIndex = 0;

            // Check which blob assets to re-compute
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var verticesHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                               (uint)uMesh.subMeshCount.GetHashCode(), 0);
                uint boneCount      = (uint)uMesh.bindposes.Length;
                var skinnedDataHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), (uint)boneCount.GetHashCode());

                var entity = GetPrimaryEntity(uMesh);

                //Schedule blob asset recomputation jobs
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleMeshContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (simpleMeshContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var simpleMeshData = new UMeshDataCache();
                        if (boneCount > 0)
                        {
                            simpleMeshData.RetrieveSkinnedMeshData(uMesh, entity, DstEntityManager, false);
                            if (skinnedMeshContext.NeedToComputeBlobAsset(skinnedDataHash))
                            {
                                UMeshSettings uSkinnedMeshSettings = new UMeshSettings(skinnedDataHash, uMesh, skinnedMeshIndex++);
                                skinnedMeshContext.AddBlobAssetToCompute(skinnedDataHash, uSkinnedMeshSettings);
                                var skinningJob = new SkinningDataConversionJob(simpleMeshData, uSkinnedMeshSettings.blobIndex, skinnedMeshBlobs);
                                combinedJH      = JobHandle.CombineDependencies(combinedJH, skinningJob.Schedule(combinedJH));
                            }
                        }
                        else
                        {
                            simpleMeshData.RetrieveSimpleMeshData(uMesh);
                        }

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, simpleIndex++);
                        simpleMeshContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);
                        var job    = new SimpleMeshConversionJob(simpleMeshData, uMeshSettings.blobIndex, simpleblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }

                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litMeshContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (litMeshContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var litMeshData = new UMeshDataCache();
                        if (boneCount > 0)
                        {
                            litMeshData.RetrieveSkinnedMeshData(uMesh, entity, DstEntityManager, true);
                            if (skinnedMeshContext.NeedToComputeBlobAsset(skinnedDataHash))
                            {
                                UMeshSettings uSkinnedMeshSettings = new UMeshSettings(skinnedDataHash, uMesh, skinnedMeshIndex++);
                                skinnedMeshContext.AddBlobAssetToCompute(skinnedDataHash, uSkinnedMeshSettings);
                                var skinningJob = new SkinningDataConversionJob(litMeshData, uSkinnedMeshSettings.blobIndex, skinnedMeshBlobs);
                                combinedJH      = JobHandle.CombineDependencies(combinedJH, skinningJob.Schedule(combinedJH));
                            }
                        }
                        else
                        {
                            litMeshData.RetrieveLitMeshData(uMesh);
                        }

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, litIndex++);
                        litMeshContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);
                        var job    = new LitMeshConversionJob(litMeshData, uMeshSettings.blobIndex, litblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }

                if (uMesh.blendShapeCount > 0)
                {
                    verticesHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                               (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.blendShapeCount);
                    blendShapeContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (blendShapeContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var blendShapeDataCache = new UBlendShapeDataCache();
                        blendShapeDataCache.RetrieveBlendShapeData(uMesh);

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, blendShapeIndex++);
                        blendShapeContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);

                        var job    = new BlendShapeConversionJob(uMeshSettings, blendShapeDataCache, blendshapeblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }
            });

            // Re-compute the new blob assets
            combinedJH.Complete();

            // Update the BlobAssetStore
            using (var simpleMeshSettings = simpleMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < simpleMeshSettings.Length; i++)
                {
                    simpleMeshContext.AddComputedBlobAsset(simpleMeshSettings[i].hash, simpleblobs[simpleMeshSettings[i].blobIndex]);
                }
            }
            using (var litMeshSettings = litMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < litMeshSettings.Length; i++)
                {
                    litMeshContext.AddComputedBlobAsset(litMeshSettings[i].hash, litblobs[litMeshSettings[i].blobIndex]);
                }
            }
            using (var meshSettings = blendShapeContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < meshSettings.Length; i++)
                {
                    blendShapeContext.AddComputedBlobAsset(meshSettings[i].hash, blendshapeblobs[meshSettings[i].blobIndex]);
                }
            }
            using (var meshSettings = skinnedMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < meshSettings.Length; i++)
                {
                    skinnedMeshContext.AddComputedBlobAsset(meshSettings[i].hash, skinnedMeshBlobs[meshSettings[i].blobIndex]);
                }
            }

            // Use blob assets in the conversion
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var entity     = GetPrimaryEntity(uMesh);
                bool addBounds = false;
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), 0);
                    simpleMeshContext.GetBlobAsset(hash128, out var blob);
                    DstEntityManager.AddComponentData(entity, new SimpleMeshRenderData()
                    {
                        Mesh = blob
                    });

                    addBounds = true;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), 0);
                    litMeshContext.GetBlobAsset(hash128, out var blob);
                    DstEntityManager.AddComponentData(entity, new LitMeshRenderData()
                    {
                        Mesh = blob
                    });

                    addBounds = true;
                }
                if (addBounds)
                {
                    DstEntityManager.AddComponentData(entity, new MeshBounds
                    {
                        Bounds = new AABB
                        {
                            Center  = uMesh.bounds.center,
                            Extents = uMesh.bounds.extents
                        }
                    });
                }
                if (uMesh.blendShapeCount > 0)
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.blendShapeCount);
                    blendShapeContext.GetBlobAsset(hash128, out var blendShapeBlob);
                    DstEntityManager.AddComponentData(entity, new MeshBlendShapeData()
                    {
                        BlendShapeDataRef = blendShapeBlob
                    });
                }

                if (uMesh.bindposes.Length > 0)
                {
                    var skinnedDataHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                      (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.bindposes.Length.GetHashCode());
                    skinnedMeshContext.GetBlobAsset(skinnedDataHash, out var skinnedMeshBlob);
                    DstEntityManager.AddComponentData(entity, new SkinnedMeshRenderData()
                    {
                        SkinnedMeshDataRef = skinnedMeshBlob
                    });
                }
            });

            simpleMeshContext.Dispose();
            litMeshContext.Dispose();
            blendShapeContext.Dispose();
            simpleblobs.Dispose();
            litblobs.Dispose();
            blendshapeblobs.Dispose();
            skinnedMeshBlobs.Dispose();
        }