예제 #1
0
 public override void Execute(ParameterBundle bundle)
 {
     if (dead)
     {
         return;
     }
     AnyExecute(bundle);
 }
 public ParameterBundle(ParameterBundle original)
 {
     //Make new dictionary and add values
     parameters = new Dictionary <string, object>(original.parameters.Count, original.parameters.Comparer);
     foreach (KeyValuePair <string, object> pair in original.parameters)
     {
         parameters.Add(pair.Key, pair.Value);
     }
 }
예제 #3
0
        // Encapsulates common functionality between Bake and Execute.
        protected void AnyExecute(ParameterBundle bundle)
        {
            Sentence           sentence;
            CharGameObjectDict implementations;
            RuleSet            rules;

            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules))
            {
                return;
            }

            // Count brackets to determine which sentence piece to pull into a new fork
            int bracketCount = 1;

            sentence.PushPosition();
            while (sentence.HasNext())
            {
                char c = sentence.Next();
                if (c == splitEndDelimiter)
                {
                    bracketCount--;
                }
                else if (c == symbol)
                {
                    bracketCount++;
                }
                if (bracketCount == 0)
                {
                    break;
                }
            }

            Sentence split = sentence.PopPositionAndCut();

            //call next recursion
            if (baked)
            {
                BakeNextModule(transform, sentence, implementations, rules, bundle);
                BakeNextModule(transform, split, implementations, rules, bundle);
            }
            else
            {
                EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle);
                EnqueueProcessNextModule(transform, split, implementations, rules, bundle);
            }

            Destroy(gameObject);
        }
예제 #4
0
        public bool GetPositionParameters(ParameterBundle bundle, out int generation, out Quaternion rotation)
        {
            bool success = true;

            if (!bundle.Get("Generation", out generation))
            {
                success = false;
                Debug.LogError("Default parameter 'Generation' missing.", gameObject);
            }
            if (!bundle.Get("Rotation", out rotation))
            {
                success = false;
                Debug.LogError("Default parameter 'Rotation' missing.", gameObject);
            }
            return(success);
        }
        /// <summary>
        /// Merge multiple ParameterBundles into one. Note that parameters with the same key will override each other and parameters with the same key but different value will be ignored
        /// </summary>
        /// <param name="bundles"></param>
        /// <returns></returns>
        public static ParameterBundle Merge(List <ParameterBundle> bundles)
        {
            ParameterBundle merged = new ParameterBundle();

            foreach (ParameterBundle bundle in bundles)
            {
                foreach (KeyValuePair <string, object> pair in bundle.parameters)
                {
                    if (!merged.Set(pair.Key, pair.Value))
                    {
                        merged.Put(pair.Key, pair.Value);
                    }
                }
            }
            return(merged);
        }
예제 #6
0
        // Entry point when pre-baking LSystem.
        public override void Bake(ParameterBundle bundle)
        {
            if ((filter = gameObject.GetComponent <MeshFilter>()) == null)
            {
                filter = gameObject.AddComponent <MeshFilter>();
            }
            if ((leafRenderer = gameObject.GetComponent <MeshRenderer>()) == null)
            {
                leafRenderer = gameObject.AddComponent <MeshRenderer>();
            }
            leafRenderer.material = leafMaterial;

            //Get parameters
            Quaternion         rotation;
            Sentence           sentence;
            CharGameObjectDict implementations;
            int     generation;
            RuleSet rules;

            // Check valid state for growing
            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules) ||
                !GetPositionParameters(bundle, out generation, out rotation))
            {
                return;
            }

            transform.position = previous.transform.position;
            transform.rotation = rotation;

            MeshFilter sharedFilter;

            if (bakedPrefabFilters.TryGetValue(prefabIdentifier, out sharedFilter))
            {
                filter.mesh = sharedFilter.sharedMesh;
            }
            else
            {
                UpdateMesh(1, offset);
                bakedPrefabFilters.Add(prefabIdentifier, filter);
            }
            if (setStaticOnComplete)
            {
                gameObject.isStatic = true;
            }

            BakeNextModule(transform, sentence, implementations, rules, bundle);
        }
