Ejemplo n.º 1
0
        public static LSystemStepper FloatSystem(
            IEnumerable <string> rules,
            string[] globalParameters = null,
            string includedCharacters = "[]ABCDEFD",
            int branchOpenSymbol      = '[',
            int branchCloseSymbol     = ']')
        {
            var compiledRules = RuleParser.CompileRules(
                rules,
                out var nativeRuleData,
                branchOpenSymbol, branchCloseSymbol,
                globalParameters
                );

            var customSymbols = new CustomRuleSymbols
            {
                branchOpenSymbol  = branchOpenSymbol,
                branchCloseSymbol = branchCloseSymbol
            };

            return(new LSystemStepper(
                       compiledRules,
                       nativeRuleData,
                       customSymbols,
                       globalParameters?.Length ?? 0,
                       includedContextualCharactersByRuleIndex: new[] { new HashSet <int>(includedCharacters.Select(x => (int)x)) }
                       ));
        }
Ejemplo n.º 2
0
        public LSystemStepper(
            IEnumerable <BasicRule> rules,
            SystemLevelRuleNativeData nativeRuleData,
            CustomRuleSymbols customSymbols,
            int expectedGlobalParameters = 0,
            ISet <int>[] includedContextualCharactersByRuleIndex = null)
        {
            GlobalParameters = expectedGlobalParameters;

            this.customSymbols = customSymbols;

            includedCharacters = includedContextualCharactersByRuleIndex == null ? new HashSet <int> [0] : includedContextualCharactersByRuleIndex;

            rulesByTargetSymbol = new Dictionary <int, IList <BasicRule> >();
            foreach (var rule in rules)
            {
                var targetSymbols = rule.TargetSymbol;
                if (!rulesByTargetSymbol.TryGetValue(targetSymbols, out var ruleList))
                {
                    rulesByTargetSymbol[targetSymbols] = ruleList = new List <BasicRule>();
                }
                ruleList.Add(rule);
            }

            var maxMemoryRequirementsPerSymbol = new NativeHashMap <int, MaxMatchMemoryRequirements>(rulesByTargetSymbol.Keys.Count(), Allocator.Persistent);

            foreach (var symbol in rulesByTargetSymbol.Keys.ToList())
            {
                rulesByTargetSymbol[symbol] = rulesByTargetSymbol[symbol]
                                              .OrderByDescending(x =>
                                                                 (x.ContextPrefix.IsValid ? x.ContextPrefix.graphNodeMemSpace.length : 0) +
                                                                 (x.ContextSuffix.IsCreated ? x.ContextSuffix.graphNodeMemSpace.length : 0))
                                              .ToList();

                var maxParamCapturedByAnyRule = rulesByTargetSymbol[symbol]
                                                .Select(x => x.CapturedLocalParameterCount)
                                                .DefaultIfEmpty().Max();
                // Greedy estimate for maximum possible parameter match.
                //  there need to be enough space for any rule's parameters to fit, since we don't know which ones will match.
                var maximumPossibleParameterMatch = maxParamCapturedByAnyRule;
                if (maximumPossibleParameterMatch > ushort.MaxValue)
                {
                    throw new LSystemRuntimeException($"Rules with more than {ushort.MaxValue} captured local parameters over all conditional options");
                }
                maxMemoryRequirementsPerSymbol[symbol] = new MaxMatchMemoryRequirements
                {
                    maxParameters = maximumPossibleParameterMatch
                };
            }

            nativeRuleData.blittableRulesByTargetSymbol = NativeOrderedMultiDictionary <BasicRule.Blittable> .WithMapFunction(
                rulesByTargetSymbol,
                rule => rule.AsBlittable(),
                Allocator.Persistent);

            nativeRuleData.maxParameterMemoryRequirementsPerSymbol = maxMemoryRequirementsPerSymbol;
            this.nativeRuleData = new DependencyTracker <SystemLevelRuleNativeData>(nativeRuleData);
        }
