コード例 #1
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);
            }
        }
コード例 #2
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);
        }
コード例 #3
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);
        }