예제 #7
0
        // Once ProcessNextModule has found an executable module
        public void ExecuteModule(Module previous, KeyValuePair <GameObject, Sentence> moduleSentancePair, ParameterBundle bundle, char symbol, bool baked)
        {
            if (previous == null)
            {
                return;                  // if object is destroyed externally
            }
            Profiler.BeginSample("LSystem.Module.ExecuteModule");

            if (moduleSentancePair.Key == null)
            {
                return;
            }

            ParameterBundle newBundle = new ParameterBundle(bundle);

            newBundle.SetOrPut("Sentence", moduleSentancePair.Value);

            GameObject moduleInstance = UnityEngine.Object.Instantiate(moduleSentancePair.Key);
            Module     module         = moduleInstance.GetComponent <Module>();

            module.previous = previous;
            moduleInstance.transform.SetParent(previous.transform, true);

            module.symbol = symbol;

            //Seeds are baked separately so their baked value must not be overwritten.
            //Is there a way to avoid this special case in module?
            if (module.GetType() != typeof(Seed))
            {
                module.baked = baked;
            }

            Profiler.EndSample();

            if (prefabIdentifier != null)
            {
                module.prefabIdentifier = prefabIdentifier;
            }
            if (baked)
            {
                module.Bake(newBundle);
            }
            else
            {
                module.Execute(newBundle);
            }
        }
예제 #8
0
        // Entry point when dynamically executing LSystem.
        public override void Execute(ParameterBundle bundle)
        {
            if ((filter = gameObject.GetComponent <MeshFilter>()) == null)
            {
                filter = gameObject.AddComponent <MeshFilter>();
            }
            if ((leafRenderer = gameObject.GetComponent <MeshRenderer>()) == null)
            {
                leafRenderer = gameObject.AddComponent <MeshRenderer>();
            }
            leafRenderer.material = leafMaterial;

            if (gameObject.activeSelf)
            {
                StartCoroutine(Grow(bundle));
            }
        }
예제 #9
0
        // Encapsulates common functionality between Bake and Execute.
        protected void AnyExecute(ParameterBundle bundle)
        {
            //try get relevant prams.
            bool               fatal = false;
            Sentence           sentence;
            CharGameObjectDict implementations;
            RuleSet            rules;

            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules))
            {
                fatal = true;
            }

            // Perform rotation on transform based.
            // Note that many rotations are not easily possible with this method. Needs to be improved.
            Quaternion rotation;

            if (bundle.Get("Rotation", out rotation))
            {
                //apply pitch yaw and roll to the rotation
                rotation = rotation * Quaternion.Euler(new Vector3(Random.Range(eulerAnglesMin.x, eulerAnglesMax.x),
                                                                   Random.Range(eulerAnglesMin.y, eulerAnglesMax.y),
                                                                   Random.Range(eulerAnglesMin.z, eulerAnglesMax.z)));
                bundle.Set("Rotation", rotation);
            }
            else
            {
                Debug.LogWarning("Default parameter 'Rotation' missing. Skipping Rotation", gameObject);
            }
            if (!fatal)
            {
                //Call next module
                if (baked)
                {
                    BakeNextModule(transform, sentence, implementations, rules, bundle);
                }
                else
                {
                    EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle);
                }
            }
            Destroy(gameObject); //once rotation  and next module clled we can destroy the object.
        }
예제 #10
0
        // Retrial for parameters common to most LSystems are wrapped here for convenience.
        public bool GetCoreParameters(ParameterBundle bundle, out Sentence sentence, out CharGameObjectDict implementations, out RuleSet rules)
        {
            bool success = true;

            if (!bundle.Get("Sentence", out sentence))
            {
                success = false;
                Debug.LogError("Default parameter 'Sentence' missing.", gameObject);
            }
            if (!bundle.Get("Implementations", out implementations))
            {
                success = false;
                Debug.LogError("Default parameter 'Implementations' missing.", gameObject);
            }
            if (!bundle.Get("RuleSet", out rules))
            {
                success = false;
                Debug.LogError("Default parameter 'RuleSet' missing.", gameObject);
            }
            return(success);
        }
