public Product CreateProduct(StoreObjectReference container, Box.PackagedBud bud)
    { // Create a container and put packaged bud into it
        GameObject newContainer = Instantiate(container.gameObject_);

        newContainer.transform.position = bud.parentBox.transform.position;
        ProductGO productGO = newContainer.GetComponent <ProductGO>();

        if (container.proType == StoreObjectReference.productType.jar)
        {
            StorageJar storageJar = new StorageJar(container, newContainer);
            storageJar.uniqueID = Dispensary.GetUniqueProductID();
            productGO.product   = storageJar;
            float      incrementValue = 1;
            List <Bud> newBuds        = new List <Bud>();
            while (bud.weight > 0)
            {
                if (bud.weight - 1 < 0)
                {
                    incrementValue = bud.weight;
                }
                GameObject budGO = new GameObject(bud.strain.name + " Nug");
                budGO.transform.SetParent(newContainer.transform);
                budGO.transform.localPosition = Vector3.zero;
                Bud newBud = budGO.AddComponent <Bud>();
                newBud.strain = bud.strain;
                newBud.weight = incrementValue;
                newBuds.Add(newBud);
                bud.weight -= incrementValue;
            }
            print("Adding buds");
            storageJar.AddBud(newBuds);
            return(storageJar);
        }
        return(null);
    }
    private void draw_internode(Internode internode, int coe)
    {
        Vector3    startPos  = internode.start_node.position + this.transform.position;
        Vector3    endPos    = internode.end_node.position + this.transform.position;
        Bud        bud       = internode.start_node.node_bud;
        Vector3    T         = bud.get_direction();
        Vector3    N         = Quaternion.Euler(0.0f, 0.0f, 90.0f) * T;
        Vector3    B         = Vector3.Cross(T, N);
        int        start_age = internode.start_node.node_bud.age;
        int        end_age   = internode.end_node.node_bud.age;
        Mesh       my_mesh   = Create_My_Mesh(T.normalized, N.normalized, B.normalized, startPos, endPos, start_age, end_age);
        GameObject s         = new GameObject("Textured Mesh");

        s.transform.position = this.transform.position;
        s.AddComponent <MeshFilter>();
        s.AddComponent <MeshRenderer>();
        s.GetComponent <MeshFilter>().mesh = my_mesh;
        Renderer rend = s.GetComponent <Renderer>();

        s.transform.parent = this.transform;
        if (curveUpward == false)
        {
            rend.material.color = new Color(Random.value, 1.0f, 1.0f, 1.0f);
        }
        else if (curveUpward == true)
        {
            rend.material.color = new Color(1.0f, Random.value, 1.0f, 1.0f);
        }
    }
Beispiel #3
0
 private void Awake()
 {
     _parent         = GetComponentInParent <Bud>();
     _renderer       = GetComponent <SpriteRenderer>();
     _playerInside   = false;
     _renderer.color = ColorOut;
 }
Beispiel #4
0
 private void evaluateState(ref Bud bud)
 {
     if (bud.v > 0)
     {
         bud.state = BudState.NEW_METAMER;
     }
 }
Beispiel #5
0
    // Evalue l'énergie pour les éventuelles branches adjacentes (main et lateral) du bourgeon traité
    private void evaluateEnergy(ref Node <Bud> N)
    {
        Bud        bud        = N.value;
        Node <Bud> lateral    = N.lateral;
        Node <Bud> main       = N.main;
        bool       hasLateral = (lateral != null);
        bool       hasMain    = (main != null);
        float      Ql         = 0f;
        float      Qm         = 0f;

        if (hasLateral)
        {
            Ql = lateral.value.Q;
        }
        if (hasMain)
        {
            Qm = main.value.Q;
        }

        float d = (lambda * Qm) + (1 - lambda) * Ql;

        if (hasLateral)
        {
            float e = (bud.v * (1 - lambda) * Ql) / d;
            lateral.value.setEnergy(e);
        }
        if (hasMain)
        {
            float e = (bud.v * lambda * Qm) / d;
            main.value.setEnergy(e);
        }
    }
