画圆

来源:互联网 发布:特效软件手机版 编辑:程序博客网 时间:2024/04/29 23:11

我们知道,把圆周的1/360所对的圆心角称为1度角,记作1°,1度=60分(1°=60′),1分等于60秒(1′=60″)。以度为单位的测量角度的单位制称为角度制。


因为角度制是60进位制,所以在计算两个角的加减时经常会遇到单位转换上的麻烦。因此再数学上经常使用另一种方式度量角:把等于半径长的圆弧所对的圆心角叫1弧度,记作1(rad)。


弧度的计算公式为l/r,其中l是弧长,r是半径。

圆周的周长是2πr,那么圆周的弧度就是2πr/r=2π,则180度角的弧度则是π。

弧度制表示角时,单位是rad,例如1(rad),2π/3(rad)等可分别记作1,2π/3.

采用弧度制后,每一个角都对应一个实数。


建立一个可使用的网格Mesh:

1.为顶点数组赋值

2.为三角形数组赋值


绘制一个简单的三角形网格:

public class example:MonoBehavior  {      void Start()      {             gameObject.AddComponent("MeshFilter");             gameObject.AddComponent("MeshRenderer");             Mesh mesh = GetComponent<MeshFilter>().mesh;             mesh.Clear();             mesh.vertices = new Vector3[]{new Vector3(0,0,0),new Vector3(0,1,0),new Vector3(1,1,0)};             mesh.uv = new Vector2{new Vector2(0,0),new Vector2(0,1),new Vector2(1,1)};             mesh.trangles = new int{0,1,2};       }   }

注意:

1.Mesh、MeshFilter、MeshRenderer关系整理

在Unity3D中创建一个Cube,在Inspector可以看到其中含有MeshFilter、MeshRenderer组件。

MeshFilter含有一个Public成员 Mesh。

在Mesh中存储着三维模型的数据:vertices(顶点数据数组Vector3[])、triangles(三角形顶点索引数组,int[])、normals(法线向量数组,Vector3[])、uv(纹理坐标数组,Vector2[])。

2.冗余的顶点坐标

正方体6个面,每个面由2个三角形组成,所以共需要36个三角形顶点索引。但是正方体只有8个顶点,为什么需要24个顶点坐标数据呢?

答案是:Unity3D的Mesh.triangles是三角形索引数组,不仅依靠这个索引值索引三角形顶点坐标,而且索引纹理坐标,索引法线向量。即正方体的每个顶点都参与了3个平面,而这3个平面的法线向量是不同的,该顶点在渲染这3个平面的时候需要索引到不同的法线向量。而由于顶点坐标和法线向量是由同一个索引值triangles[Index]取得的,例如,根据triangles[0],triangles[14],triangles[17]在vertices中索引到的顶点都为(0.5,-0.5,0.5),但是在normals中索引到的法向量值各不相同。这就决定了在正方体中一个顶点,需要有3份存储。(如果你需要创建其它模型,需要根据实际情况决定顶点坐标的冗余度。实质上顶点坐标的冗余正是方便了法线坐标、纹理坐标的存取。)

3.三角形的渲染

准则:三角形有两面,正面可见,背面不可见。三角形的渲染顺序与三角形的正面法线呈左手螺旋定则

这就决定了,如果我们需要渲染如下一个正方形面,那么就需要保证组成这个正方形的两个小三角形的正面法线都是指向屏幕外的。

我在程序中的顶点顺序为,三角形1: 0->3->1,三角形2: 0->2->3 。

int currentCount=0;

  for(int i=0;i<24;i=i+4)  {      //三角形1      triangles[currentCount++]=i;      triangles[currentCount++]=i+3;      triangles[currentCount++]=i+1;      //三角形2             triangles[currentCount++]=i;     triangles[currentCount++]=i+2;     triangles[currentCount++]=i+3; }
这段代码保证了正方体的6个面,12个三角形的都正确被渲染(正面法线朝外)。

using UnityEngine;

using System.Collections;[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]public class DrawCircle : MonoBehaviour{    //圆的半径,分割数,通过算法得到:顶点的Vector3数组以及对应的三角形索引数组    public float radius = 6; //半径    public int segments = 60;//分割数    private MeshFilter meshFilter;    void Start()    {        meshFilter = GetComponent<MeshFilter>();        meshFilter.mesh = CreateMesh(radius, segments);    }    Mesh CreateMesh(float radius, int segments)    {        //vertices:顶点        int vertices_count = segments + 1;        Vector3[] vertices = new Vector3[vertices_count];//顶点数组       //vertices[0]保存圆心坐标,后面的segments个Vector3保存圆(边)上的点。        vertices[0] = Vector3.zero;        float angledegree = 360.0f;        float angleRad = Mathf.Deg2Rad * angledegree;        float angleCur = angleRad;        float angleDelta = angleRad / segments;//每个分割的弧度        for (int i = 1; i < vertices_count; i++)        {            float cosA = Mathf.Cos(angleCur);            float sinA = Mathf.Sin(angleCur);            vertices[i] = new Vector3(radius * cosA, 0, radius * sinA);            angleCur -= angleDelta;        }        //triangles        int triangle_count = segments * 3;        int[] triangles = new int[triangle_count];        //因为该案例分割了60个三角形,故最好一个索引顺序应该是:0,60,1;需要单独处理        for (int i = 0, vi = 1; i <= triangle_count - 1; i += 3, vi++)        {            triangles[i] = 0;            triangles[i + 1] = vi;            triangles[i + 2] = vi + 1;        }        //uv:        Vector2[] uvs = new Vector2[vertices_count];        for (int i = 0; i < vertices_count; i++)        {            uvs[i] = new Vector2(vertices[i].x / radius / 2 + 0.5f, vertices[i].y / radius / 2 + 0.5f);//?        }        //负载属性与mesh        Mesh mesh = new Mesh();        mesh.vertices = vertices;        mesh.triangles = triangles;        mesh.uv = uvs;        return mesh;    }}




        

0 0
原创粉丝点击