예제 #11
0
        // Execute next module as a bake (no delay) operation.
        public void BakeNextModule(Transform caller, Sentence sentence,
                                   SerializableDictionary <char, GameObject> implementation, RuleSet rules, ParameterBundle bundle)
        {
            Module previous;

            if (this.ethereal)
            {
                // Since this module is ethereal we have to set the parent to this modules parent
                // Note that this behavior is recursive up to the first non ethereal module or null.
                previous = caller.parent.GetComponent <Module>();
            }
            else
            {
                previous = caller.GetComponent <Module>();
            }
            ProcessNextModule(previous, sentence, implementation, rules, bundle, true);
        }
예제 #12
0
        public override void Bake(ParameterBundle bundle)
        {
            if (dead)
            {
                return;
            }

            Quaternion rotation;

            if (!bundle.Get("Rotation", out rotation))
            {
                //TODO: used to be Vector3.up. Equivelent?
                rotation = Quaternion.identity;
            }

            Vector3   position = transform.position;
            Transform parent   = null;

            if (previous != null)
            {
                position = previous.transform.position;
                parent   = previous.transform;
            }

            Quaternion bakedRot = Quaternion.Euler(UnityEngine.Random.Range(bakedRotationMin.x, bakedRotationMax.x),
                                                   UnityEngine.Random.Range(bakedRotationMin.y, bakedRotationMax.y),
                                                   UnityEngine.Random.Range(bakedRotationMin.z, bakedRotationMax.z));

            float   s     = UnityEngine.Random.Range(bakedScaleMin, bakedScaleMax);
            Vector3 scale = new Vector3(s, s, s);

            // try get existing instance
            GameObject prototypeInstance;
            GameObject instance;

            if (bakedProtoypes.TryGetValue(prefabIdentifier, out prototypeInstance))
            {
                if (parent == null)
                {
                    parent = transform;
                }
                instance = (GameObject)Instantiate(prototypeInstance, position, bakedRot, parent);
                instance.transform.localScale = scale;
                instance.name = "Instance_" + prefabIdentifier;

                instance.transform.rotation = rotation;
                instance.SetActive(true);

                if (bakedScaleOnSpawn)
                {
                    StartCoroutine(BakedScale(instance));
                }
            }
            else
            {
                //TODO: This could be done off-line.
                AnyExecute(bundle); //bake

                transform.position = Vector3.zero;
                transform.rotation = Quaternion.identity;
                transform.parent   = null;

                // The current object contains the original mesh data so it needs to become the prototypical instance. we create a copy of it to continue.
                instance = (GameObject)Instantiate(gameObject, position, rotation, parent);
                instance.transform.localScale = scale;
                instance.name = "InitialInstance_" + prefabIdentifier;

                if (bakedScaleOnSpawn)
                {
                    StartCoroutine(BakedScale(instance));
                }

                //Kill initial instance module since its already generated.
                Module initialInstanceModule = instance.GetComponent <Module>();
                if (initialInstanceModule != null)
                {
                    Kill(initialInstanceModule);
                }

                gameObject.name = "Prototype_" + prefabIdentifier;
                Kill(this); //the prototype must not be able to create new instances(they will do the same... etc)
                gameObject.hideFlags = HideFlags.HideInHierarchy;

                bakedProtoypes.Add(prefabIdentifier, gameObject);
                gameObject.SetActive(false);
            }
        }
