Draw a circle with Unity Mesh

Probuider

A few days ago to do a small project, we used the Unity comes with a package ProBuilder which generates a quarter of a circle Arch.

Really fun, can be customized with graphics generated in Unity Mesh in direct, rather than modeling software.

But there is a small problem, is his central point is generated in the lower left corner of the graphic when in use.

When rotation does not meet my needs, I want to be generated when the center of rotation at the center position, so prepare yourself a custom.

aims

About Mesh principles generated graphics can refer to this article speaks, though not very detailed, but enough to understand the basic concept.

Goal is to produce a bottom view of the hollow cylinder 1/4

We switch to Wireframe mode, it can be seen that there is a one vertex, and a straight line passing through the connecting section. So how do we determine the location of the vertices and line it?

Small goal - create a face

In fact, very simple, we take it step by step. A whole will generate a bit of trouble, we can be side side. Generating a first long side, the other side is similar methods to generate enough.

In the front we mentioned we want is to create a cylinder, a cylinder of an important nature is to be produced by a superimposed circular, that is, as long as we generate a circular to complete most of the work.

We know that 3D modeling is a combination of a triangle into, so we use the triangle to simulate a hollow circle.

Probuilder generated in such a hollow cylinder with the Arch, it has several parameters, namely,
\ (\ color {# 1E90FF} {Radius} \) radius, from the center to the outermost
\ (\ color {# 1E90FF} {thickness} \) thickness, from the center to the outermost periphery - center distance between the innermost
\ (\ color {# 1E90FF} {depth} \) depth
\ (\ color {# 1E90FF} {NumberOfSides} \ ) how many of the surface composition, the more smooth the surface, the poorer the performance
\ (\ color {# 1E90FF} {DrawArchDegrees} \) angle of total drawn

\ (\ color {# 1E90FF} {NumberOfSides} \) in the surface means of two triangles a circular piece makes up a ladder, a plurality of small heads Bigfoot became trapezoidal together we need.

Principles already know, just make sure that the next vertex of the triangle position on OK. As for how to determine the position of the apex of the triangle, we can look at this picture.
Mesh2.png

Is not instantaneous clarity, the red line is the intersection of the center position, numbers are numbers each vertex.

We assume that the center at the origin, where the numbers 0-1 line of 180-degree line. \ (\ # 1E90FF Color {} {} Increment \) = \ (DrawArchDegrees {} \ \ 1E90FF Color {#}) / \ (\ # 1E90FF Color {} {} NumberOfSides \) is the angle between the line and the line. Each line may be formed of angle \ (\ color {# 1E90FF} {180-Increment * i} \) to give. i for the first several lines.

By a dotted line may be ({# 1E90FF} \ color { y = r * sinθ, y = r * cosθ} \) \ obtained.

        //顶点坐标
        vertexList.Clear();
        float incrementAngle = DrawArchDegrees / NumberOfSides;
        //小于等于是因为n+1条线才能组成n个面
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float innerX = (Radius - Thickness) * Mathf.Cos(angle * Mathf.Deg2Rad);
            float innerY = (Radius - Thickness) * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(innerX, innerY, 0));
            float outsideX = Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
            float outsideY = Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(outsideX, outsideY, 0));
        }

In the above code, we have calculated the position of the vertex, the next step we need to do is to insert the apex of the triangle in order position. From Mesh this article we can see, is only a triangle will be rendered at the front of the case.

The front and back may be performed by determining the orientation of a normal line, that is, the front surface outwardly, the back surface is opposite.

In Unity, orientation can be obtained from normal left-hand rule. Out left, straight, vertical thumb and other four fingers, four fingers and then bent toward finger loop, thumb pointing direction to normal.

That in the figure above, we want to render a triangle, the order should be like this 012,321, 234, 543.

        //三角形索引
        triangleList.Clear();
        int direction = 1;
        for (int i = 0; i < NumberOfSides * 2; i++)
        {
            int[] triangleIndexs = getTriangleIndexs(i, direction);
            direction *= -1;
            for (int j = 0; j < triangleIndexs.Length; j++)
            {
                triangleList.Add(triangleIndexs[j]);
            }
        }

\ (\ color {# F08080} {getTriangleIndexs} \) code is as follows

    int[] getTriangleIndexs(int index, int direction)
    {
        int[] triangleIndexs = new int[3] { 0,1,2};
        for (int i = 0; i < triangleIndexs.Length; i++)
        {
            triangleIndexs[i] += index;
        }
        if (direction == -1)
        {
            int temp = triangleIndexs[0];
            triangleIndexs[0] = triangleIndexs[2];
            triangleIndexs[2] = temp;
        }
        return triangleIndexs;
    }

As more simple uv coordinates, the Y coordinates uv fixed inner vertex is 0, Y coordinates of the fixed outer ring vertex uv is 1, and the x-coordinate of \ (\ color {# 1E90FF} {1 / NumberOfSides} \) to obtain:

    //UV索引
    uvList.Clear();
    for (int i = 0; i <= NumberOfSides; i++)
    {
        float angle = 180 - i * incrementAngle;
        float littleX = (1.0f / NumberOfSides) * i;
        uvList.Add(new Vector2(littleX, 0));
        float bigX = (1.0f / NumberOfSides) * i;
        uvList.Add(new Vector2(bigX, 1));
    }

The complete code is as follows:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//[RequireComponent(typeof(MeshFilter))]
//[RequireComponent(typeof(MeshRenderer))]
//[ExecuteInEditMode]
public class DrawArch : MonoBehaviour
{
    public float Radius = 20.0f;                //外圈的半径
    public float Thickness = 10.0f;             //厚度,外圈半径减去内圈半径
    public float Depth = 1.0f;                  //厚度
    public float NumberOfSides = 30.0f;         //由多少个面组成
    public float DrawArchDegrees = 90.0f;       //要绘画多长
    public Material archMaterial = null;
    
    private List<Vector3> vertexList = new List<Vector3>();
    private List<int> triangleList = new List<int>();
    private List<Vector2> uvList = new List<Vector2>();

    // Start is called before the first frame update
    void Start()
    {
        GenerateVertex();
    }

    void GenerateVertex()
    {
        //顶点坐标
        vertexList.Clear();
        float incrementAngle = DrawArchDegrees / NumberOfSides;
        //小于等于是因为n+1条线才能组成n个面
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float innerX = (Radius - Thickness) * Mathf.Cos(angle * Mathf.Deg2Rad);
            float innerY = (Radius - Thickness) * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(innerX, innerY, 0));
            float outsideX = Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
            float outsideY = Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(outsideX, outsideY, 0));
        }

        //三角形索引
        triangleList.Clear();
        int direction = 1;
        for (int i = 0; i < NumberOfSides * 2; i++)
        {
            int[] triangleIndexs = getTriangleIndexs(i, direction);
            direction *= -1;
            for (int j = 0; j < triangleIndexs.Length; j++)
            {
                triangleList.Add(triangleIndexs[j]);
            }
        }

        //UV索引
        uvList.Clear();
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float littleX = (1.0f / NumberOfSides) * i;
            uvList.Add(new Vector2(littleX, 0));
            float bigX = (1.0f / NumberOfSides) * i;
            uvList.Add(new Vector2(bigX, 1));
        }
        Mesh mesh = new Mesh()
        {
            vertices = vertexList.ToArray(),
            uv = uvList.ToArray(),
            triangles = triangleList.ToArray(),
        };

        mesh.RecalculateNormals();
        gameObject.AddComponent<MeshFilter>().mesh = mesh;
        gameObject.AddComponent<MeshRenderer>().material = archMaterial;
    }

    int[] getTriangleIndexs(int index, int direction)
    {
        int[] triangleIndexs = new int[3] { 0,1,2};
        for (int i = 0; i < triangleIndexs.Length; i++)
        {
            triangleIndexs[i] += index;
        }
        if (direction == -1)
        {
            int temp = triangleIndexs[0];
            triangleIndexs[0] = triangleIndexs[2];
            triangleIndexs[2] = temp;
        }
        return triangleIndexs;
    }
}

To be continued. . .

Guess you like

Origin www.cnblogs.com/suanjie/p/11870178.html