Пример #1
0
    public Mesh BuildLeaves()
    {
        PGTreeBase        p     = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;
        PGTreeTrunkSimple trunk = transform.parent.GetComponentInChildren <PGTreeTrunkSimple>();

        MeshBuilder meshBuilder = new MeshBuilder();

        for (int i = 0; i < trunk.Leaves.Count - 1; i++)
        {
            for (int j = 0; j < p.m_leaves_per_branch; j++)
            {
                Vector3    offset      = trunk.Leaves[i].position;
                Vector3    localOffset = new Vector3(0.0f, Mathf.Cos(p.m_stem_start_angle * Mathf.Deg2Rad), Mathf.Sin(p.m_stem_start_angle * Mathf.Deg2Rad)) * p.m_stem_length;
                Quaternion rotation    = trunk.Leaves[i].rotation * Quaternion.Euler(0.0f, (360 * (float)j) / (float)p.m_leaves_per_branch, 0.0f);
                BuildLeaf(meshBuilder, offset, localOffset, rotation, p.m_leaf_length, p.m_leaf_width, p.m_leaf_length_rand, p.m_leaf_width_rand, p.m_leaf_length_segments, p.m_leaf_width_segments,
                          p.m_leaf_bend, p.m_leaf_bend_rand, p.m_leaf_curl, p.m_leaf_curl_rand, p.m_leaf_twist, p.m_leaf_twist_rand, true, p.m_leaf_variation);
                //BuildLeaf(meshBuilder,offset,localOffset,rotation,p.m_leaf_length,p.m_leaf_width,p.m_leaf_length_rand,p.m_leaf_width_rand,p.m_leaf_length_segments,p.m_leaf_width_segments,
                //	p.m_leaf_bend,p.m_leaf_bend_rand,p.m_leaf_curl,p.m_leaf_curl_rand,p.m_leaf_twist,p.m_leaf_twist_rand,true,p.m_leaf_variation);
            }
        }

        Mesh mesh = meshBuilder.CreateMesh();

        mesh.RecalculateNormals();
        return(mesh);
    }
Пример #2
0
    private GameObject AddTree(TreeSpecies species)
    {
        GameObject tree     = new GameObject("TreeInstance");
        PGTreeBase treeBase = tree.AddComponent <PGTreeBase>();

        treeBase.SetSpecies(species);
        return(tree);
    }
Пример #3
0
    void BuildStems(MeshBuilder meshBuilder, Vector3 offset, Quaternion rotation, float length, float radius, int segments, float bendAngle)
    {
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        for (int i = 0; i < p.m_leaves_per_branch; i++)
        {
            Quaternion stemRotation = rotation * Quaternion.Euler(0.0f, (360 * (float)i) / (float)p.m_leaves_per_branch, 0.0f) * Quaternion.Euler(0.0f, 0.0f, p.m_stem_start_angle);
            BuildBranch(meshBuilder, offset, radius, stemRotation, segments, 3, new Vector2(0.0f, 0.0f), 0.0f, length, 0.0f, 0.0f, 0.0f, false, false);
        }
    }
Пример #4
0
    void BuildLODBranch(int LODindex, MeshBuilder meshBuilder, Vector3 offset, float startRadius, Quaternion startAngle, int lengthSegments, int radialSegments, bool startTriangles)
    {
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        // Calculate a random bend towards the sky
        Vector3 angleRand = Vector3.zero;

        angleRand.x = NextLODRand();
        angleRand.y = NextLODRand();
        angleRand.z = NextLODRand();

        Vector3    ringCentre = offset;
        Quaternion rotation   = Quaternion.identity;

        float twistRand  = NextLODRand();
        float lengthRand = NextLODRand();

        float radius = startRadius;

        for (int i = 0; i <= lengthSegments; i++)
        {
            float heightRatio = (float)i / (float)lengthSegments;
            //float ringHeight = heightRatio*lengthRand;
            float twistAngle     = heightRatio * twistRand;
            bool  buildTriangles = !startTriangles && i == 0 ? false : true;
            //radius = useMinRadius ? radius : radius*p.m_branch_radius_falloff;

            float v = (heightRatio * lengthRand) / (2 * Mathf.PI * radius) + 1.0f / (2 * Mathf.PI);


            //BuildCurve(meshBuilder,ringCentre,radius,radialSegments,v,0,0,0.0f,0.0f,startAngle*rotation,twistAngle,0,buildTriangles);
            if (i == lengthSegments)
            {
                // Add new fork
                BuildLODFork(LODindex, meshBuilder, ringCentre, radius, startAngle * rotation * Quaternion.Euler(0.0f, -twistRand, 0.0f), lengthSegments, radialSegments);
                break;
            }
            else if (radius < p.m_branch_min_radius)
            {
                // Complete branch
                //rotation = Quaternion.Euler(angleRand*heightRatio);
                //ringCentre += startAngle*rotation*new Vector3(0.0f,lengthRand/lengthSegments,0.0f);
                v      = (((float)(i + 1) / (float)lengthSegments) * lengthRand) / (2 * Mathf.PI * radius) + 1.0f / (2 * Mathf.PI);
                radius = 0;
                BuildCurveSimple(meshBuilder, ringCentre, radius, radialSegments, v, startAngle * rotation, twistAngle, buildTriangles);
                break;
            }
            BuildCurveSimple(meshBuilder, ringCentre, radius, radialSegments, v, startAngle * rotation, twistAngle, buildTriangles);
            rotation    = Quaternion.Euler(angleRand * ((float)i / (float)(lengthSegments + 1)));
            ringCentre += startAngle * rotation * new Vector3(0.0f, lengthRand / (float)lengthSegments, 0.0f);
        }
    }