Beispiel #6
0
    public void AddStartJar()
    {
        List <StoreObjectReference> containerObjects = db.GetProducts(StoreObjectReference.productType.container);
        GameObject jar       = Instantiate(containerObjects[1].gameObject_);
        ProductGO  productGO = jar.GetComponent <ProductGO>();

        productGO.objectID = containerObjects[1].objectID;
        StorageJar storageJar = new StorageJar(containerObjects[1], jar);

        storageJar.uniqueID              = Dispensary.GetUniqueProductID();
        storageJar.objectID              = containerObjects[1].objectID;
        productGO.product                = storageJar;
        productGO.canHighlight           = true;
        jar.GetComponent <Jar>().product = storageJar;
        List <Bud> toAdd = new List <Bud>();
        Strain     toUse = db.GetRandomStrain();

        for (int i = 0; i < 28; i++)
        {
            GameObject bud    = new GameObject("Bud");
            Bud        newBud = bud.AddComponent <Bud>();
            newBud.strain = toUse;
            newBud.weight = UnityEngine.Random.Range(.65f, 1.35f);
            newBud.weight = Mathf.Round(newBud.weight * 100f) / 100f; // Round to 2 decimal places
            jar.GetComponent <Jar>().AddBud(bud);
            bud.transform.position = Vector3.zero;
            toAdd.Add(newBud);
        }
        storageJar.AddBud(toAdd);
        ShelfPosition jarPosition = dm.dispensary.Storage_cs[0].GetRandomStorageLocation(storageJar);

        jar.transform.position = jarPosition.transform.position;
        jar.transform.parent   = jarPosition.transform;
        jarPosition.shelf.parentShelf.AddProduct(storageJar);
    }
 public Node(Bud bud, Vector3 pos, bool curve, bool trop)
 {
     node_bud = bud;
     position = pos;
     bud_list.Add(bud);
     curveUpward = curve;
     tropical    = trop;
 }
    void circleSampling(ref Node <Bud> node, bool lateralMode)
    {
        Bud currentBud = node.value;

        Vector3 axis = Vector3.down;

        if (!node.isRoot())
        {
            if (lateralMode && currentBud.lateralDir != null)
            {
                axis = currentBud.lateralDir;
            }
            else
            {
                Vector3 previousBudPos = node.parent.value.pos;
                Vector3 currentBudPos  = currentBud.pos;
                axis = Vector3.Normalize(previousBudPos - currentBudPos);
            }
        }

        Vector3 side = Quaternion.Euler(90, 0, 90) * axis;

        Vector3 budPos    = currentBud.pos;
        float   angle     = 0f;
        float   stepAngle = 360f / (float)subdivision_qty;
        Vector3 normale   = side;

        if (lateralMode)
        {
            currentBud.lateralVertices = new List <Vector3>();
            currentBud.lateralNormales = new List <Vector3>();
        }
        else
        {
            currentBud.mainVertices = new List <Vector3>();
            currentBud.mainNormales = new List <Vector3>();
        }

        for (int i = 0; i < subdivision_qty; i++)
        {
            angle  += stepAngle;
            normale = Quaternion.AngleAxis(stepAngle, axis) * normale;
            Vector3 pt = budPos + normale * node.value.branchWidth;

            if (lateralMode)
            {
                currentBud.lateralVertices.Add(pt);
                currentBud.lateralNormales.Add(normale);
            }
            else
            {
                currentBud.mainVertices.Add(pt);
                currentBud.mainNormales.Add(normale);
            }
        }
    }
    private void addMetamer(ref TreeGraph <Bud> skeleton, ref List <Node <Bud> > leaves, ref Node <Bud> currentNode)
    {
        Bud   currentBud      = currentNode.value;
        float internodeLength = currentBud.l;

        currentBud.lateralDir = Vector3.Normalize(eta * tropismVec + epsilon * currentBud.optimalGrowth + (1 - eta - epsilon) * currentBud.dir);
        Vector3 newLateralBudPosition = currentBud.pos + currentBud.lateralDir * internodeLength;

        Bud        newLateralBud  = new Bud(newLateralBudPosition, true);
        Node <Bud> newLateralNode = new Node <Bud>(ref skeleton, currentNode, newLateralBud);

        currentNode.lateral = newLateralNode;
        leaves.Add(newLateralNode);
    }
Beispiel #10
0
    private void updateBranchWidth(ref Node <Bud> baseNode)
    {
        Bud currentBud = baseNode.value;

        if (baseNode.isLeaf())
        {
            currentBud.branchWidth = initialDiameter;
        }
        else
        {
            float lateralBudWidth = (baseNode.lateral != null ? baseNode.lateral.value.branchWidth : 0f);
            float mainBudWidth    = (baseNode.main != null ? baseNode.main.value.branchWidth : 0f);
            currentBud.branchWidth = (float)(Math.Pow(lateralBudWidth, this.n) + Math.Pow(mainBudWidth, this.n));
        }
    }
Beispiel #11
0
    public Bud AddNewBud(AGrowable parent, float relativePercentPosition = 0f)
    {
        GameObject gameObject = _assetManager.CreateBud(transform);

        Bud growable = new Bud(this, gameObject, relativePercentPosition);

        gameObject.GetComponent <GrowableComponent>().Growable = growable;
        gameObject.transform.localScale = Vector3.zero;

        if (parent != null)
        {
            parent.AddChild(growable);
        }
        return(growable);
    }