Ejemplo n.º 3
0
        public LSystemStepper CompileSystem(Dictionary <string, string> globalCompileTimeOverrides = null)
        {
            UnityEngine.Profiling.Profiler.BeginSample("L System compilation");

            var openSymbol  = GetSymbol(originFile, '[');
            var closeSymbol = GetSymbol(originFile, ']');

            var allReplacementDirectives = GetCompileTimeReplacementsWithOverrides(globalCompileTimeOverrides);

            var compiledRules = CompileAllRules(
                allReplacementDirectives,
                out var nativeRuleData,
                openSymbol, closeSymbol);

            var includedByFile = allFiles.data
                                 .Select(x => new HashSet <int>(x.GetAllIncludedContextualSymbols()))
                                 .ToArray();

            var customSymbols = new CustomRuleSymbols();

            customSymbols.branchOpenSymbol  = openSymbol;
            customSymbols.branchCloseSymbol = closeSymbol;

            foreach (var file in allFiles.data)
            {
                file.SetCustomRuleSymbols(ref customSymbols);
            }
            if (allReplacementDirectives.TryGetValue("diffusionStepsPerStep", out var defineValue))
            {
                if (!int.TryParse(defineValue, out var stepsPerStep))
                {
                    throw new LinkException(LinkExceptionType.BAD_GLOBAL_PARAMETER, $"global parameter 'diffusionStepsPerStep' is defined, but is not an integer. this parameter must be an integer: '{defineValue}'");
                }
                customSymbols.diffusionStepsPerStep = stepsPerStep;
            }
            customSymbols.independentDiffusionUpdate = false;
            customSymbols.diffusionConstantRuntimeGlobalMultiplier = 1f;
            if (allReplacementDirectives.TryGetValue("independentDiffusionStep", out defineValue))
            {
                if (!bool.TryParse(defineValue, out var stepsIndependent))
                {
                    throw new LinkException(LinkExceptionType.BAD_GLOBAL_PARAMETER, $"global parameter 'independentDiffusionStep' is defined, but is not a boolean. this parameter must be either 'true' or 'false': '{defineValue}'");
                }
                customSymbols.independentDiffusionUpdate = stepsIndependent;
            }

            var result = new LSystemStepper(
                compiledRules,
                nativeRuleData,
                customSymbols,
                expectedGlobalParameters: allGlobalRuntimeParams.Count,
                includedContextualCharactersByRuleIndex: includedByFile
                );

            UnityEngine.Profiling.Profiler.EndSample();
            return(result);
        }
        public JobHandle ApplySunlightToSymbols(
            LSystemState <float> systemState,
            CustomRuleSymbols customSymbols)
        {
            var idsNativeArray = uniqueSunlightAssignments.ActiveData;

            if (idsNativeArray == null)
            {
                Debug.LogError("no sunlight data available");
                return(default);
        public DiffusionWorkingDataPack(int estimatedEdges, int estimatedNodes, int estimatedUniqueResources, CustomRuleSymbols customSymbols, Allocator allocator = Allocator.TempJob)
        {
            this.customSymbols = customSymbols;
            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            allEdges = new NativeList <DiffusionEdge>(estimatedEdges, allocator);
            nodes    = new NativeList <DiffusionNode>(estimatedNodes, allocator);
            UnityEngine.Profiling.Profiler.EndSample();

            nodeMaxCapacities = new NativeList <float>(estimatedNodes * estimatedUniqueResources, allocator);
            nodeAmountsListA  = new NativeList <float>(estimatedNodes * estimatedUniqueResources, allocator);
            nodeAmountsListB  = new NativeList <float>(estimatedNodes * estimatedUniqueResources, allocator);
            IsCreated         = true;
        }
Ejemplo n.º 6
0
        public LSystemParameterSizeCountingCompletable(
            LSystemState <float> systemState,
            DependencyTracker <SystemLevelRuleNativeData> lSystemNativeData,
            float[] globalParameters,
            ISet <int>[] includedCharactersByRuleIndex,
            CustomRuleSymbols customSymbols,
            JobHandle parameterModificationJobDependency)
        {
            currentJobHandle = default;

            this.globalParameters            = globalParameters;
            this.paramModificationDependency = parameterModificationJobDependency;

            this.systemState   = systemState;
            this.customSymbols = customSymbols;
            nativeData         = lSystemNativeData;

            // 1.
            UnityEngine.Profiling.Profiler.BeginSample("Paramter counts");

            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            matchSingletonData = new NativeArray <LSystemSingleSymbolMatchData>(systemState.currentSymbols.Data.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            parameterTotalSum  = new NativeArray <int>(1, Allocator.TempJob);
            UnityEngine.Profiling.Profiler.EndSample();

            var memorySizeJob = new SymbolStringMemoryRequirementsJob
            {
                matchSingletonData          = matchSingletonData,
                memoryRequirementsPerSymbol = nativeData.Data.maxParameterMemoryRequirementsPerSymbol,
                parameterTotalSum           = parameterTotalSum,
                sourceSymbolString          = systemState.currentSymbols.Data
            };

            currentJobHandle = memorySizeJob.Schedule();
            systemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);


            UnityEngine.Profiling.Profiler.EndSample();

            // 2.1
            UnityEngine.Profiling.Profiler.BeginSample("branch cache");
            branchingCache = new SymbolStringBranchingCache(
                customSymbols.branchOpenSymbol,
                customSymbols.branchCloseSymbol,
                includedCharactersByRuleIndex,
                nativeData.Data);
            branchingCache.BuildJumpIndexesFromSymbols(systemState.currentSymbols);
            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 7
0
 private JobHandle ScheduleIndependentDiffusion(JobHandle dependency, CustomRuleSymbols customSymbols)
 {
     // diffusion is only dependent on the target symbol data. don't need to register as dependent on native data/source symbols
     if (customSymbols.hasDiffusion && customSymbols.independentDiffusionUpdate)
     {
         diffusionHelper = new DiffusionWorkingDataPack(10, 5, 2, customSymbols, Allocator.TempJob);
         var diffusionJob = new IndependentDiffusionReplacementJob
         {
             inPlaceSymbols = target,
             customSymbols  = customSymbols,
             working        = diffusionHelper
         };
         dependency = diffusionJob.Schedule(dependency);
     }
     return(dependency);
 }
Ejemplo n.º 8
0
        private JobHandle ScheduleAutophagyJob(JobHandle dependency, CustomRuleSymbols customSymbols)
        {
            // autophagy is only dependent on the source string. don't need to register as dependent on native data/source symbols
            if (customSymbols.hasAutophagy)
            {
                var helperStack   = new TmpNativeStack <AutophagyPostProcess.BranchIdentity>(10, Allocator.TempJob);
                var autophagicJob = new AutophagyPostProcess
                {
                    symbols           = target,
                    lastIdentityStack = helperStack,
                    customSymbols     = customSymbols
                };

                dependency = autophagicJob.Schedule(dependency);
                dependency = helperStack.Dispose(dependency);
            }
            return(dependency);
        }
Ejemplo n.º 9
0
        public TurtleInterpretor(
            List <TurtleOperationSet> operationSets,
            TurtleState defaultState,
            LinkedFileSet linkedFiles,
            CustomRuleSymbols customSymbols,
            OrganVolumetricWorld volumetricWorld,
            VoxelCapReachedTimestampEffect damageCapFlags,
            char startChar = '[', char endChar = ']')
        {
            foreach (var operationSet in operationSets)
            {
                operationSet.InternalCacheOperations();
            }

            var totalRequirements = operationSets.Select(x => x.DataReqs).Aggregate(new TurtleDataRequirements(), (agg, req) => agg + req);
            var nativeData        = new NativeTurtleData(totalRequirements);
            var nativeWriter      = new TurtleNativeDataWriter();

            foreach (var operationSet in operationSets)
            {
                operationSet.WriteIntoNativeData(nativeData, nativeWriter);
            }

            submeshMaterials = nativeWriter.materialsInOrder.ToArray();

            nativeData.operationsByKey = new NativeHashMap <int, TurtleOperation>(nativeWriter.operators.Count(), Allocator.Persistent);
            foreach (var ops in nativeWriter.operators)
            {
                var realSymbol = linkedFiles.GetSymbolFromRoot(ops.characterInRootFile);
                nativeData.operationsByKey[realSymbol] = ops.operation;
            }

            branchStartChar    = linkedFiles.GetSymbolFromRoot(startChar);
            branchEndChar      = linkedFiles.GetSymbolFromRoot(endChar);
            this.customSymbols = customSymbols;


            nativeDataTracker = new DependencyTracker <NativeTurtleData>(nativeData);
            this.defaultState = defaultState;

            this.volumetricWorld = volumetricWorld;
            this.damageCapFlags  = damageCapFlags;
            RefreshVolumetricWriters();
        }
Ejemplo n.º 10
0
        private JobHandle ScheduleIdAssignmentJob(
            JobHandle dependency,
            CustomRuleSymbols customSymbols,
            LSystemState <float> lastSystemState)
        {
            // identity assignment job is not dependent on the source string or any other native data. can skip assigning it as a dependent
            maxIdReached = new NativeArray <uint>(1, Allocator.TempJob);
            var identityAssignmentJob = new IdentityAssignmentPostProcessRule
            {
                targetData            = target,
                maxIdentityId         = maxIdReached,
                customSymbols         = customSymbols,
                lastMaxIdReached      = lastSystemState.maxUniqueOrganIds,
                uniquePlantId         = lastSystemState.uniquePlantId,
                originOfUniqueIndexes = lastSystemState.firstUniqueOrganId,
            };

            return(identityAssignmentJob.Schedule(dependency));
        }
        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();
        }
Ejemplo n.º 12
0
        public LSystemSymbolReplacementCompletable(
            Unity.Mathematics.Random randResult,
            LSystemState <float> lastSystemState,
            int totalNewSymbolSize,
            int totalNewParamSize,
            NativeArray <float> globalParamNative,
            NativeArray <float> tmpParameterMemory,
            NativeArray <LSystemSingleSymbolMatchData> matchSingletonData,
            DependencyTracker <SystemLevelRuleNativeData> nativeData,
            SymbolStringBranchingCache branchingCache,
            CustomRuleSymbols customSymbols)
        {
            this.lastSystemState    = lastSystemState;
            this.matchSingletonData = matchSingletonData;
            this.branchingCache     = branchingCache;
            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            target = new SymbolString <float>(totalNewSymbolSize, totalNewParamSize, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            this.randResult = randResult;

            this.nativeData = nativeData;

            // 5
            UnityEngine.Profiling.Profiler.BeginSample("generating replacements");

            var replacementJob = new RuleReplacementJob
            {
                globalParametersArray = globalParamNative,

                parameterMatchMemory = tmpParameterMemory,
                matchSingletonData   = matchSingletonData,

                sourceData            = lastSystemState.currentSymbols.Data,
                structExpressionSpace = nativeData.Data.structExpressionMemorySpace,
                globalOperatorData    = nativeData.Data.dynamicOperatorMemory,
                replacementSymbolData = nativeData.Data.replacementsSymbolMemorySpace,
                outcomeData           = nativeData.Data.ruleOutcomeMemorySpace,

                targetData = target,
                blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol,
                branchingCache = branchingCache,
                customSymbols  = customSymbols
            };

            currentJobHandle = replacementJob.Schedule(
                matchSingletonData.Length,
                100
                );

            if (customSymbols.hasDiffusion && !customSymbols.independentDiffusionUpdate)
            {
                diffusionHelper = new DiffusionWorkingDataPack(10, 5, 2, customSymbols, Allocator.TempJob);
                var diffusionJob = new ParallelDiffusionReplacementJob
                {
                    matchSingletonData = matchSingletonData,
                    sourceData         = lastSystemState.currentSymbols.Data,
                    targetData         = target,
                    customSymbols      = customSymbols,
                    working            = diffusionHelper
                };
                currentJobHandle = JobHandle.CombineDependencies(
                    currentJobHandle,
                    diffusionJob.Schedule()
                    );
            }
            // only parameter modifications beyond this point
            lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);

            currentJobHandle = JobHandle.CombineDependencies(
                JobHandle.CombineDependencies(
                    ScheduleIdAssignmentJob(currentJobHandle, customSymbols, lastSystemState),
                    ScheduleIndependentDiffusion(currentJobHandle, customSymbols)
                    ),
                JobHandle.CombineDependencies(
                    ScheduleAutophagyJob(currentJobHandle, customSymbols),
                    ScheduleImmaturityJob(currentJobHandle)
                    ));

            UnityEngine.Profiling.Profiler.EndSample();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="lastSystemState"></param>
        /// <param name="lSystemNativeData"></param>
        /// <param name="globalParameters"></param>
        /// <param name="maxMemoryRequirementsPerSymbol"></param>
        /// <param name="branchOpenSymbol"></param>
        /// <param name="branchCloseSymbol"></param>
        /// <param name="includedCharactersByRuleIndex"></param>
        /// <param name="customSymbols"></param>
        /// <param name="parameterModificationJobDependency">A dependency on a job which only makes changes to the parameters of the source symbol string.
        ///     the symbols themselves must be constant</param>
        public LSystemRuleMatchCompletable(
            NativeArray <LSystemSingleSymbolMatchData> matchSingletonData,
            int parameterTotalSum,
            SymbolStringBranchingCache branchingCache,
            LSystemState <float> lastSystemState,
            DependencyTracker <SystemLevelRuleNativeData> lSystemNativeData,
            float[] globalParameters,
            CustomRuleSymbols customSymbols,
            JobHandle parameterModificationJobDependency)
        {
            this.customSymbols   = customSymbols;
            this.lastSystemState = lastSystemState;
            randResult           = lastSystemState.randomProvider;
            nativeData           = lSystemNativeData;

            this.matchSingletonData = matchSingletonData;
            this.branchingCache     = branchingCache;

            // 1.
            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            tmpParameterMemory = new NativeArray <float>(parameterTotalSum, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            globalParamNative  = new NativeArray <float>(globalParameters, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            // 2.
            UnityEngine.Profiling.Profiler.BeginSample("matching");


            var prematchJob = new RuleCompleteMatchJob
            {
                matchSingletonData = matchSingletonData,

                sourceData         = lastSystemState.currentSymbols.Data,
                tmpParameterMemory = tmpParameterMemory,

                globalOperatorData = nativeData.Data.dynamicOperatorMemory,
                outcomes           = nativeData.Data.ruleOutcomeMemorySpace,
                globalParams       = globalParamNative,

                blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol,
                branchingCache = branchingCache,
                seed           = randResult.NextUInt()
            };

            var matchingJobHandle = prematchJob.ScheduleBatch(
                matchSingletonData.Length,
                100,
                parameterModificationJobDependency);


            UnityEngine.Profiling.Profiler.EndSample();

            // 4.
            UnityEngine.Profiling.Profiler.BeginSample("replacement counting");

            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            totalSymbolCount          = new NativeArray <int>(1, Allocator.Persistent);
            totalSymbolParameterCount = new NativeArray <int>(1, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            var totalSymbolLengthJob = new RuleReplacementSizeJob
            {
                matchSingletonData        = matchSingletonData,
                totalResultSymbolCount    = totalSymbolCount,
                totalResultParameterCount = totalSymbolParameterCount,
                sourceData    = lastSystemState.currentSymbols.Data,
                customSymbols = customSymbols
            };

            currentJobHandle = totalSymbolLengthJob.Schedule(matchingJobHandle);
            lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);

            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 14
0
 public virtual void SetCustomRuleSymbols(ref CustomRuleSymbols customSymbols)
 {
 }