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; } }