Example #1
0
        public void Operate(
            ref TurtleState currentState,
            NativeArray <TurtleMeshAllocationCounter> meshSizeCounterPerSubmesh,
            int indexInString,
            SymbolString <float> sourceString,
            NativeArray <TurtleOrganTemplate.Blittable> allOrgans,
            NativeList <TurtleOrganInstance> targetOrganInstances,
            TurtleVolumetricHandles volumetricHandles,
            EntityCommandBuffer spawningEntityBuffer)
        {
            switch (operationType)
            {
            case TurtleOperationType.BEND_TOWARDS:
                bendTowardsOperation.Operate(ref currentState, indexInString, sourceString);
                break;

            case TurtleOperationType.ADD_ORGAN:
                meshOperation.Operate(ref currentState, meshSizeCounterPerSubmesh, indexInString, sourceString, allOrgans, targetOrganInstances, volumetricHandles.durabilityWriter);
                break;

            case TurtleOperationType.INSTANTIATE_ENTITY:
                instantiateOperator.Operate(ref currentState, indexInString, sourceString, spawningEntityBuffer, volumetricHandles.durabilityWriter.localToWorldTransformation);
                break;

            case TurtleOperationType.ROTATE:
                rotationOperation.Operate(ref currentState, indexInString, sourceString);
                break;

            case TurtleOperationType.SCALE_TRANSFORM:
                scaleOperation.Operate(ref currentState, indexInString, sourceString);
                break;

            case TurtleOperationType.SCALE_THICCNESS:
                thiccnessOperation.Operate(ref currentState, indexInString, sourceString);
                break;

            case TurtleOperationType.VOLUMETRIC_RESOURCE:
                volumetricDiffusionOperation.Operate(ref currentState, indexInString, sourceString, volumetricHandles);
                break;

            default:
                break;
            }
            return;
        }
        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();
        }
        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();
        }
            public void Execute()
            {
                for (int symbolIndex = 0; symbolIndex < symbols.Length; symbolIndex++)
                {
                    var symbol = symbols[symbolIndex];
                    if (symbol == branchStartChar)
                    {
                        nativeTurtleStack.Push(currentState);
                        continue;
                    }
                    if (symbol == branchEndChar)
                    {
                        currentState = nativeTurtleStack.Pop();
                        continue;
                    }
                    if (customRules.hasIdentifiers && customRules.identifier == symbol)
                    {
                        currentState.organIdentity = new UIntFloatColor32(symbols.parameters[symbolIndex, 0]);
                        continue;
                    }
                    if (operationsByKey.TryGetValue(symbol, out var operation))
                    {
                        operation.Operate(
                            ref currentState,
                            newMeshSizeBySubmesh,
                            symbolIndex,
                            symbols,
                            organData,
                            organInstances,
                            volumetricHandles,
                            spawnEntityBuffer);
                        if (hasVolumetricDestruction && customRules.hasAutophagy && operation.operationType == TurtleOperationType.ADD_ORGAN)
                        {
                            // check for an operation which may have changed the position of the turtle
                            var turtlePosition = currentState.transformation.MultiplyPoint(Vector3.zero); // extract transformation
                            var voxelIndex     = volumetricHandles.durabilityWriter.GetVoxelIndexFromLocalSpace(turtlePosition);
                            if (voxelIndex.IsValid)
                            {
                                var lastDestroyCommandTime = volumetricDestructionTimestamps[voxelIndex.Value];
                                if (lastDestroyCommandTime >= earliestValidDestructionCommand)
                                {
                                    symbols[symbolIndex] = customRules.autophagicSymbol;
                                    // TODO: can skipping over this whole branching structure work here? could save some time
                                }
                            }
                        }
                    }
                }
                var totalVertexes = 0;
                var totalIndexes  = 0;

                for (int i = 0; i < newMeshSizeBySubmesh.Length; i++)
                {
                    var meshSize = newMeshSizeBySubmesh[i];
                    meshSize.indexInVertexes  = totalVertexes;
                    meshSize.indexInTriangles = totalIndexes;
                    totalVertexes            += meshSize.totalVertexes;
                    totalIndexes           += meshSize.totalTriangleIndexes;
                    newMeshSizeBySubmesh[i] = meshSize;
                }
            }