Exemplo n.º 1
0
    /// <summary>
    /// Builds a ring of leafy parts (petals, sepals, etc.).
    /// </summary>
    /// <param name="meshBuilder">The mesh builder currently being added to.</param>
    /// <param name="offset">The position offset to apply (position at the top of the stem).</param>
    /// <param name="rotation">The rotation offset to apply(rotation at the top of the stem).</param>
    /// <param name="radius">The radius at the top of the stem.</param>
    /// <param name="partData">The parameters describing the part to be built.</param>
    private void BuildLeafRing(MeshBuilder meshBuilder, Vector3 offset, Quaternion rotation, float radius, LeafPartData partData)
    {
        //bail if this part has been disabled:
        if (!partData.m_Build)
            return;

        for (int i = 0; i < partData.m_Count; i++)
        {
            //calculate the rotation of this part:
            float yAngle = 360.0f * i / partData.m_Count;
            Quaternion radialRotation = rotation * Quaternion.Euler(0.0f, yAngle, 0.0f);

            //set the postion at the top of the stem, away from the middle:
            Vector3 position = offset + radialRotation * Vector3.forward * radius;

            //calculate a bend angle with random variation:
            float bendAngleRandom = Random.Range(-partData.m_BendAngleVariation, partData.m_BendAngleVariation);
            float bendAngle = partData.m_BendAngle + bendAngleRandom;

            //calculate a starting angle with random variation:
            float startAngleRandom = Random.Range(-partData.m_StartAngleVariation, partData.m_StartAngleVariation);
            float startAngle = partData.m_StartAngle + startAngleRandom;

            //build the leaf part:
            BuildLeafPart(meshBuilder, position, radialRotation, partData, false, bendAngle, startAngle);
        }
    }
Exemplo n.º 2
0
    /// <summary>
    /// Build a single leaf part (petals, sepals, etc.).
    /// </summary>
    /// <param name="meshBuilder">The mesh builder currently being added to.</param>
    /// <param name="offset">The position offset to apply (position at the base of the leaf part).</param>
    /// <param name="rotation">The rotation offset to apply.</param>
    /// <param name="partData">The parameters describing the part to be built.</param>
    /// <param name="isBackFace">Is this the back side of the part?</param>
    /// <param name="bendAngle">The bend angle</param>
    /// <param name="startAngle">The starting angle.</param>
    private void BuildLeafPart(MeshBuilder meshBuilder, Vector3 offset, Quaternion rotation, LeafPartData partData, bool isBackFace, float bendAngle, float startAngle)
    {
        //get the angle in radians:
        float bendAngleRadians = bendAngle * Mathf.Deg2Rad;

        //the radius of our bend (vertical) circle:
        float bendRadius = partData.m_Length / bendAngleRadians;

        //the angle increment per height segment (based on arc length):
        float angleInc = bendAngleRadians / partData.m_LengthSegmentCount;

        //get the starting angle in radians:
        float startAngleRadians = startAngle * Mathf.Deg2Rad;

        //calculate a startOffset based on the starting angle:
        Vector3 startOffset = Vector3.zero;

        startOffset.y = Mathf.Cos(startAngleRadians) * bendRadius;
        startOffset.z = Mathf.Sin(startAngleRadians) * bendRadius;

        //a multiplier to reverse some values for the back of the leaf part:
        float backFaceMultiplier = isBackFace ? -1.0f : 1.0f;

        //build the rows:
        for (int i = 0; i <= partData.m_LengthSegmentCount; i++)
        {
            //V coordinate:
            float v = (1.0f / partData.m_LengthSegmentCount) * i;

            //width of the current row, scaled to shape the leaf part:
            float localWidth = partData.m_Width * Mathf.Sin(v * Mathf.PI) * backFaceMultiplier;
            ////use this instead for rectangular leaves:
            //float localWidth = partData.m_Width * backFaceMultiplier;

            //offset the x value to put the origin of the leaf part at bottom-centre:
            float xOffset = -localWidth * 0.5f;

            //unit position along the edge of the vertical circle:
            Vector3 centrePos = Vector3.zero;
            centrePos.y = Mathf.Cos(angleInc * i + startAngleRadians);
            centrePos.z = Mathf.Sin(angleInc * i + startAngleRadians);

            //rotation at that position on the circle:
            float      bendAngleDegrees = (angleInc * i + startAngleRadians) * Mathf.Rad2Deg;
            Quaternion bendRotation     = Quaternion.Euler(bendAngleDegrees, 0.0f, 0.0f);

            //multiply the unit postion by the radius:
            centrePos *= bendRadius;

            //offset the position so that the base row (at the starting angle) sits on zero:
            centrePos -= startOffset;

            //calculate the normal for this row:
            Vector3 normal = rotation * (bendRotation * Vector3.up) * backFaceMultiplier;

            //build the row:
            for (int j = 0; j <= partData.m_WidthSegmentCount; j++)
            {
                //X position:
                float x = (localWidth / partData.m_WidthSegmentCount) * j;

                //U coordinate:
                float u = (1.0f / partData.m_WidthSegmentCount) * j;

                //calculate the final position of this quad:
                Vector3 position = offset + rotation * new Vector3(x + xOffset, centrePos.y, centrePos.z);

                Vector2 uv             = new Vector2(u, v);
                bool    buildTriangles = i > 0 && j > 0;

                //build the quad:
                BuildQuadForGrid(meshBuilder, position, uv, buildTriangles, partData.m_WidthSegmentCount + 1, normal);
            }
        }

        //if not building the back side of the leaf parts, and the part data does not have backfaces disabled,
        //rebuild this part, facing in the other direction:
        if (!isBackFace && partData.m_BuildBackfaces)
        {
            BuildLeafPart(meshBuilder, offset, rotation, partData, true, bendAngle, startAngle);
        }
    }