Beispiel #12
0
    // Evalue la lumière recue pour un bourgeon de l'arbre
    private void evaluateLight(ref Node <Bud> N)
    {
        Bud        bud     = N.value;
        Node <Bud> lateral = N.lateral;
        Node <Bud> main    = N.main;

        if (N.isLeaf())
        {
            bud.Q = Q_leaf;
        }
        else
        {
            bud.Q = (lateral != null ? lateral.value.Q : 0f) + (main != null ? main.value.Q : 0f);
        }
    }
    public void Create_SideBud(Bud bud, bool curveUpward, float k, bool trop)
    {
        Vector3 curr_direction = bud.get_direction();
        int     bud_num        = Random.Range(min_bud, max_bud);
        float   angle          = 360 / bud_num;
        int     curr_age       = bud.age;

        if (trop == false)
        {
            if (curveUpward == true)
            {
                for (int i = 0; i < bud_num; i++)
                {
                    Vector3 new_direction = Quaternion.Euler(15.0f, angle * i, 15.0f) * curr_direction;
                    Vector3 u             = new Vector3(0.0f, 1.0f, 0.0f);
                    new_direction += u * k;
                    new_direction  = new_direction.normalized;
                    Bud new_bud = new Bud(new_direction, curr_age + 3);
                    bud_list.Add(new_bud);
                }
            }
            else
            {
                for (int i = 0; i < bud_num; i++)
                {
                    Vector3 new_direction = Quaternion.Euler(15.0f, angle * i, 15.0f) * curr_direction;
                    Vector3 H             = new Vector3(new_direction.x, 0.0f, new_direction.z);
                    H              = H.normalized;
                    new_direction += k * H;
                    new_direction  = new_direction.normalized;
                    Bud new_bud = new Bud(new_direction, curr_age + 2);
                    bud_list.Add(new_bud);
                }
            }
        }
        else
        {
            for (int i = 0; i < bud_num; i++)
            {
                Vector3 new_direction = Quaternion.Euler(15.0f, angle * i, 15.0f) * curr_direction;
                //Vector3 u = new Vector3(0.0f, 1.0f, 0.0f);
                //new_direction += u * k;
                //new_direction = new_direction.normalized;
                Bud new_bud = new Bud(new_direction.normalized, curr_age + 3);
                bud_list.Add(new_bud);
            }
        }
    }
Beispiel #14
0
    public float theta_rad = 1.3f; // radians

    public void execute(ref TreeData tree)
    {
        float cos_theta = (float)Math.Cos(theta_rad);

        foreach (Node <Bud> node in tree.skeleton.leaves)
        {
            Bud            bud        = node.value;
            List <Vector3> directions = new List <Vector3>();

            for (int i = (tree.markers.Count - 1); i >= 0; i--)
            {
                Vector3 marker          = tree.markers[i];
                Vector3 vecBetween      = (marker - bud.pos);
                float   distanceBetween = vecBetween.magnitude;

                if (distanceBetween <= phi) // in bud sphere
                {
                    tree.markers.RemoveAt(i);
                }
            }

            foreach (Vector3 marker in tree.markers)
            {
                Vector3 vecBetween      = (bud.pos - marker);
                float   distanceBetween = vecBetween.magnitude;

                if (distanceBetween <= r) // maybe in bud cone
                {
                    Vector3 dirToMarker     = Vector3.Normalize(vecBetween);
                    float   angleCosBetween = Vector3.Dot(bud.dir, dirToMarker);
                    if (angleCosBetween > cos_theta)   // in bud cone
                    {
                        bud.targetMarkers.Add(marker);
                        directions.Add(dirToMarker);
                    }
                }
            }

            // optimal growth = average of directions to markers which are inside the bud cone
            Vector3 sum = new Vector3(0, 0, 0);
            foreach (Vector3 dir in directions)
            {
                sum += dir;
            }
            bud.optimalGrowth = sum / directions.Count;
        }
    }
Beispiel #15
0
    // Use this for initialization
    void Start()
    {
        // Scripts
        generationScript = GameObject.Find("DepthMovingObjects").GetComponent <Generation>();

        // Components
        thisTransform = transform;

        // Init
        level       = 0;
        budSelected = 0;
        buds        = new Bud[thisTransform.childCount];
        for (int i = 0; i < thisTransform.childCount; i++)
        {
            buds[i] = thisTransform.GetChild(i).GetComponent <Bud>();
        }
        buds[0].petals[0].setAlive(true);
    }