Пример #5
0
    public Mesh BuildLOD2Leaves()
    {
        PGTreeBase  p           = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;
        MeshBuilder meshBuilder = new MeshBuilder();

        Vector3 position = Vector3.zero;
        Vector3 offsetXZ = new Vector3(5.0f, 0.0f, 0.0f);
        Vector3 offsetY  = new Vector3(0.0f, 5.0f, 0.0f);

        BuildQuad(meshBuilder, position - offsetXZ, new Vector2(0.0f, 0.0f), false, 2, Vector3.zero, true);
        BuildQuad(meshBuilder, position + offsetXZ, new Vector2(5.0f, 0.0f), false, 2, Vector3.zero, true);
        BuildQuad(meshBuilder, position - offsetXZ + offsetY, new Vector2(0.0f, 5.0f), false, 2, Vector3.zero, true);
        BuildQuad(meshBuilder, position + offsetXZ + offsetY, new Vector2(5.0f, 5.0f), true, 2, Vector3.zero, true);

        Mesh mesh = meshBuilder.CreateMesh();

        mesh.RecalculateNormals();
        return(mesh);
    }
Пример #6
0
    private void InitSeed()
    {
        PGTreeBase tree = gameObject.GetComponent <PGTreeBase>();

        tree.Init(seed);
    }
Пример #7
0
    public Mesh BuildTrunk()
    {
        // Set variables from parent
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        /*
         * float m_height = p.m_height;
         * float m_start_radius = p.m_start_radius;
         * float m_end_radius = p.m_end_radius;
         * float m_twist_angle = p.m_twist_angle;
         * float m_max_bend = p.m_max_bend;
         * TrunkCurveType m_trunk_curve_type = p.m_trunk_curve_type;
         * float m_circ_trunk_bulge = p.m_circ_trunk_bulge;
         * float m_circ_trunk_bulge_offset = p.m_circ_trunk_bulge_offset;
         * float m_circ_trunk_bulge_freq = p.m_circ_trunk_bulge_freq;
         * float m_exp_mid_radius = p.m_exp_mid_radius;
         * float m_expolinear_blend = p.m_expolinear_blend;
         * float m_start_irregularity = p.m_start_irregularity;
         * float m_irregularity_falloff = p.m_irregularity_falloff;
         * int m_radial_segments = p.m_radial_segments;
         * int m_height_segments = p.m_height_segments;
         */

        MeshBuilder meshBuilder = new MeshBuilder();

        Vector3 offset = new Vector3(0.0f, 0.0f, 0.0f);

        // Generate 2 random harmonic frequencies to blend.
        int f1 = Random.Range(1, 5) * 2;
        int f2 = Random.Range(1, 3) * 2 + 1;

        float angle_offset1 = Random.Range(0.0f, Mathf.PI * 2);
        float angle_offset2 = Random.Range(0.0f, Mathf.PI * 2);

        Vector3    ring_centre = offset;
        Quaternion rotation    = Quaternion.identity;
        Vector3    angle_rand  = new Vector3(Random.Range(-p.m_max_bend, p.m_max_bend), Random.Range(-p.m_max_bend, p.m_max_bend), Random.Range(-p.m_max_bend, p.m_max_bend));

        BuildCurve(meshBuilder, offset, p.m_start_radius, p.m_radial_segments, 0.0f, f1, f2, angle_offset1, angle_offset2, Quaternion.identity, 0.0f, p.m_start_irregularity, false);
        for (int i = 1; i <= p.m_height_segments; i++)
        {
            float ring_height = ((float)i / (float)p.m_height_segments) * p.m_height;
            float radius      = 1.0f;

            if (p.m_trunk_curve_type == TrunkCurveType.Circular)
            {
                radius = p.m_circ_trunk_bulge * Mathf.Sin((Mathf.PI * p.m_circ_trunk_bulge_freq * ring_height) / p.m_height + p.m_circ_trunk_bulge_offset) + (p.m_end_radius - p.m_start_radius) * ring_height / p.m_height + p.m_start_radius;
            }
            else if (p.m_trunk_curve_type == TrunkCurveType.Exponential || p.m_trunk_curve_type == TrunkCurveType.ExpoLinear)
            {
                bool isExpoLin = p.m_trunk_curve_type == TrunkCurveType.ExpoLinear;
                if (isExpoLin)
                {
                    radius = ExpoLinInterp(p.m_start_radius, p.m_exp_mid_radius, p.m_end_radius, p.m_height, ring_height, p.m_expolinear_blend);
                }
                else
                {
                    radius = ExpoLinInterp(p.m_start_radius, p.m_exp_mid_radius, p.m_end_radius, p.m_height, ring_height);
                }
            }

            float irregularity = p.m_start_irregularity * Mathf.Exp(-ring_height * p.m_irregularity_falloff / p.m_height);
            float twist_angle  = (ring_height * p.m_twist_angle) / p.m_height;

            float hr = (ring_height / p.m_height);
            rotation = Quaternion.Euler(angle_rand.x * hr, angle_rand.y * hr, angle_rand.z * hr);
            Vector3 new_ring_offset = new Vector3(0.0f, p.m_height / (float)p.m_height_segments, 0.0f);
            ring_centre += rotation * new_ring_offset;

            float v = ring_height / (2 * Mathf.PI * radius);

            BuildCurve(meshBuilder, ring_centre, radius, p.m_radial_segments, v, f1, f2, angle_offset1, angle_offset2, rotation, twist_angle, irregularity, true);

            if (i == p.m_height_segments)
            {
                // Add twist angle to rotation for complete angle reference
                Quaternion rotationRef = rotation * Quaternion.Euler(0.0f, -p.m_twist_angle, 0.0f);
                BuildFork(meshBuilder, ring_centre, radius, rotationRef, p.m_branch_segments, p.m_radial_segments, new Vector2(p.m_branch_min_fork_angle, p.m_branch_max_fork_angle),
                          p.m_branch_max_bend, p.m_branch_length, p.m_branch_length_randomness, p.m_branch_twist_angle, p.m_branch_twist_randomness);
                break;
            }
        }
        Debug.Log("Number of Leaves: " + m_Leaves.Count);
        Mesh mesh = meshBuilder.CreateMesh();

        mesh.RecalculateNormals();
        return(mesh);
    }