예제 #13
0
 /// <summary>
 /// A unified LSystem symbol implementation execution point with a parameter list for pre-baked execution.
 /// </summary>
 /// <param name="bundle">Bundle containing information collected by previous iterations</param>
 /// <returns>Bundle containing any information that previous Modules may be interested in.</returns>>
 public abstract void Bake(ParameterBundle bundle);
예제 #14
0
        public void AnyExecute(ParameterBundle bundle)
        {
            Profiler.BeginSample("LSystem.Seed.Execute");

            if (previous != null)
            {
                transform.position = previous.transform.position;
            }

            Sentence sentence = new Sentence(axiom);

            if (generateMode == GenMode.PreEdgeRewrite)
            {
                //Pre calculate final sentence.
                for (int i = 0; i < iterations; i++)
                {
                    sentence = rules.NextGeneration(sentence);
                }
                rules.Fertile = false;
                bundle.SetOrPut("Iterations", 0);
            }
            else // if(preGrow == GenMode.IterateNodeRewrite)
            {
                rules.Fertile = true;
                bundle.SetOrPut("Iterations", iterations);
            }

            bundle.SetOrPut("Generation", 0);
            bundle.SetOrPut("Sentence", sentence);
            bundle.SetOrPut("Implementations", implementations);
            bundle.SetOrPut("RuleSet", rules);


            if (!bundle.Exists("Position"))
            {
                bundle.Put("Position", transform.position);
            }

            if (!inheritRotation)
            {
                bundle.SetOrPut("Rotation", transform.rotation);
            }
            else if (!bundle.Exists("Rotation"))
            {
                bundle.Put("Rotation", transform.rotation);
            }

            // execute modules in the axiom
            if (!executed)
            {
                executed = true;

                if (baked)
                {
                    BakeNextModule(transform, sentence, implementations, rules, bundle);
                }
                else
                {
                    EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle);
                }
            }
            Profiler.EndSample();
        }
예제 #15
0
        // Run the update loop to grow the mesh when not baked
        IEnumerator Grow(ParameterBundle bundle)
        {
            //Get parameters
            Quaternion         rotation;
            Sentence           sentence;
            CharGameObjectDict implementations;
            int     generation;
            RuleSet rules;

            // Check valid state for growing
            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules) ||
                !GetPositionParameters(bundle, out generation, out rotation))
            {
                yield break;
            }

            float medialSize, lateralSize, growTime;

            if (bundle.Get("LeafMedialSize", out medialSize))
            {
                startMedialSize = medialSize;
            }
            if (bundle.Get("LeafLateralSize", out lateralSize))
            {
                startLateralSize = lateralSize;
            }
            if (bundle.Get("LeafGrowTime", out growTime))
            {
                startGrowTime = growTime;
            }

            transform.position = previous.transform.position;
            transform.rotation = rotation;

            float time = 1f;

            if (animate)
            {
                time = 0f;
            }
            while (time < startGrowTime)
            {
                time += Time.deltaTime;
                UpdateMesh(time / startGrowTime, offset);
                yield return(null);
            }

            bundle.SetOrPut("LeafMedialSize", startMedialSize * medialSizeChangeCoefficient);
            bundle.SetOrPut("LeafLateralSize", startLateralSize * lateralSizeChangeCoefficient);
            bundle.SetOrPut("LeafGrowTime", startGrowTime * growTimeChangeCoefficient);

            if (setStaticOnComplete)
            {
                gameObject.isStatic = true;
            }

            EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle);

            if (continuousUpdate)
            {
                while (true)
                {
                    UpdateMesh(1f, offset);
                    yield return(null);
                }
            }
        }
