【Unity】Mesh网格编程(四)麦比乌斯环

前言


事隔四个多月,第二篇网格编程原创,本次献给大家的是麦比乌斯环。

事实上这个早就想做了,还是轻松下来的时候思绪转的快。

不废话,先看效果:





博文首发:http://blog.csdn.net/duzixi


project资源准备:

1. 本脚本要放在Editor目录下

2. 在资源中有一个空对象,作为顶点预设体,创建时要引入

3. 在Resources目录下有一个材质。叫"M"


源码:

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 脚本功能:扩展Unity编辑器。在GameObject文件夹下加入“麦比乌斯带”文件夹以向导方式生成麦比乌斯带3D模型对象
/// 加入对象:无(在Editor文件夹中)
/// 创建时间:2015年6月27日14:16:16
/// 创建人员:杜子兮
/// 版权声明:2015 www.duzixi.com
/// 技术要点:
/// 1. 通过生成。父子化和旋转空对象确认各个顶点位置
/// 2. 依据几何顶点位置生成网格顶点位置
/// </summary>
public class CreateMesh : ScriptableWizard {
    public int n = 50;       // 分割数
    public float r = 5;      // 半径
    public float h = 0.2f;   // 半高
    public GameObject point; // 顶点的预设体(选择适当的图标可显示顶点号)

    [MenuItem("GameObject/麦比乌斯带")]
    static void Create() {
        DisplayWizard<CreateMesh>("创建麦比乌斯带", "创建");
    }

    void OnWizardCreate() {
        // Step 1: 确定顶点位置
        List<Vector3> vList = new List<Vector3>();

        GameObject obj = new GameObject();  // 实例化要生成的目标对象
        obj.name = "麦比乌斯带";
        
        float angle = 2 * Mathf.PI / n;     // 计算单位弧度

        for (int i = 0; i < n; i++)
        {
            // 分别计算带子上中下三个顶点位置并保存到数组中
            Vector3 center = new Vector3(Mathf.Cos(angle * i), 0, Mathf.Sin(angle * i));
            Vector3[] vs = new Vector3[3] { center, center + h * Vector3.down, center + h * Vector3.up };

            // 计算中心点的角度,使之朝向坐标原点
            Quaternion rot = Quaternion.Euler(new Vector3(0, -90 - 360 / n * i, 0));

            // 生成顶点对象
            GameObject p0 = Instantiate(point, vs[0], rot) as GameObject ;
            GameObject p1 = Instantiate(point, vs[1], Quaternion.identity) as GameObject;
            GameObject p2 = Instantiate(point, vs[2], Quaternion.identity) as GameObject;

            // 设置顶点名字(用于调试)
            p0.name = "c" + i;
            p1.name = 2 * i + "";
            p2.name = 2 * i + 1 + "";

            // 让上下边缘的点认中心点为父对象
            p0.transform.parent = obj.transform;
            p1.transform.parent = p0.transform;
            p2.transform.parent = p0.transform;

            // 通过旋转中心点。改变上下边缘顶点的位置
            p0.transform.Rotate(Vector3.right, 360 / n * i);

            // 将上下边缘顶点加入到顶点列表中
            vList.Add(p1.transform.position);
            vList.Add(p2.transform.position);

        }

        // Step 2: 生成顶点数组
        Vector3[] Vs = new Vector3[6 * n];
        int index = 0;

        for (int i = 0; i < 2 * n - 2; i += 2)
        {
            Vs[index++] = vList[i];
            Vs[index++] = vList[i + 1];
            Vs[index++] = vList[i + 2];
            Vs[index++] = vList[i + 2];
            Vs[index++] = vList[i + 1];
            Vs[index++] = vList[i + 3];
        }

        // 结合处顶点
        Vs[index++] = vList[2 * n - 2];
        Vs[index++] = vList[2 * n - 1];
        Vs[index++] = vList[0];
        Vs[index++] = vList[1];
        Vs[index++] = vList[0];
        Vs[index++] = vList[2 * n - 1];

        // Step 3: 缔造三角形索引
        int[] Ts = new int[Vs.Length];
        for (int i = 0; i < Vs.Length; i++)
        {
            Ts[i] = i;
        }

        // Step 4: 给目标对象加入网格组件
        obj.AddComponent<MeshFilter>();
        obj.AddComponent<MeshRenderer>();

        Mesh mesh = new Mesh();
        mesh.vertices = Vs;
        mesh.triangles = Ts;
        obj.GetComponent<MeshFilter>().mesh = mesh;

        // Step 5: 加载材质资源,加入给目标对象
        Material m = Resources.Load<Material>("M");
        obj.renderer.sharedMaterial = m;
    }

}



后记:

形状不是严格的麦比乌斯环,渲染仅仅渲染了一面。眼下没有加法线和切线。

posted @ 2017-05-16 11:59  jzdwajue  阅读(299)  评论(0编辑  收藏  举报