Ejemplo n.º 1
0
    // Creates a fork and builds 2 branches off it
    // -> radiusRef: radius of trunk
    // -> angleRef: angle of the final trunk ring
    void BuildFork(MeshBuilder meshBuilder, Vector3 offset, float radiusRef, Quaternion angleRef, int lengthSegments, int radialSegments, Vector2 forkAngleBounds, float maxBendAngle, float branchLength, float lengthRandomness, float branchTwist, float twistRandomness)
    {
        // Calculate a random angle for branches to leave from
        float forkAngle = Random.Range(forkAngleBounds.x, forkAngleBounds.y) * (Random.Range(0, 1) == 1 ? 1:-1);     // angle of the fork ring (vertices curving between branches)

        LODRandNums.Add(forkAngle);

        // Add offset to LODList for greater accuracy
        LODRandNums.Add(offset.x);
        LODRandNums.Add(offset.y);
        LODRandNums.Add(offset.z);

        float angle_A  = (Mathf.PI / 4.0f) + (forkAngle * Mathf.Deg2Rad) / 2.0f;
        float angle_B  = (Mathf.PI / 4.0f) - (forkAngle * Mathf.Deg2Rad) / 2.0f;
        float radius_A = Mathf.Cos(angle_A) * radiusRef;
        float radius_B = Mathf.Cos(angle_B) * radiusRef;

        Quaternion ringRotation_A = angleRef * Quaternion.Euler(angle_A * Mathf.Rad2Deg, 0.0f, 0.0f);
        Vector3    ringCentre_A   = (ringRotation_A * (new Vector3(0.0f, radiusRef, 0.0f))) + offset;
        Quaternion ringRotation_B = angleRef * Quaternion.Euler(-angle_B * Mathf.Rad2Deg, 0.0f, 0.0f);
        Vector3    ringCentre_B   = (ringRotation_B * (new Vector3(0.0f, radiusRef, 0.0f))) + offset;

        int segments_A = radialSegments;
        int segments_B = radialSegments;

        if (radius_A > radius_B)
        {
            ringCentre_B = offset;
            segments_B   = Mathf.RoundToInt(radialSegments * (radius_B / radiusRef));
            if (segments_B < 3)
            {
                segments_B = 3;
            }
        }
        if (radius_B > radius_A)
        {
            ringCentre_A = offset;
            segments_A   = Mathf.RoundToInt(radialSegments * (radius_A / radiusRef));
            if (segments_A < 3)
            {
                segments_A = 3;
            }
        }

        BuildBranch(meshBuilder, ringCentre_A, radius_A, ringRotation_A, lengthSegments, segments_A, forkAngleBounds, maxBendAngle, branchLength, lengthRandomness, branchTwist, twistRandomness, true);

        BuildBranch(meshBuilder, ringCentre_B, radius_B, ringRotation_B, lengthSegments, segments_B, forkAngleBounds, maxBendAngle, branchLength, lengthRandomness, branchTwist, twistRandomness, false);
    }
Ejemplo n.º 2
0
    private Mesh BuildTrunk(bool setupLOD)
    {
        // Set variables from parent
        PGTreeBase p = transform.parent.GetComponent("PGTreeBase") as PGTreeBase;

        // Ensure leaf list is empty
        m_Leaves.Clear();

        MeshBuilder meshBuilder = new MeshBuilder();

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

        int   f1            = 0;
        int   f2            = 0;
        float angle_offset1 = 0.0f;
        float angle_offset2 = 0.0f;

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

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

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

        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));
        LODRandNums.Add(angle_rand.x);
        LODRandNums.Add(angle_rand.y);
        LODRandNums.Add(angle_rand.z);

        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_s == 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_s == TrunkCurveType.Exponential || p.m_trunk_curve_type_s == TrunkCurveType.ExpoLinear)
            {
                bool isExpoLin = p.m_trunk_curve_type_s == 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);
                LODRandNums.Add(radius);
                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();

        //Debug.Log("Length of LODRandNums = " + LODRandNums.Count);
        mesh.RecalculateNormals();
        return(mesh);
    }
Ejemplo n.º 3
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;
        float   maxAngle   = maxBendAngle;

        for (int i = 0; i < 100 && testVector.y <= p.m_branch_min_uprightness; i++)
        {
            angleRand = new Vector3(Random.Range(-maxAngle, maxAngle), Random.Range(-maxAngle, maxAngle), Random.Range(-maxAngle, maxAngle));
            maxAngle += 30;
            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!");
            }
        }
        LODRandNums.Add(angleRand.x);
        LODRandNums.Add(angleRand.y);
        LODRandNums.Add(angleRand.z);

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

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

        LODRandNums.Add(twistRand);
        LODRandNums.Add(lengthRand);

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


            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;
            }
            BuildCurve(meshBuilder, ringCentre, radius, radialSegments, v, 0, 0, 0.0f, 0.0f, startAngle * rotation, twistAngle, 0, buildTriangles);
            rotation    = Quaternion.Euler(angleRand * ((float)i / (float)(lengthSegments + 1)));
            ringCentre += startAngle * rotation * new Vector3(0.0f, lengthRand / (float)lengthSegments, 0.0f);
        }
    }