예제 #16
0
        IEnumerator Grow(ParameterBundle bundle)
        {
            //Get parameters
            Quaternion         rotation;
            Sentence           sentence;
            CharGameObjectDict implementations;
            int     generation;
            RuleSet rules;

            // Check valid state for growing
            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules) ||
                !GetPositionParameters(bundle, out generation, out rotation))
            {
                yield break;
            }

            // Setup Renderer
            if ((filter = gameObject.GetComponent <MeshFilter>()) == null)
            {
                filter = gameObject.AddComponent <MeshFilter>();
            }
            if ((branchRenderer = gameObject.GetComponent <MeshRenderer>()) == null)
            {
                branchRenderer = gameObject.AddComponent <MeshRenderer>();
            }
            branchRenderer.material = branchMaterial;

            // Match start position to previous position. As growth progresses position will be offset
            // While rotation stays the same
            transform.position = previous.transform.position;
            transform.rotation = rotation;

            // Try and pick up length and radius where last branch left off.
            float length, radius, growSpeed;

            if (bundle.Get("BranchLength", out length))
            {
                startLength = length;
            }
            if (bundle.Get("BranchRadius", out radius))
            {
                startRadius = radius;
            }
            if (bundle.Get("BranchGrowSpeed", out growSpeed))
            {
                startGrowSpeed = growSpeed;
            }
            if (bundle.Get("BranchFaceNum", out faces))
            {
                startFaceNum = faces;
            }

            GrowLoopCallback growLoopCallback;

            bundle.Get("GrowLoopCallback", out growLoopCallback);

            radius    = startRadius;
            length    = startLength;
            growSpeed = startGrowSpeed;
            faces     = startFaceNum;

            // Since we don't want to continue drawing where it doesn't matter!
            // Note that future emergence is killed here.
            if (length < lengthCutoff || radius < radiusCutoff)
            {
                yield break;
            }

            if (endObject != null)
            {
                endObject = (GameObject)Instantiate(endObject, transform);
                Module mod = endObject.GetComponent <Module>();
                if (mod != null)
                {
                    AssignPrevious(mod, this);
                    if (mod.GetType() != typeof(Seed))
                    {
                        Kill(mod);
                        mod.Execute(bundle);
                    }
                }
                endObject.transform.rotation = rotation;
            }

            // Update mesh and extend transform towards final position
            float distance = Vector3.Distance(transform.position, previous.transform.position);

            while (distance < length)
            {
                float completionRatio = distance / length;
                transform.position += transform.up * Mathf.Min(/*heading.magnitude * */ Time.deltaTime * Mathf.Lerp(startGrowSpeed,
                                                                                                                    growSpeed * growSpeedChangeCoefficient, completionRatio), length);
                distance = Vector3.Distance(transform.position, previous.transform.position);

                bottomRadius = Mathf.Lerp(0, startRadius, completionRatio);
                UpdateBranch(Vector3.up * -distance, distance, bottomRadius * bottomRadiusMultiplier,
                             topRadius * topRadiusMultiplier, Mathf.Max(2, (int)(faces)));
                if (growLoopCallback != null)
                {
                    growLoopCallback(bottomRadius);
                }

                if (endObject != null)
                {
                    endObject.transform.position = transform.position;
                    endObject.transform.rotation = rotation;
                }

                yield return(null);
            }
            bottomRadius = startRadius;

            // Update parameters for next branch
            bundle.SetOrPut("BranchLength", length * lengthChangeCoefficient);
            bundle.SetOrPut("BranchRadius", radius * radiusChangeCoefficient);
            bundle.SetOrPut("BranchGrowSpeed", growSpeed * growSpeedChangeCoefficient);
            bundle.SetOrPut("BranchFaceNum", faces * faceNumChangeCoefficient);

            // For coordination between branches
            growLoopCallback = NextBranchGrowLoopCallback;
            bundle.SetOrPut("GrowLoopCallback", growLoopCallback);

            if (setStaticOnComplete)
            {
                gameObject.isStatic = true;
            }

            EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle);
        }