Beispiel #16
0
    public Bud[] BreakBud(float newWeight) // Returns two buds, the first one has the weight of the parameter, the second has the remaining
    {
        GameObject pieceOneGO     = new GameObject("Bud");
        GameObject pieceTwoGO     = new GameObject("Bud");
        Bud        pieceOne       = pieceOneGO.AddComponent <Bud>();
        Bud        pieceTwo       = pieceTwoGO.AddComponent <Bud>();
        float      pieceOneWeight = newWeight;
        float      pieceTwoWeight = weight - newWeight;

        pieceOne.strain = strain;
        pieceOne.weight = pieceOneWeight;
        pieceTwo.strain = strain;
        pieceTwo.weight = pieceTwoWeight;
        Bud[] returnArray = new Bud[2];
        returnArray[0] = pieceOne;
        returnArray[1] = pieceTwo;
        StartCoroutine(Broke());
        return(returnArray);
    }
Beispiel #17
0
    public void execute(ref TreeData tree)
    {
        tree.markers     = new List <Vector3>(nb_markers);
        tree.boundingBox = boundingBox;

        for (int i = 0; i < nb_markers; i++)
        {
            float x = Random.Range(0, tree.boundingBox.x);
            float y = Random.Range(0, tree.boundingBox.y);
            float z = Random.Range(0, tree.boundingBox.z);
            tree.markers.Add(new Vector3(x, y, z));
        }

        Vector3    budPosition = new Vector3(boundingBox.x / 2, 0, boundingBox.z / 2); // default seed position => bottom
        Bud        bud         = new Bud(budPosition, true);
        Node <Bud> root        = new Node <Bud>(bud);

        tree.skeleton = new TreeGraph <Bud>(root);
    }
Beispiel #18
0
    // Accumule l'énergie de l'arbre, de la base vers les feuilles
    private void distributeEnergy(ref TreeGraph <Bud> skeleton)
    {
        // On évalue d'abord la quantité d'énergie à la base de l'arbre
        Bud   rootBud = skeleton.root.value;
        float vBase   = alpha * rootBud.Q;

        rootBud.setEnergy(vBase);

        for (int i = 0; i < skeleton.levels.Count; i++)
        {
            List <Node <Bud> > list = skeleton.levels[i];
            for (int j = 0; j < list.Count; j++)
            {
                Node <Bud> node = list[j];
                Bud        bud  = node.value;
                evaluateState(ref bud);
                evaluateEnergy(ref node);
            }
        }
    }
    private void growBranch(ref TreeGraph <Bud> skeleton, ref List <Node <Bud> > leaves, ref Node <Bud> currentNode)
    {
        Bud     currentBud = currentNode.value;
        Vector3 dir        = currentBud.dir;
        float   length     = currentBud.l;
        int     it_number  = currentBud.n;

        Node <Bud> node = currentNode;

        for (int i = 1; i < it_number; i++)
        {
            Node <Bud> previousNode = node;
            Bud        previousBud  = previousNode.value;
            Vector3    position     = previousBud.pos + dir * length;
            Bud        bud          = new Bud(position, false);
            node = new Node <Bud>(ref skeleton, previousNode, bud);
            previousNode.main = node;
        }

        leaves.Add(node);
    }
    void drawNodeCircles(Color c, bool lateralMode)
    {
        Gizmos.color = c;

        if (treeModel.skeleton != null)
        {
            foreach (List <Node <Bud> > level in treeModel.skeleton.levels)
            {
                foreach (Node <Bud> node in level)
                {
                    Bud bud = node.value;

                    List <Vector3> vertices = null;
                    if (lateralMode)
                    {
                        vertices = bud.lateralVertices;
                    }
                    else
                    {
                        vertices = bud.mainVertices;
                    }

                    if (vertices != null)
                    {
                        Vector3 position_start, position_end;
                        position_start = position_end = new Vector3();
                        for (int i = 1; i < vertices.Count; i++)
                        {
                            position_start = transform.position + vertices[i - 1];
                            position_end   = transform.position + vertices[i];
                            Gizmos.DrawLine(position_start, position_end);
                        }
                        position_start = transform.position + vertices[vertices.Count - 1];
                        position_end   = transform.position + vertices[0];
                        Gizmos.DrawLine(position_start, position_end);
                    }
                }
            }
        }
    }
 public void Bud_Growth(ArrayList node_list, ArrayList internode_list, float k, bool trop)
 {
     for (int i = 0; i < bud_list.Count; i++)
     {
         Bud bud      = (Bud)bud_list[i];
         int curr_age = bud.age;
         if (Random.value < bud.prob_die)
         {
             bud.Set_Dead();
         }
         else if (Random.value > bud.prob_pause)
         {
             Vector3 direction    = bud.get_direction();
             Vector3 new_position = position + node_length * direction;
             Bud     new_bud      = new Bud(direction, curr_age + 1);
             Node    end_node     = new Node(new_bud, new_position, curveUpward, trop);
             node_list.Add(end_node);
             internode_list.Add(new Internode(this, end_node));
             end_node.Create_SideBud(bud, curveUpward, k, trop);
             end_node.Create_TipBud(bud);
         }
     }
 }
    public void execute(ref TreeData tree)
    {
        List <Node <Bud> > leaves = tree.skeleton.leaves;

        for (int i = leaves.Count - 1; i >= 0; i--)
        {
            Node <Bud> node = leaves[i];
            Bud        bud  = node.value;

            switch (bud.state)
            {
            case BudState.NEW_METAMER:
                growBranch(ref tree.skeleton, ref leaves, ref node);
                addMetamer(ref tree.skeleton, ref leaves, ref node);
                break;

            case BudState.DORMANT:
                growBranch(ref tree.skeleton, ref leaves, ref node);
                break;
            }

            leaves.Remove(node);
        }
    }
    // Use this for initialization
    void Start()
    {
        float k = kValueForCurve;

        internode_list = new ArrayList();
        node_list      = new ArrayList();
        Random.InitState(random_seed);
        Bud  start_bud  = new Bud(new Vector3(0, 1, 0), 1);
        Node start_node = new Node(start_bud, this.transform.position, curveUpward, NoTropicalImplementation);

        node_list.Add(start_node);

        for (int i = 0; i < growth_cap; i++)
        {
            int count = node_list.Count;
            for (int j = 0; j < count; j++)
            {
                ((Node)node_list[j]).Bud_Growth(node_list, internode_list, k, NoTropicalImplementation);
            }
        }
        foreach (Internode internode in internode_list)
        {
            int color_coe = internode.start_node.node_bud.age;
            draw_internode(internode, color_coe);
            if (flower != null)
            {
                if (internode.end_node.node_bud.age >= 5)
                {
                    Vector3    pos      = internode.end_node.position + this.transform.position;
                    GameObject myFlower = Instantiate(flower, pos, Quaternion.identity) as GameObject;
                    myFlower.transform.parent = this.transform;
                    //myFlower.transform.rotation = Random.rotation;
                }
            }
        }
    }