Exemplo n.º 3
0
    /// <summary>
    /// Build a single leaf part (petals, sepals, etc.).
    /// </summary>
    /// <param name="meshBuilder">The mesh builder currently being added to.</param>
    /// <param name="offset">The position offset to apply (position at the base of the leaf part).</param>
    /// <param name="rotation">The rotation offset to apply.</param>
    /// <param name="partData">The parameters describing the part to be built.</param>
    /// <param name="isBackFace">Is this the back side of the part?</param>
    /// <param name="bendAngle">The bend angle</param>
    /// <param name="startAngle">The starting angle.</param>
    private void BuildLeafPart(MeshBuilder meshBuilder, Vector3 offset, Quaternion rotation, LeafPartData partData, bool isBackFace, float bendAngle, float startAngle)
    {
        //get the angle in radians:
        float bendAngleRadians = bendAngle * Mathf.Deg2Rad;

        //the radius of our bend (vertical) circle:
        float bendRadius = partData.m_Length / bendAngleRadians;

        //the angle increment per height segment (based on arc length):
        float angleInc = bendAngleRadians / partData.m_LengthSegmentCount;

        //get the starting angle in radians:
        float startAngleRadians = startAngle * Mathf.Deg2Rad;

        //calculate a startOffset based on the starting angle:
        Vector3 startOffset = Vector3.zero;
        startOffset.y = Mathf.Cos(startAngleRadians) * bendRadius;
        startOffset.z = Mathf.Sin(startAngleRadians) * bendRadius;

        //a multiplier to reverse some values for the back of the leaf part:
        float backFaceMultiplier = isBackFace ? -1.0f : 1.0f;

        //build the rows:
        for (int i = 0; i <= partData.m_LengthSegmentCount; i++)
        {
            //V coordinate:
            float v = (1.0f / partData.m_LengthSegmentCount) * i;

            //width of the current row, scaled to shape the leaf part:
            float localWidth = partData.m_Width * Mathf.Sin(v * Mathf.PI) * backFaceMultiplier;
            ////use this instead for rectangular leaves:
            //float localWidth = partData.m_Width * backFaceMultiplier;

            //offset the x value to put the origin of the leaf part at bottom-centre:
            float xOffset = -localWidth * 0.5f;

            //unit position along the edge of the vertical circle:
            Vector3 centrePos = Vector3.zero;
            centrePos.y = Mathf.Cos(angleInc * i + startAngleRadians);
            centrePos.z = Mathf.Sin(angleInc * i + startAngleRadians);

            //rotation at that position on the circle:
            float bendAngleDegrees = (angleInc * i + startAngleRadians) * Mathf.Rad2Deg;
            Quaternion bendRotation = Quaternion.Euler(bendAngleDegrees, 0.0f, 0.0f);

            //multiply the unit postion by the radius:
            centrePos *= bendRadius;

            //offset the position so that the base row (at the starting angle) sits on zero:
            centrePos -= startOffset;

            //calculate the normal for this row:
            Vector3 normal = rotation * (bendRotation * Vector3.up) * backFaceMultiplier;

            //build the row:
            for (int j = 0; j <= partData.m_WidthSegmentCount; j++)
            {
                //X position:
                float x = (localWidth / partData.m_WidthSegmentCount) * j;

                //U coordinate:
                float u = (1.0f / partData.m_WidthSegmentCount) * j;

                //calculate the final position of this quad:
                Vector3 position = offset + rotation * new Vector3(x + xOffset, centrePos.y, centrePos.z);

                Vector2 uv = new Vector2(u, v);
                bool buildTriangles = i > 0 && j > 0;

                //build the quad:
                BuildQuadForGrid(meshBuilder, position, uv, buildTriangles, partData.m_WidthSegmentCount + 1, normal);
            }
        }

        //if not building the back side of the leaf parts, and the part data does not have backfaces disabled,
        //rebuild this part, facing in the other direction:
        if (!isBackFace && partData.m_BuildBackfaces)
            BuildLeafPart(meshBuilder, offset, rotation, partData, true, bendAngle, startAngle);
    }