Пример #8
0
    void BuildBranch(MeshBuilder meshBuilder, Vector3 offset, float startRadius, Quaternion startAngle, int lengthSegments, int radialSegments, Vector2 forkAngleBounds, float maxBendAngle, float branchLength, float lengthRandomness, float branchTwist, float twistRandomness, bool startTriangles, bool useMinRadius, bool generateLOD)
    {
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        // Calculate a random bend towards the sky
        Vector3 angleRand  = Vector3.zero;
        Vector3 testVector = Vector3.down;

        for (int i = 0; i < 100 && testVector.y <= p.m_branch_min_uprightness; i++)
        {
            angleRand = new Vector3(Random.Range(-maxBendAngle, maxBendAngle), Random.Range(-maxBendAngle, maxBendAngle), Random.Range(-maxBendAngle, maxBendAngle));
            Quaternion newRot = startAngle * Quaternion.Euler(angleRand.x, angleRand.y, angleRand.z);
            testVector = newRot * Vector3.up;
            if (i == 99)
            {
                Debug.LogError("Maximum iterations reached. Bend angle may not be upright!");
            }
        }


        Vector3    ringCentre = offset;
        Quaternion rotation   = Quaternion.identity;

        float twistRand  = branchTwist + Random.Range(-twistRandomness, twistRandomness);
        float lengthRand = branchLength + Random.Range(-lengthRandomness, lengthRandomness);

        float radius = startRadius;

        for (int i = 0; i <= lengthSegments; i++)
        {
            float heightRatio = (float)i / (float)lengthSegments;
            //float ringHeight = heightRatio*lengthRand;
            float twistAngle     = heightRatio * twistRand;
            bool  buildTriangles = !startTriangles && i == 0 ? false : true;
            radius = useMinRadius ? radius : radius * p.m_branch_radius_falloff;

            float v = (heightRatio * lengthRand) / (2 * Mathf.PI * radius) + 1.0f / (2 * Mathf.PI);

            BuildCurve(meshBuilder, ringCentre, radius, radialSegments, v, 0, 0, 0.0f, 0.0f, startAngle * rotation, twistAngle, 0, buildTriangles);
            if (i == lengthSegments && useMinRadius)
            {
                // Add new fork
                BuildFork(meshBuilder, ringCentre, radius, startAngle * rotation * Quaternion.Euler(0.0f, -twistRand, 0.0f), lengthSegments, radialSegments,
                          forkAngleBounds, maxBendAngle * p.m_branch_bend_falloff, branchLength * p.m_branch_length_falloff, lengthRandomness, branchTwist * p.m_branch_twist_falloff, twistRandomness);
                break;
            }
            else if (radius < p.m_branch_min_radius && useMinRadius)
            {
                // Complete branch
                rotation    = Quaternion.Euler(angleRand * heightRatio);
                ringCentre += startAngle * rotation * new Vector3(0.0f, lengthRand / lengthSegments, 0.0f);
                v           = (((float)(i + 1) / (float)lengthSegments) * lengthRand) / (2 * Mathf.PI * radius) + 1.0f / (2 * Mathf.PI);
                radius      = 0;
                BuildCurve(meshBuilder, ringCentre, radius, radialSegments, v, 0, 0, 0.0f, 0.0f, startAngle * rotation, twistAngle, 0, buildTriangles);
                if (p.m_hasLeaves)
                {
                    if (p.m_hasStems)
                    {
                        BuildStems(meshBuilder, ringCentre, startAngle * rotation * Quaternion.Euler(0.0f, twistRand, 0.0f), p.m_stem_length, p.m_stem_radius, p.m_stem_segments, p.m_stem_bend);
                    }
                    m_Leaves.Add(new LeafConstruct(ringCentre, startAngle * rotation * Quaternion.Euler(0.0f, twistRand, 0.0f), p.m_stem_length, p.m_stem_bend));
                }
                break;
            }
            rotation    = Quaternion.Euler(angleRand * heightRatio);
            ringCentre += startAngle * rotation * new Vector3(0.0f, lengthRand / lengthSegments, 0.0f);
        }
    }
