コード例 #1
0
        public DoubleBufferNativeWritableHandle GetNextNativeWritableHandle(
            Matrix4x4 localToWorldTransform,
            ref JobHandleWrapper dependency)
        {
            if (IsDisposed)
            {
                throw new System.ObjectDisposedException("DoubleBufferModifierHandle", "Tried to write a modification via a disposed writing handle");
            }
            UnityEngine.Profiling.Profiler.BeginSample("volume clearing");
            if (!newDataIsAvailable)
            {
                // Only swap data if the old data hasn't been picked up yet.
                //  just update the new data where it is
                mostRecentDataInA  = !mostRecentDataInA;
                newDataIsAvailable = true;
            }
            var mostRecentVolumeData = mostRecentDataInA ? valuesA : valuesB;
            var volumeClearJob       = new NativeArrayClearJob
            {
                newValue   = 0f,
                writeArray = mostRecentVolumeData
            };

            dependency      = volumeClearJob.Schedule(mostRecentVolumeData.Length, 10000, dependency + writeDependency);
            writeDependency = dependency;

            UnityEngine.Profiling.Profiler.EndSample();

            return(new DoubleBufferNativeWritableHandle(
                       mostRecentVolumeData,
                       voxelLayout,
                       localToWorldTransform));
        }
コード例 #2
0
        public override void RemoveEffects(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency)
        {
            var layout             = layerData.VoxelLayout;
            var subtractCleanupJob = new NativeArrayAdditionNegativeProtection
            {
                allBaseMarkers    = layerData,
                layerToAdd        = newValues,
                layerMultiplier   = -1,
                markerLayerIndex  = doubleBufferedLayerIndex,
                totalLayersInBase = layout.dataLayerCount
            };

            dependency = subtractCleanupJob.Schedule(layout.totalVoxels, 1000, dependency + writeDependency);
        }
コード例 #3
0
        /// <summary>
        /// takes in a by-voxel data array. returns another array of the same format with the diffused results.
        ///     may modify the values in the input array. may return the input array. will handle disposing the input
        ///     array if not returned.
        /// </summary>
        public static void ComputeDiffusion(
            VolumetricWorldVoxelLayout voxelLayout,
            DoubleBuffered <float> layerData,
            NativeArray <float> diffusionConstantMultipliers,
            float minimumDiffusionConstantMultiplier,
            float deltaTime,
            float diffusionConstant,
            ref JobHandleWrapper dependecy)
        {
            var combinedDiffusionFactor = deltaTime * diffusionConstant;

            if (combinedDiffusionFactor >= 1f / 6)
            {
                throw new System.ArgumentException("diffusion factor cannot exceed the connectivity of each node");
            }

            var adjacencyVectors = new NativeArray <Vector3Int>(new[]
            {
                new Vector3Int(1, 0, 0),
                new Vector3Int(-1, 0, 0),
                new Vector3Int(0, 1, 0),
                new Vector3Int(0, -1, 0),
                new Vector3Int(0, 0, 1),
                new Vector3Int(0, 0, -1),
            }, Allocator.TempJob);

            var diffuseJob = new VoxelAdjacencyResourceConservingBoundaryComputeJob
            {
                sourceDiffusionValues = layerData.CurrentData,
                targetDiffusionValues = layerData.NextData,

                diffusionConstantAdjusters         = diffusionConstantMultipliers,
                minimumDiffusionConstantMultiplier = minimumDiffusionConstantMultiplier,
                maximumDiffsuionConstant           = 1 / 7f,

                adjacencyVectors = adjacencyVectors,

                voxelLayout = voxelLayout,

                diffusionConstant = combinedDiffusionFactor
            };

            dependecy = diffuseJob.Schedule(layerData.CurrentData.Length, 1000, dependecy);
            layerData.Swap();

            adjacencyVectors.Dispose(dependecy);
        }
コード例 #4
0
        public virtual bool ApplyLayerWideUpdate(VoxelWorldVolumetricLayerData data, float deltaTime, ref JobHandleWrapper dependecy)
        {
            if (effects.Length <= 0)
            {
                return(false);
            }


            var voxelLayout = data.VoxelLayout;
            var copyInData  = new NativeArray <float>(voxelLayout.totalVoxels, Allocator.TempJob);

            var copyInJob = new CopyVoxelToWorkingDataJob
            {
                layerData  = data,
                targetData = copyInData,
                layerId    = voxelLayerId
            };

            dependecy = copyInJob.Schedule(copyInData.Length, 1000, dependecy);

            var swapSpace   = new NativeArray <float>(voxelLayout.totalVoxels, Allocator.TempJob);
            var workingData = new DoubleBuffered <float>(copyInData, swapSpace);

            var changed = false;

            foreach (var effect in effects)
            {
                if (effect.ApplyEffectToLayer(workingData, data, deltaTime, ref dependecy))
                {
                    changed = true;
                }
            }

            if (changed)
            {
                var copyBackJob = new CopyWorkingDataToVoxels
                {
                    layerData  = data,
                    sourceData = workingData.CurrentData,
                    layerId    = this.voxelLayerId
                };
                dependecy = copyBackJob.Schedule(workingData.CurrentData.Length, 1000, dependecy);
                workingData.Dispose(dependecy);
            }

            return(changed);
        }