예제 #17
0
        // Execute next module as a IEnumerator (undefined delay based on load) operation.
        public void EnqueueProcessNextModule(Transform caller, Sentence sentence,
                                             SerializableDictionary <char, GameObject> implementation, RuleSet rules, ParameterBundle bundle)
        {
            if (sheduler == null)
            {
                sheduler = FindObjectOfType <ModuleSheduler>();
                if (sheduler == null)
                {
                    GameObject shedulerObject = new GameObject("LSystemModuleSheduler");
                    sheduler = shedulerObject.AddComponent <ModuleSheduler>();
                    shedulerObject.hideFlags = HideFlags.HideInHierarchy;
                }
            }

            Module previous;

            if (this.ethereal)
            {
                // Since this module is ethereal we have to set the parent to this modules parent
                // Note that this behavior is recursive up to the first non ethereal module or null.
                previous = caller.parent.GetComponent <Module>();
            }
            else
            {
                previous = caller.GetComponent <Module>();
            }

            sheduler.EnqueueProcessNextModule(EnumerableProcessNextModule(previous, sentence, implementation, rules, bundle));
        }
예제 #18
0
 // Entry point when dynamically generating LSystem.
 public override void Execute(ParameterBundle bundle)
 {
     AnyExecute(bundle);
 }
예제 #19
0
 // Called from the module scheduler when there is time.
 IEnumerator EnumerableProcessNextModule(Module previous, Sentence sentence,
                                         SerializableDictionary <char, GameObject> implementation, RuleSet rules, ParameterBundle bundle)
 {
     if (!ProcessNextModule(previous, sentence, implementation, rules, bundle, false))
     {
         yield break;
     }
 }
예제 #20
0
 // Entry point when dynamically executing LSystem.
 public override void Execute(ParameterBundle bundle)
 {
     StartCoroutine(Grow(bundle));
 }
예제 #21
0
        // Parse the sentence, load symbol implementations and find the next module to execute.
        // One module is executed at a time, and an internal pointer is adjusted to for the next iteration.
        public bool ProcessNextModule(Module previous, Sentence sentence,
                                      SerializableDictionary <char, GameObject> implementation, RuleSet rules, ParameterBundle bundle, bool baked)
        {
            if (dead)
            {
                return(false);
            }
            Profiler.BeginSample("LSystem.Module.ProcessNextModule");

            GameObject module;
            char       symbol = '\0';

            do
            {
                if (!sentence.HasNext())
                {
                    sentence = rules.NextGeneration(sentence);

                    if (!bundle.Set("Sentence", sentence))
                    {
                        Debug.LogError("Cannot set 'Sentence' parameter in GetAndExecuteModule", gameObject);
                    }

                    int generation;
                    int iterations;
                    if (bundle.Get("Generation", out generation))
                    {
                        generation++;
                        if (bundle.Get("Iterations", out iterations))
                        {
                            if (generation > iterations)
                            {
                                //Max iterations reached.
                                return(false);
                            }
                        }
                        if (!bundle.Set("Generation", generation))
                        {
                            Debug.LogError("Cannot set 'Generation' parameter in GetAndExecuteModule", gameObject);
                        }
                    }
                    else
                    {
                        Debug.LogError("Cannot get 'Generation' parameter in GetAndExecuteModule", gameObject);
                    }
                }
                symbol = sentence.Next();
                if (symbol == '\0')
                {
                    return(false);                 //Sentence is empty! Caused if rules do not generate anything from previous
                }
            } while (!implementation.TryGetValue(symbol, out module));
            KeyValuePair <GameObject, Sentence> newPair = new KeyValuePair <GameObject, Sentence>(module, sentence);

            Profiler.EndSample();

            ExecuteModule(previous, newPair, bundle, symbol, baked);

            return(true);
        }