Пример #9
0
    private Mesh BuildLODTrunk(int LODindex)
    {
        // Set variables from parent
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        MeshBuilder meshBuilder = new MeshBuilder();

        // Set up LOD variables
        int height_segments = p.m_height_segments;
        int radial_segments = p.m_radial_segments;
        int branch_segments = p.m_branch_segments;

        switch (LODindex)
        {
        case 1:
            height_segments = p.m_LOD1_height_segments;
            radial_segments = p.m_LOD1_radial_segments;
            branch_segments = p.m_LOD1_branch_segments;
            break;

        case 2:
            height_segments = p.m_LOD2_height_segments;
            radial_segments = p.m_LOD2_radial_segments;
            branch_segments = p.m_LOD2_branch_segments;
            break;

        default:
            Debug.LogError("Error in BuildLODTrunk(): Invalid LODindex!");
            break;
        }

        float radius = p.m_start_radius;
        float height = p.m_height;

        Vector3 offset = new Vector3(0.0f, 0.0f, 0.0f);

        Vector3    ring_centre = offset;
        Quaternion rotation    = Quaternion.identity;
        Vector3    angle_rand  = Vector3.zero;

        angle_rand.x = NextLODRand();
        angle_rand.y = NextLODRand();
        angle_rand.z = NextLODRand();
        BuildCurveSimple(meshBuilder, offset, radius, radial_segments, 0.0f, Quaternion.identity, 0.0f, false);

        float end_radius = NextLODRand();

        for (int i = 1; i <= height_segments; i++)
        {
            float ring_height = ((float)i / (float)height_segments) * height;

            float twist_angle = (ring_height * p.m_twist_angle) / height;

            float hr = (ring_height / height);
            rotation = Quaternion.Euler(angle_rand.x * hr, angle_rand.y * hr, angle_rand.z * hr);
            Vector3 new_ring_offset = new Vector3(0.0f, height / (float)height_segments, 0.0f);
            ring_centre += rotation * new_ring_offset;

            radius = p.m_start_radius - ((p.m_start_radius - end_radius) / height) * ring_height;

            float v = ring_height / (2 * Mathf.PI * radius);
            BuildCurveSimple(meshBuilder, ring_centre, radius, radial_segments, v, rotation, twist_angle, true);
            //BuildCurve(meshBuilder,ring_centre,radius,radial_segments,v,rotation,twist_angle,irregularity,true);

            if (i == height_segments)
            {
                // Add twist angle to rotation for complete angle reference
                Quaternion rotationRef = rotation * Quaternion.Euler(0.0f, -p.m_twist_angle, 0.0f);
                radius = end_radius;
                BuildLODFork(LODindex, meshBuilder, ring_centre, radius, rotationRef, branch_segments, radial_segments);
                break;
            }
        }
        //Debug.Log("Number of Leaves: " + m_Leaves.Count);
        Mesh mesh = meshBuilder.CreateMesh();

        LODRandIndex = 0;
        mesh.RecalculateNormals();
        return(mesh);
    }