コード例 #5
0
        public TurtleStringReadingCompletable(
            Mesh targetMesh,
            int totalSubmeshes,
            DependencyTracker <SymbolString <float> > symbols,
            DependencyTracker <NativeTurtleData> nativeData,
            int branchStartChar,
            int branchEndChar,
            TurtleState defaultState,
            CustomRuleSymbols customSymbols,
            TurtleVolumeWorldReferences volumetrics,
            Matrix4x4 localToWorldTransform)
        {
            this.targetMesh = targetMesh;
            this.nativeData = nativeData;

            UnityEngine.Profiling.Profiler.BeginSample("turtling job");

            JobHandleWrapper volumetricJobHandle = currentJobHandle;
            var volumetricHandles = new TurtleVolumetricHandles
            {
                durabilityWriter = volumetrics.durabilityWriter.GetNextNativeWritableHandle(localToWorldTransform, ref volumetricJobHandle),
                universalWriter  = volumetrics.universalLayerWriter.GetNextNativeWritableHandle(localToWorldTransform),
                volumetricData   = volumetrics.world.NativeVolumeData.openReadData.AsReadOnly()
            };

            currentJobHandle = volumetricJobHandle;


            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            var tmpHelperStack = new TmpNativeStack <TurtleState>(50, Allocator.TempJob);

            organInstances       = new NativeList <TurtleOrganInstance>(100, Allocator.TempJob);
            newMeshSizeBySubmesh = new NativeArray <TurtleMeshAllocationCounter>(totalSubmeshes, Allocator.TempJob);
            UnityEngine.Profiling.Profiler.EndSample();

            NativeArray <float> destructionCommandTimestamps;

            if (volumetrics.damageFlags != null)
            {
                destructionCommandTimestamps = volumetrics.damageFlags.GetDestructionCommandTimestampsReadOnly();
            }
            else
            {
                destructionCommandTimestamps = new NativeArray <float>(0, Allocator.TempJob);
            }

            var entitySpawningSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem <BeginSimulationEntityCommandBufferSystem>();
            var entitySpawnBuffer    = entitySpawningSystem.CreateCommandBuffer();


            var turtleCompileJob = new TurtleCompilationJob
            {
                symbols         = symbols.Data,
                operationsByKey = nativeData.Data.operationsByKey,
                organData       = nativeData.Data.allOrganData,

                organInstances       = organInstances,
                newMeshSizeBySubmesh = newMeshSizeBySubmesh,
                spawnEntityBuffer    = entitySpawnBuffer,

                nativeTurtleStack = tmpHelperStack,

                branchStartChar = branchStartChar,
                branchEndChar   = branchEndChar,

                currentState = defaultState,

                customRules = customSymbols,

                volumetricHandles               = volumetricHandles,
                hasVolumetricDestruction        = volumetrics.damageFlags != null,
                volumetricDestructionTimestamps = destructionCommandTimestamps,
                earliestValidDestructionCommand = volumetrics.damageFlags != null ? Time.time - volumetrics.damageFlags.timeCommandStaysActive : -1
            };

            currentJobHandle = turtleCompileJob.Schedule(currentJobHandle);
            volumetrics.world.NativeVolumeData.RegisterReadingDependency(currentJobHandle);
            entitySpawningSystem.AddJobHandleForProducer(currentJobHandle);
            volumetrics.damageFlags?.RegisterReaderOfDestructionFlags(currentJobHandle);
            volumetrics.durabilityWriter.RegisterWriteDependency(currentJobHandle);
            volumetrics.universalLayerWriter.RegisterWriteDependency(currentJobHandle);

            nativeData.RegisterDependencyOnData(currentJobHandle);
            symbols.RegisterDependencyOnData(currentJobHandle);

            currentJobHandle = tmpHelperStack.Dispose(currentJobHandle);
            if (volumetrics.damageFlags == null)
            {
                currentJobHandle = destructionCommandTimestamps.Dispose(currentJobHandle);
            }
            UnityEngine.Profiling.Profiler.EndSample();
        }
コード例 #6
0
 public override bool ApplyEffectToLayer(DoubleBuffered <float> layerData, VoxelWorldVolumetricLayerData readonlyLayerData, float deltaTime, ref JobHandleWrapper dependecy)
 {
     ComputeDiffusion(layerData, readonlyLayerData.VoxelLayout, deltaTime, globalDiffusionConstant, ref dependecy);
     return(true);
 }
コード例 #7
0
 /// <summary>
 /// remove any persistent effects this handle has on the world. <br/>
 ///     For a double buffered handle, this means subtracting the total sum which this
 ///     handle has contributed to the volume world
 /// </summary>
 public abstract void RemoveEffects(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency);