예제 #22
0
        // Entry point when pre-baking LSystem.
        public override void Bake(ParameterBundle bundle)
        {
            //Get parameters
            Quaternion         rotation;
            Sentence           sentence;
            CharGameObjectDict implementations;
            int     generation;
            RuleSet rules;

            // Check valid state for growing
            if (!GetCoreParameters(bundle, out sentence, out implementations, out rules) ||
                !GetPositionParameters(bundle, out generation, out rotation))
            {
                return;
            }

            // Setup Renderer
            if ((filter = gameObject.GetComponent <MeshFilter>()) == null)
            {
                filter = gameObject.AddComponent <MeshFilter>();
            }
            if ((branchRenderer = gameObject.GetComponent <MeshRenderer>()) == null)
            {
                branchRenderer = gameObject.AddComponent <MeshRenderer>();
            }
            branchRenderer.material = branchMaterial;

            //Match start position to previous position. As growth progresses position will be offset
            //While rotation stays the same
            transform.position = previous.transform.position;
            transform.rotation = rotation;

            // Try and pick up length and radius where last branch left off.
            float length, radius;

            if (bundle.Get("BranchLength", out length))
            {
                startLength = length;
            }
            if (bundle.Get("BranchRadius", out radius))
            {
                startRadius = radius;
            }
            if (bundle.Get("BranchFaceNum", out faces))
            {
                startFaceNum = faces;
            }

            int branchIndex = 0;

            bundle.Get("BakedBranchIndex", out branchIndex);

            GrowLoopCallback growLoopCallback;

            bundle.Get("GrowLoopCallback", out growLoopCallback);

            radius = startRadius;
            length = startLength;
            faces  = startFaceNum;

            // Since we don't want to continue drawing where it doesn't matter!
            // Note that future emergence is killed here.
            if (length < lengthCutoff || radius < radiusCutoff)
            {
                return;
            }

            // Update end object to final position and execute
            if (endObject != null)
            {
                endObject = (GameObject)Instantiate(endObject, transform);
                Module mod = endObject.GetComponent <Module>();
                if (mod != null)
                {
                    AssignPrevious(mod, this);
                    if (mod.GetType() != typeof(Seed))
                    {
                        Kill(mod);
                        SetPrefabIdentifier(mod);
                        mod.Bake(bundle);
                    }
                }
                endObject.transform.rotation = rotation;
            }

            //TODO: used to be the heading.. does this work?
            transform.position += transform.up * length;

            // Bake or reuse mesh.
            // Meshes are reused based on prefabIdentifier
            bool meshNeeded = false;
            List <MeshFilter> sharedFilters;

            if (bakedPrefabFilters.TryGetValue(prefabIdentifier, out sharedFilters))
            {
                if (sharedFilters.Count > branchIndex)
                {
                    filter.mesh = sharedFilters[branchIndex].sharedMesh;
                }
                else
                {
                    meshNeeded = true;
                }
            }
            else
            {
                bakedPrefabFilters.Add(prefabIdentifier, new List <MeshFilter>());
                meshNeeded = true;
            }

            if (meshNeeded)
            {
                float distance = Vector3.Distance(transform.position, previous.transform.position);
                bottomRadius = startRadius;
                UpdateBranch(Vector3.up * -distance, distance, bottomRadius * bottomRadiusMultiplier,
                             radius * radiusChangeCoefficient, Mathf.Max(2, (int)(faces)));
            }

            if (endObject != null)
            {
                endObject.transform.position = transform.position;
                endObject.transform.rotation = rotation;
            }

            // Update parameters for next branch
            bundle.SetOrPut("BranchLength", length * lengthChangeCoefficient);
            bundle.SetOrPut("BranchRadius", radius * radiusChangeCoefficient);
            bundle.SetOrPut("BranchFaceNum", faces * faceNumChangeCoefficient);

            bundle.SetOrPut("BakedBranchIndex", ++branchIndex);

            if (setStaticOnComplete)
            {
                gameObject.isStatic = true;
            }

            BakeNextModule(transform, sentence, implementations, rules, bundle);
        }
예제 #23
0
 /// <summary>
 /// A unified LSystem symbol implementation execution point with a parameter list for dynamic execution.
 /// </summary>
 /// <param name="bundle">Bundle containing information collected by previous iterations</param>
 /// <returns>Bundle containing any information that previous Modules may be interested in.</returns>
 public abstract void Execute(ParameterBundle bundle);