Exemplo n.º 4
0
    /// <summary>
    /// Builds a ring of leafy parts (petals, sepals, etc.).
    /// </summary>
    /// <param name="meshBuilder">The mesh builder currently being added to.</param>
    /// <param name="offset">The position offset to apply (position at the top of the stem).</param>
    /// <param name="rotation">The rotation offset to apply(rotation at the top of the stem).</param>
    /// <param name="radius">The radius at the top of the stem.</param>
    /// <param name="partData">The parameters describing the part to be built.</param>
    private void BuildLeafRing(MeshBuilder meshBuilder, Vector3 offset, Quaternion rotation, float radius, LeafPartData partData)
    {
        //bail if this part has been disabled:
        if (!partData.m_Build)
        {
            return;
        }

        for (int i = 0; i < partData.m_Count; i++)
        {
            //calculate the rotation of this part:
            float      yAngle         = 360.0f * i / partData.m_Count;
            Quaternion radialRotation = rotation * Quaternion.Euler(0.0f, yAngle, 0.0f);

            //set the postion at the top of the stem, away from the middle:
            Vector3 position = offset + radialRotation * Vector3.forward * radius;

            //calculate a bend angle with random variation:
            float bendAngleRandom = Random.Range(-partData.m_BendAngleVariation, partData.m_BendAngleVariation);
            float bendAngle       = partData.m_BendAngle + bendAngleRandom;

            //calculate a starting angle with random variation:
            float startAngleRandom = Random.Range(-partData.m_StartAngleVariation, partData.m_StartAngleVariation);
            float startAngle       = partData.m_StartAngle + startAngleRandom;

            //build the leaf part:
            BuildLeafPart(meshBuilder, position, radialRotation, partData, false, bendAngle, startAngle);
        }
    }