コード例 #8
0
 /// <summary>
 /// Plays back any changes that have been cached inside this modification handle
 /// </summary>
 /// <param name="layerData">the layer data to apply changes to</param>
 /// <param name="dependency">job handle</param>
 /// <returns>true if any changes were available to be applied, false otherwise</returns>
 public abstract bool ConsolidateChanges(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency);
コード例 #9
0
 public override void RemoveEffects(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency)
 {
     // command buffer has no record of the effects it has had on the world
     return;
 }
コード例 #10
0
        public override bool ConsolidateChanges(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency)
        {
            // TODO: consider skipping if writeDependency is not complete yet. should the job chain keep extending, or should
            //  consolidation be deffered?
            if (!newDataIsAvailable)
            {
                return(false);
            }
            var consolidationJob = new VoxelMarkerConsolidation
            {
                allBaseMarkers   = layerData,
                oldMarkerLevels  = oldValues,
                newMarkerLevels  = newValues,
                markerLayerIndex = doubleBufferedLayerIndex,
            };

            dependency = consolidationJob.Schedule(newValues.Length, 1000, dependency + writeDependency);
            RegisterReadDependency(dependency);
            newDataIsAvailable = false;
            return(true);
        }
コード例 #11
0
        public override bool ConsolidateChanges(VoxelWorldVolumetricLayerData layerData, ref JobHandleWrapper dependency)
        {
            if (!newDataIsAvailable)
            {
                return(false);
            }
            var commandPlaybackJob = new LayerModificationCommandPlaybackJob
            {
                commands    = modificationCommands,
                dataArray   = layerData,
                voxelLayout = voxelLayout
            };

            dependency = commandPlaybackJob.Schedule(dependency + writeDependency);
            RegisterReadDependency(dependency);
            newDataIsAvailable = false;
            return(true);
        }
コード例 #12
0
 /// <summary>
 /// apply whatever effect this transform applies to the layer.
 ///
 /// </summary>
 /// <param name="data"></param>
 /// <param name="deltaTime"></param>
 /// <param name="dependecy"></param>
 /// <returns>true if any changes were applied</returns>
 public abstract bool ApplyEffectToLayer(DoubleBuffered <float> layerData, VoxelWorldVolumetricLayerData readonlyLayerData, float deltaTime, ref JobHandleWrapper dependecy);
コード例 #13
0
        private void RepairDamage(DoubleBuffered <float> layerData, VoxelWorldVolumetricLayerData readonlyLayerData, float deltaTime, ref JobHandleWrapper dependency)
        {
            damageDataUpdateDependency?.Complete();
            var voxelLayers  = readonlyLayerData;
            var damageValues = layerData.CurrentData; // this is not a parallized job, so edits are made in-place
            var dampenDamage = new DampenDamageJob
            {
                voxelLayerData               = voxelLayers,
                voxelLayout                  = voxelLayers.VoxelLayout,
                volumetricDamageValues       = damageValues,
                durabilityRegenerationFactor = Mathf.Exp(regenerationPerSecondAsPercentOfDurability * Time.deltaTime) - 1
            };

            dependency = JobHandle.CombineDependencies(destructionFlagReadDependencies, dependency);
            dependency = dampenDamage.Schedule(damageValues.Length, 1000, dependency);
        }
コード例 #14
0
        private void UpdateDestructionFlags(DoubleBuffered <float> layerData, VoxelWorldVolumetricLayerData readonlyLayerData, float deltaTime, ref JobHandleWrapper dependency)
        {
            damageDataUpdateDependency?.Complete();

            var damageValues = layerData.CurrentData; // this is not a parallized job, so edits are made in-place

            var voxelLayers = readonlyLayerData;
            var updateJob   = new UpdatePlantDestructionFlags
            {
                voxelLayerData    = voxelLayers,
                flagCapLayerIndex = voxelResourceCapLayerId,
                voxelLayout       = voxelLayers.VoxelLayout,

                volumetricDamageValues          = damageValues,
                volumetricDestructionTimestamps = volumetricDestructionTimestamps,
                currentTime = Time.time,
                durabilityRegenerationFactor = Mathf.Exp(regenerationPerSecondAsPercentOfDurability * deltaTime) - 1
            };

            dependency = JobHandle.CombineDependencies(destructionFlagReadDependencies, dependency);

            damageDataUpdateDependency = dependency = updateJob.Schedule(damageValues.Length, 1000, dependency);
        }
コード例 #15
0
 public override bool ApplyEffectToLayer(DoubleBuffered <float> layerData, VoxelWorldVolumetricLayerData readonlyLayerData, float deltaTime, ref JobHandleWrapper dependecy)
 {
     UpdateDestructionFlags(layerData, readonlyLayerData, deltaTime, ref dependecy);
     return(true);
 }