Beispiel #24
0
    // Use this for initialization
    void Start()
    {
        instance = GetComponent <PlantManager>();

        starting_position.xGridPosition = 2;
        starting_position.yGridPosition = 3;
        GameObject gm = Instantiate(grid_marker_prefab, new Vector3(BOARD_START_X + (BOARD_MARKER_MARGIN * 2), BOARD_START_Y - (BOARD_MARKER_MARGIN * 3), 0), grid_marker_prefab.transform.rotation);

        starting_position.obj = gm;

        // instantiate all grid markers with their position and neighbor knowledge
        CreateBoard();

        grid_markers[(GRID_WIDTH - 1) / 2, GRID_HEIGHT - 1] = starting_position;

        // create initial bud and set position
        GameObject original_bud_gm = new GameObject();
        Bud        original_bud    = original_bud_gm.AddComponent <Bud>();

        original_bud.current_position = starting_position;
        original_bud.growth           = original_bud_gm;
        original_bud.InstantiateLineRenderer();
        bud_list.Add(original_bud);
    }
Beispiel #25
0
 private static void testing(long start, long limit, string expected)
 {
     Console.WriteLine("start: {0}, limit: {1}, expected: {2}", start, limit, expected);
     Assert.AreEqual(expected, Bud.Buddy(start, limit));
 }
    // Method for generating a plant object
    public GameObject generatePlant(string leafColor)
    {
        // Clear segment list
        segments = new List <Segment>();

        startSegment(new Vector3(0f, 0f, 0f), 1, 1);

        // Grow segments
        for (int i = 0; i < growthCycles; i++)
        {
            // List of new nodes being made
            List <Node> newNodes = new List <Node>();

            // Grow each segment
            foreach (Segment seg in segments)
            {
                List <Node> segNodes = seg.getNodes();
                Bud         tipBud   = segNodes[segNodes.Count - 1].getTipBud();

                int tipBudAge = tipBud.getAge();

                // Check if bud should die -> if so then set bud to die
                // If it should not die, check if its already dead or should pause growth
                float deathValue = Random.value;
                if (deathValue <= tipBud.getDiePob() + (0.015f * tipBudAge))
                {
                    //string message = deathValue.ToString() + ", " + (tipBud.getDiePob() + (0.015f * tipBudAge)).ToString();
                    //Debug.Log(message);
                    tipBud.setDead();
                }
                if (!tipBud.getIsDead() && Random.value > tipBud.getPause())
                {
                    Node newNode = seg.grow();
                    newNodes.Add(newNode);
                }
            }

            //print(newNodes[0].getTipBud().getOrder());

            // Start new segments at new nodes' side buds
            foreach (Node newNode in newNodes)
            {
                foreach (Bud sidebud in newNode.getSideBuds())
                {
                    startSegment(sidebud.getPos(), sidebud.getAge(), sidebud.getOrder());
                }
            }
        }

        GameObject plant = new GameObject();

        plant.name = "Plant";

        // Create the segment objects
        foreach (Segment seg in segments)
        {
            GameObject segment = new GameObject();
            segment.name = "Segment";
            segment.AddComponent <MeshFilter>();
            segment.AddComponent <MeshRenderer>();
            segment.GetComponent <MeshFilter>().mesh = seg.getMesh();
            Renderer rend = segment.GetComponent <Renderer>();
            rend.material.color      = new Color(0.5f, 0.2f, 0.05f, 1.0f); // bark color
            segment.transform.parent = plant.transform;

            // Create leaf spheres at the end of each segment
            List <Node> segNodes  = seg.getNodes();
            Bud         segTipBud = segNodes[segNodes.Count - 1].getTipBud();
            if (segTipBud.getOrder() > 3)
            {
                GameObject leaf = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                leaf.transform.position = segTipBud.getPos();
                //leaf.transform.localScale = new Vector3(5f / segTipBud.getOrder(), 5f / segTipBud.getOrder(), 5f / segTipBud.getOrder());
                leaf.transform.localScale = new Vector3(2.5f, 2.5f, 2.5f);

                // Set leaf color
                Color color = new Color(1f, 1f, 1f);
                if (leafColor == "Green")
                {
                    color = new Color(0f, Random.value, 0f, 1f);                                     // light green
                }
                else if (leafColor == "Autumn")
                {
                    color = new Color(0.3f + Random.value, Random.value - 0.5f, 0f, 1f);     // autumn colors
                }
                else if (leafColor == "Sakura")
                {
                    float pinkRandom = Random.Range(0.5f, 0.8f);
                    color = new Color(1f, pinkRandom, pinkRandom, 1f);                                   // pink
                }
                leaf.GetComponent <Renderer>().material.color = color;
                leaf.transform.parent = plant.transform;
            }
        }

        return(plant);
    }
    ////////// Functions //////////////

    // Begins a new segnment by create a tip bud, a node, and the segment object
    // Also creates the mesh for the base of the first cylinder
    public void startSegment(Vector3 pos, int age, int order)
    {
        // If this is the first segment of the plant, make its direction up
        Vector3 dir;

        if (segments.Count == 0)
        {
            dir = new Vector3(0f, 1f, 0f);
        }
        else
        {
            dir = new Vector3((Random.value * 2f) - 1f, 0.1f + Random.value, (Random.value * 2f) - 1f);
            //dir = new Vector3((Random.value * 2f) - 1f, Random.value / 1.5f, (Random.value * 2f) - 1f);
            //dir = new Vector3(Random.value - 0.5f, 1f + Random.value, Random.value - 0.5f);
        }
        Bud     tipBud     = new Bud(pos, dir, age, order);
        Node    startNode  = new Node(pos, tipBud);
        Segment newSegment = new Segment(startNode);

        // Create cylinder base in mesh
        Mesh startMesh = new Mesh();

        Vector3[] verts = new Vector3[7];
        int[]     tris  = new int[6 * 3];

        Vector3 T = dir.normalized;
        Vector3 V = (T.x == 1f) ? new Vector3(0f, 1f, 0f) : new Vector3(1f, 0f, 0f);
        Vector3 N = -1f * (Vector3.Cross(T, V)).normalized;
        Vector3 B = Vector3.Cross(T, N);

        //verts[0] = pos;
        //verts[1] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 0f), 0f, Mathf.Sin(Mathf.Deg2Rad * 0f));
        //verts[2] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 60f), 0f, Mathf.Sin(Mathf.Deg2Rad * 60f));
        //verts[3] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 120f), 0f, Mathf.Sin(Mathf.Deg2Rad * 120f));
        //verts[4] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 180f), 0f, Mathf.Sin(Mathf.Deg2Rad * 180f));
        //verts[5] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 240f), 0f, Mathf.Sin(Mathf.Deg2Rad * 240f));
        //verts[6] = pos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 300f), 0f, Mathf.Sin(Mathf.Deg2Rad * 300f));

        verts[0] = pos;
        verts[1] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 0f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 0f))) / ((age + order) * 1f / 2f));
        verts[2] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 60f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 60f))) / ((age + order) * 1f / 2f));
        verts[3] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 120f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 120f))) / ((age + order) * 1f / 2f));
        verts[4] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 180f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 180f))) / ((age + order) * 1f / 2f));
        verts[5] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 240f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 240f))) / ((age + order) * 1f / 2f));
        verts[6] = pos + (((N * Mathf.Cos(Mathf.Deg2Rad * 300f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 300f))) / ((age + order) * 1f / 2f));

        tris[0] = 0;
        tris[1] = 2;
        tris[2] = 1;

        tris[3] = 0;
        tris[4] = 3;
        tris[5] = 2;

        tris[6] = 0;
        tris[7] = 4;
        tris[8] = 3;

        tris[9]  = 0;
        tris[10] = 5;
        tris[11] = 4;

        tris[12] = 0;
        tris[13] = 6;
        tris[14] = 5;

        tris[15] = 0;
        tris[16] = 1;
        tris[17] = 6;

        startMesh.vertices  = verts;
        startMesh.triangles = tris;
        startMesh.RecalculateNormals();

        newSegment.setMesh(startMesh);

        // Add to global list of segments
        segments.Add(newSegment);
    }
        // Grows the segment by adding a new node in the direction
        // of the tipNode's tipBud
        // Returns the new tipNode
        public Node grow()
        {
            Node tipNode  = nodes[nodes.Count - 1];
            Bud  tipBud   = tipNode.getTipBud();
            int  segOrder = tipBud.getOrder();
            int  age      = tipBud.getAge();

            Vector3 oldTipPos = tipBud.getPos();
            Vector3 growthDir = tipBud.getDir();

            // Get segment's vertices and triangles of mesh
            Vector3[] oldVerts = segMesh.vertices;
            int[]     oldTris  = segMesh.triangles;

            int oldVertLength = oldVerts.Length;
            int oldTriLength  = oldTris.Length;

            // Create new lists of vertices and tris
            Vector3[] newVerts = new Vector3[oldVertLength + 7];
            int[]     newTris  = new int[oldTriLength + (18 * 3)];

            // Check if segment is not just a cylinder base in mesh
            // If it is multiple cylinders, "cut off" the top cap of the mesh
            int stopCopyIndex = (oldVertLength > 7) ? oldTriLength - 18 - 1 : oldTriLength - 1;

            for (int v = 0; v < oldVertLength; v++)
            {
                newVerts[v] = oldVerts[v];
            }
            for (int t = 0; t <= stopCopyIndex; t++)
            {
                newTris[t] = oldTris[t];
            }

            // Calculate new vertices
            Vector3 T = growthDir.normalized;
            Vector3 V = (T.x == 1f) ? new Vector3(0f, 1f, 0f) : new Vector3(1f, 0f, 0f);
            Vector3 N = -1f * (Vector3.Cross(T, V)).normalized;
            Vector3 B = Vector3.Cross(T, N);

            Vector3 newTipPos = oldTipPos + (T * growthLength);

            //newVerts[oldVertLength] = newTipPos;
            //newVerts[oldVertLength + 1] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 0f), 0f, Mathf.Sin(Mathf.Deg2Rad * 0f));
            //newVerts[oldVertLength + 2] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 60f), 0f, Mathf.Sin(Mathf.Deg2Rad * 60f));
            //newVerts[oldVertLength + 3] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 120f), 0f, Mathf.Sin(Mathf.Deg2Rad * 120f));
            //newVerts[oldVertLength + 4] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 180f), 0f, Mathf.Sin(Mathf.Deg2Rad * 180f));
            //newVerts[oldVertLength + 5] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 240f), 0f, Mathf.Sin(Mathf.Deg2Rad * 240f));
            //newVerts[oldVertLength + 6] = newTipPos + new Vector3(Mathf.Cos(Mathf.Deg2Rad * 300f), 0f, Mathf.Sin(Mathf.Deg2Rad * 300f));

            newVerts[oldVertLength]     = newTipPos;
            newVerts[oldVertLength + 1] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 0f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 0f))) / ((segOrder + age) * 1f / 2f));
            newVerts[oldVertLength + 2] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 60f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 60f))) / ((segOrder + age) * 1f / 2f));
            newVerts[oldVertLength + 3] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 120f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 120f))) / ((segOrder + age) * 1f / 2f));
            newVerts[oldVertLength + 4] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 180f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 180f))) / ((segOrder + age) * 1f / 2f));
            newVerts[oldVertLength + 5] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 240f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 240f))) / ((segOrder + age) * 1f / 2f));
            newVerts[oldVertLength + 6] = newTipPos + (((N * Mathf.Cos(Mathf.Deg2Rad * 300f)) + (B * Mathf.Sin(Mathf.Deg2Rad * 300f))) / ((segOrder + age) * 1f / 2f));

            int newVertsLength = newVerts.Length;

            // Calculate new tris
            // Sides
            newTris[oldTriLength]     = newVertsLength - 13;
            newTris[oldTriLength + 1] = newVertsLength - 12;
            newTris[oldTriLength + 2] = newVertsLength - 6;

            newTris[oldTriLength + 3] = newVertsLength - 12;
            newTris[oldTriLength + 4] = newVertsLength - 5;
            newTris[oldTriLength + 5] = newVertsLength - 6;

            newTris[oldTriLength + 6] = newVertsLength - 12;
            newTris[oldTriLength + 7] = newVertsLength - 11;
            newTris[oldTriLength + 8] = newVertsLength - 5;

            newTris[oldTriLength + 9]  = newVertsLength - 11;
            newTris[oldTriLength + 10] = newVertsLength - 4;
            newTris[oldTriLength + 11] = newVertsLength - 5;

            newTris[oldTriLength + 12] = newVertsLength - 11;
            newTris[oldTriLength + 13] = newVertsLength - 10;
            newTris[oldTriLength + 14] = newVertsLength - 4;

            newTris[oldTriLength + 15] = newVertsLength - 10;
            newTris[oldTriLength + 16] = newVertsLength - 3;
            newTris[oldTriLength + 17] = newVertsLength - 4;

            newTris[oldTriLength + 18] = newVertsLength - 10;
            newTris[oldTriLength + 19] = newVertsLength - 9;
            newTris[oldTriLength + 20] = newVertsLength - 3;

            newTris[oldTriLength + 21] = newVertsLength - 9;
            newTris[oldTriLength + 22] = newVertsLength - 2;
            newTris[oldTriLength + 23] = newVertsLength - 3;

            newTris[oldTriLength + 24] = newVertsLength - 9;
            newTris[oldTriLength + 25] = newVertsLength - 8;
            newTris[oldTriLength + 26] = newVertsLength - 2;

            newTris[oldTriLength + 27] = newVertsLength - 8;
            newTris[oldTriLength + 28] = newVertsLength - 1;
            newTris[oldTriLength + 29] = newVertsLength - 2;

            newTris[oldTriLength + 30] = newVertsLength - 8;
            newTris[oldTriLength + 31] = newVertsLength - 13;
            newTris[oldTriLength + 32] = newVertsLength - 1;

            newTris[oldTriLength + 33] = newVertsLength - 13;
            newTris[oldTriLength + 34] = newVertsLength - 6;
            newTris[oldTriLength + 35] = newVertsLength - 1;

            // New cap
            newTris[oldTriLength + 36] = newVertsLength - 7;
            newTris[oldTriLength + 37] = newVertsLength - 6;
            newTris[oldTriLength + 38] = newVertsLength - 5;

            newTris[oldTriLength + 39] = newVertsLength - 7;
            newTris[oldTriLength + 40] = newVertsLength - 5;
            newTris[oldTriLength + 41] = newVertsLength - 4;

            newTris[oldTriLength + 42] = newVertsLength - 7;
            newTris[oldTriLength + 43] = newVertsLength - 4;
            newTris[oldTriLength + 44] = newVertsLength - 3;

            newTris[oldTriLength + 45] = newVertsLength - 7;
            newTris[oldTriLength + 46] = newVertsLength - 3;
            newTris[oldTriLength + 47] = newVertsLength - 2;

            newTris[oldTriLength + 48] = newVertsLength - 7;
            newTris[oldTriLength + 49] = newVertsLength - 2;
            newTris[oldTriLength + 50] = newVertsLength - 1;

            newTris[oldTriLength + 51] = newVertsLength - 7;
            newTris[oldTriLength + 52] = newVertsLength - 1;
            newTris[oldTriLength + 53] = newVertsLength - 6;

            // Make new new tipBud and new tipNode and add it to segment's node list
            //Vector3 newTipDir = new Vector3((Random.value * 2f) - 1f, 1f + Random.value, (Random.value * 2f) - 1f);
            Vector3 newTipDir  = new Vector3(Random.value - 0.5f, 0.25f + Random.value, Random.value - 0.5f);
            Bud     newTipBud  = new Bud(newTipPos, newTipDir, age + 1, segOrder);
            Node    newTipNode = new Node(newTipPos, newTipBud);

            // Add a number of branches at the new node
            int numBranches = Random.Range(0, maxSideBudsPerNode);

            for (int i = 0; i < numBranches; i++)
            {
                Vector3 dir        = new Vector3((Random.value * 2f) - 1f, Random.value / 4f, (Random.value * 2f) - 1f);
                Vector3 sideBudPos = newTipPos - T;
                Bud     sideBud    = new Bud(sideBudPos, dir, age, segOrder + 1);
                newTipNode.addSideBud(sideBud);
            }

            nodes.Add(newTipNode);

            // Set the new vertices and triangles for the mesh
            segMesh.vertices  = newVerts;
            segMesh.triangles = newTris;
            segMesh.RecalculateNormals();

            return(newTipNode);
        }
 public void addSideBud(Bud bud)
 {
     this.sideBuds.Add(bud);
 }
 public Node(Vector3 pos, Bud tipBud)
 {
     this.pos      = pos;
     this.sideBuds = new List <Bud>();
     this.tipBud   = tipBud;
 }