找回密码
 注册帐号

扫一扫,访问微社区

Unity 动态创建不规则平面多边形并贴上贴图

12
回复
1266
查看
打印 上一主题 下一主题
[ 复制链接 ]
6蛮牛粉丝
1444/1500
排名
4167
昨日变化

18

主题

407

帖子

1444

积分

Rank: 6Rank: 6Rank: 6

UID
18541
好友
7
蛮牛币
150
威望
0
注册时间
2014-3-22
在线时间
661 小时
最后登录
2020-8-31

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
首先感谢https://blog.csdn.net/nanggong/article/details/54728823博主 这好像是个大妹子

如果要研究原理的请去原博主那里去研究 脑子已经被数学烧炸了

上效果图


底部红色区域是一个正方形的plan 为了方便表示 特意多创建了一个Material进行对比 UV展好了


也可以创建雷达图
自己搞吧

我使用的版本比较高 版本比较低的可以对比着操作 就是一通绑定

不会上传 比较笨 直接发放了

链接:https://pan.baidu.com/s/1DNvql-0957hxjaPgULZgeg
提取码:vn5c


回复

使用道具 举报

6蛮牛粉丝
1444/1500
排名
4167
昨日变化

18

主题

407

帖子

1444

积分

Rank: 6Rank: 6Rank: 6

UID
18541
好友
7
蛮牛币
150
威望
0
注册时间
2014-3-22
在线时间
661 小时
最后登录
2020-8-31
沙发
楼主 2020-8-14 14:56:58 只看该作者
对了 里面的点要逆时针排列 要不然会报错的
回复 支持 反对

使用道具 举报

6蛮牛粉丝
1444/1500
排名
4167
昨日变化

18

主题

407

帖子

1444

积分

Rank: 6Rank: 6Rank: 6

UID
18541
好友
7
蛮牛币
150
威望
0
注册时间
2014-3-22
在线时间
661 小时
最后登录
2020-8-31
板凳
楼主 2020-8-14 14:58:03 只看该作者
using System.Collections.Generic;
using UnityEngine;

namespace PolygonTool
{

    #region 耳切法对简单多边形进行三角形化

    /// <summary>判断凹点,凸点,耳朵的比较轴</summary>
    public enum CompareAxle
    {
        X
        Y
        Z
    }

    /// <summary>对多边形处理</summary>
    public class Triangulation
    {
        /// <summary>判断凹凸的时候的比对轴</summary>
        private CompareAxle _compareAxle = CompareAxle.Y;
        /// <summary>顶点序列</summary>
        private List<int> _vertexsSequence = new List<int>();
        /// <summary>节点管理器</summary>
        private NodeManager _nodeManager = new NodeManager();

        /// <summary>初始化</summary>
        /// <param name=\"polygonVertexs\">多边形顶点</param>
        /// <param name=\"compareAxle\">设置比较轴</param>
        public Triangulation(List<Vector3> polygonVertexs CompareAxle compareAxle)
        {
            _nodeManager.Init(polygonVertexs);
            this._compareAxle = compareAxle;
        }

        /// <summary>获取三角形的顶点序列</summary>
        public int[] GetTriangles()
        {
            while (_nodeManager.LinkedListLength >= 3)
            {
                SplitResult sr = SplitPolygon();
                if (sr == null)
                {
                    Debug.Log(\"null\");
                    return null;
                }
            }

            return _vertexsSequence.ToArray();
        }

        /// <summary>计算凹顶点,凸顶点,耳朵</summary>
        private SplitResult SplitPolygon()
        {
            //凹点
            List<Node> _concaveVertexs = new List<Node>();
            //凸点
            List<Node> _raisedVertexs = new List<Node>();
            //耳朵
            List<Node> _polygonEars = new List<Node>();
            //起始节点
            Node currentNode = _nodeManager.FirstNode;

            #region 计算凹顶点,凸顶点

            for (int i = 0; i < _nodeManager.LinkedListLength; i++)
            {
                Vector3 > 0)
                    {
                        _concaveVertexs.Add(currentNode);
                    }
                    else
                    {
                        _raisedVertexs.Add(currentNode);
                    }
                }

                if (_compareAxle == CompareAxle.X)
                {
                    if (crossRes.x > 0)
                    {
                        _concaveVertexs.Add(currentNode);
                    }
                    else
                    {
                        _raisedVertexs.Add(currentNode);
                    }
                }

                if (_compareAxle == CompareAxle.Z)
                {
                    if (crossRes.z > 0)
                    {
                        _concaveVertexs.Add(currentNode);
                    }
                    else
                    {
                        _raisedVertexs.Add(currentNode);
                    }
                }

                _polygonEars.Add(currentNode);
                currentNode = currentNode.nextNode;
            }

            for (int i = 0; i < _concaveVertexs.Count; i++)
            {
                _polygonEars.Remove(_concaveVertexs[i]);
            }
            #endregion

            #region 计算耳朵
            List<int> needRemoveIdList = new List<int>();
            for (int i = 0; i < _polygonEars.Count; i++)
            {
                Node earNode = _polygonEars[i];
                Node compareNode = earNode.nextNode.nextNode;

                while (compareNode != earNode.lastNode)
                {
                    bool isIn = IsIn(compareNode.vertex earNode.lastNode.vertex earNode.vertex
                        earNode.nextNode.vertex);

                    if (isIn == true)
                    {
                        if (_polygonEars.Contains(_polygonEars[i]))
                        {
                            needRemoveIdList.Add(_polygonEars[i].id);
                        }
                        break;
                    }
                    compareNode = compareNode.nextNode;
                }
            }

            for (int j = 0; j < needRemoveIdList.Count; j++)
            {
                for (int i = 0; i < _polygonEars.Count; i++)
                {
                    if (_polygonEars[i].id == needRemoveIdList[j])
                    {
                        _polygonEars.RemoveAt(i);
                    }
                }
            }

            #endregion

            //耳朵为空说明不是简单多边形 多边形三角化失败
            if (_polygonEars.Count == 0)
            {
                return null;
            }

            _vertexsSequence.Add(_polygonEars[0].lastNode.id);
            _vertexsSequence.Add(_polygonEars[0].id);
            _vertexsSequence.Add(_polygonEars[0].nextNode.id);
            _nodeManager.RemoveNode(_polygonEars[0]);


            return new SplitResult(_raisedVertexs _concaveVertexs _polygonEars);
        }

        /// <summary>判断一点是否在三角形内</summary>
        /// <param name=\"p\">一点</param>
        /// <param name=\"a\"></param>
        /// <param name=\"b\"></param>
        /// <param name=\"c\"></param>
        /// <returns></returns>
        public bool IsIn(Vector3 p Vector3 a Vector3 b Vector3 c)
        {
            Vector3 pa = p - a;
            Vector3 pb = p - b;
            Vector3 pc = p - c;

            Vector3 t1 = Vector3.Cross(pa pb);
            Vector3 t2 = Vector3.Cross(pb pc);
            Vector3 t3 = Vector3.Cross(pc pa);

            bool isIn2 = t1.y >= 0 && t2.y >= 0 && t3.y >= 0 || t1.y <= 0 && t2.y <= 0 && t3.y <= 0;

            return isIn2;
        }

        /// <summary>管理多边形 构成一个双向链表</summary>
        public class NodeManager
        {
            /// <summary>所有链表集合</summary>
            private List<Node> _nodeList = new List<Node>();
            public int LinkedListLength { get { return _nodeList.Count; } }
            public Node FirstNode { get { return _nodeList[0]; } }
            public void Init(List<Vector3> vertexs)
            {
                for (int i = 0; i < vertexs.Count; i++)
                {
                    Node node = new Node(i vertexs[i]);
                    _nodeList.Add(node);
                }

                for (int i = 0; i < _nodeList.Count; i++)
                {
                    if (i == 0)
                    {
                        _nodeList[i].lastNode = _nodeList[_nodeList.Count - 1];
                        _nodeList[i].nextNode = _nodeList[1];
                    }
                    else if (i == _nodeList.Count - 1)
                    {
                        _nodeList[i].lastNode = _nodeList[_nodeList.Count - 2];
                        _nodeList[i].nextNode = _nodeList[0];
                    }
                    else
                    {
                        _nodeList[i].lastNode = _nodeList[i - 1];
                        _nodeList[i].nextNode = _nodeList[i + 1];
                    }
                }
            }

            public void RemoveNode(Node node)
            {
                _nodeList.Remove(node);
                node.lastNode.nextNode = node.nextNode;
                node.nextNode.lastNode = node.lastNode;
            }
        }
        /// <summary>链表结构</summary>
        public class Node
        {
            /// <summary>// 节点角标</summary>
            public int id;
            /// <summary>节点Position</summary>
            public Vector3 vertex;
            public Node lastNode;
            public Node nextNode;

            /// <summary>初始化</summary>
            /// <param name=\"id\">节点角标</param>
            /// <param name=\"vertex\">节点Position</param>
            public Node(int id Vector3 vertex)
            {
                this.id = id;
                this.vertex = vertex;
            }

            public Node(int id Vector3 vertex Node lastNode Node nextNode)
            {
                this.id = id;
                this.vertex = vertex;
                this.lastNode = lastNode;
                this.nextNode = nextNode;
            }
        }

        public class SplitResult
        {
            /// <summary>凸顶点</summary>
            public List<Node> raisedVertexs;

            /// <summary>凹顶点</summary>
            public List<Node> concaveVertexs;

            /// <summary>耳朵</summary>
            public List<Node> polygonEars;

            public SplitResult(List<Node> raisedVertexs List<Node> concaveVertexs List<Node> polygonEars)
            {
                this.raisedVertexs = raisedVertexs;
                this.concaveVertexs = concaveVertexs;
                this.polygonEars = polygonEars;
            }
        }
    }

    #endregion
}
回复 支持 反对

使用道具 举报

6蛮牛粉丝
1444/1500
排名
4167
昨日变化

18

主题

407

帖子

1444

积分

Rank: 6Rank: 6Rank: 6

UID
18541
好友
7
蛮牛币
150
威望
0
注册时间
2014-3-22
在线时间
661 小时
最后登录
2020-8-31
地板
楼主 2020-8-14 14:59:05 只看该作者
using PolygonTool;
using System.Collections.Generic;
using UnityEngine;

public class T : MonoBehaviour
{
    /// <summary>用物体的坐标来代替点</summary>
    public List<Transform> tList;
    /// <summary>计算得到的三角形序列下标</summary>
    private List<int> resultList = new List<int>();

    private Triangulation triangulation;
    public Material mat;
    public Vector3[] vertexs;
    public Vector2[] uvs;
    GameObject tempGame;

    bool sss = true;
    private void Update()
    {
        if (sss)
        {
            sss = false;
        Start();
        }
        else
        {
            sss = true;
        }
    }
    private void Start()
    {
        #region 转坐标
        List<Vector3> posList = new List<Vector3>();
        for (int i = 0; i < tList.Count; i++)
        {
            posList.Add(tList[i].position);
        }
        #endregion

        triangulation = new Triangulation(posList CompareAxle.Y);

        int[] a = triangulation.GetTriangles();

        if (a != null)
        {
            for (int i = 0; i < a.Length; i++)
            {
                //Debug.Log(\"===:\" + a[i]);
                resultList.Add(a[i]);
            }
        }
        MeshFilter mf;
        MeshRenderer mr;
        if (tempGame==null)
        {
        tempGame = new GameObject(\"多边形\");
        mf= tempGame.AddComponent<MeshFilter>();
       mr= tempGame.AddComponent<MeshRenderer>();

        }
        else
        {
            mf = tempGame.GetComponent<MeshFilter>();
            mr = tempGame.GetComponent<MeshRenderer>();
        }

        Mesh m = new Mesh();

        vertexs = new Vector3[a.Length];
        for (int i = 0; i < vertexs.Length; i++)
        {
            vertexs[i] = tList[a[i]].position;
        }
        float left = vertexs[0].x;
        float right = vertexs[0].x;
        float up = vertexs[0].z;
        float down = vertexs[0].z;
        for (int i = 1; i < vertexs.Length; i++)
        {
            if (left > vertexs[i].x)
            {
                left = vertexs[i].x;
            }
            if (right < vertexs[i].x)
            {
                right = vertexs[i].x;
            }
            if (up < vertexs[i].z)
            {
                up = vertexs[i].z;
            }
            if (down > vertexs[i].z)
            {
                down = vertexs[i].z;
            }
        }

        uvs = new Vector2[vertexs.Length];
        float _x = right - left;
        float _y = up - down;


        int[] tri = new int[a.Length];
        for (int i = 0; i < tri.Length; i += 3)
        {
            tri[i] = i;
            tri[i + 1] = i + 2;
            tri[i + 2] = i + 1;
        }
        for (int i = 0; i < tri.Length; i += 3)
        {
            uvs[i] = new Vector2(1 - (vertexs[tri[i]].x - left) / _x 1 - (vertexs[tri[i]].z - down) / _y);
            uvs[i + 2] = new Vector2(1 - (vertexs[tri[i + 1]].x - left) / _x 1 - (vertexs[tri[i + 1]].z - down) / _y);
            uvs[i + 1] = new Vector2(1 - (vertexs[tri[i + 2]].x - left) / _x 1 - (vertexs[tri[i + 2]].z - down) / _y);
        }




        DrawSquare(vertexs);
        m.vertices = vertexs;
        m.triangles = tri;
        m.uv = uvs;
        mf.mesh = m;
        mr.material = mat;
    }
    #region 画正方形
    public GameObject games;
    void DrawSquare(Vector3[] vertexs)
    {
        float left = vertexs[0].x;
        float right = vertexs[0].x;
        float up = vertexs[0].z;
        float down = vertexs[0].z;
        for (int i = 1; i < vertexs.Length; i++)
        {
            if (left > vertexs[i].x)
            {
                left = vertexs[i].x;
            }
            if (right < vertexs[i].x)
            {
                right = vertexs[i].x;
            }
            if (up < vertexs[i].z)
            {
                up = vertexs[i].z;
            }
            if (down > vertexs[i].z)
            {
                down = vertexs[i].z;
            }
        }

        Debug.LogError(left + \"-\" + right + \"-\" + up + \"-\" + down);
        games.GetComponent<MeshFilter>();

        Mesh mesh = new Mesh();
        mesh.Clear();

        Vector3 _ld00 = new Vector3(left 0 down);
        Vector3 _lu01 = new Vector3(left 0 up);
        Vector3 _rd10 = new Vector3(right 0 down);
        Vector3 _ru11 = new Vector3(right 0 up);
        mesh.vertices = new Vector3[] { _ld00 _lu01 _ru11 _rd10 };

        mesh.triangles = new int[] { 0 1 2 0 2 3 };
        games.GetComponent<MeshFilter>().mesh = mesh;
        Vector2 _00 = new Vector2(0 0);
        Vector2 _01 = new Vector2(0 1);
        Vector2 _11 = new Vector2(1 1);
        Vector2 _10 = new Vector2(1 0);

        //mesh.uv = new Vector2[] { _00 _01 _11 _10 };
        mesh.uv = new Vector2[] { _11 _10 _00 _01 };
    }
    #endregion
    private void OnDrawGizmos()
    {
        for (int i = 0; i < tList.Count; i++)
        {
            if (i < tList.Count - 1)
                Gizmos.DrawLine(tList[i].position tList[i + 1].position);
            else
                Gizmos.DrawLine(tList[i].position tList[0].position);

        }

        Gizmos.color = Color.black;

        for (int i = 0; i < resultList.Count; i += 3)
        {
            int startIndex = resultList[i];
            int endIndex = resultList[i + 2];
            Gizmos.DrawLine(tList[startIndex].position tList[endIndex].position);
        }
    }

}
回复 支持 反对

使用道具 举报

7日久生情
2522/5000

4

主题

391

帖子

2522

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
330509
好友
0
蛮牛币
578
威望
0
注册时间
2019-8-30
在线时间
2125 小时
最后登录
2020-8-31
5#
2020-8-20 09:38:55 只看该作者
6666666666666666666666666666
回复 支持 反对

使用道具 举报

7日久生情
2021/5000
排名
1363
昨日变化

2

主题

174

帖子

2021

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
148089
好友
0
蛮牛币
2435
威望
0
注册时间
2016-5-10
在线时间
937 小时
最后登录
2020-8-31
6#
2020-8-20 19:17:10 只看该作者
很厉害了,不知道是否用的三角剖分算法
回复 支持 反对

使用道具 举报

7日久生情
3135/5000
排名
4092
昨日变化

0

主题

2242

帖子

3135

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
254705
好友
1
蛮牛币
2712
威望
0
注册时间
2017-11-16
在线时间
531 小时
最后登录
2020-8-28
7#
2020-8-21 08:12:36 只看该作者
666666666666666666666
回复 支持 反对

使用道具 举报

4四处流浪
388/500
排名
39866
昨日变化

0

主题

82

帖子

388

积分

Rank: 4

UID
253407
好友
0
蛮牛币
342
威望
0
注册时间
2017-11-9
在线时间
300 小时
最后登录
2020-8-31
8#
7 天前 只看该作者
学习学习一下
回复

使用道具 举报

7日久生情
1975/5000
排名
8746
昨日变化

0

主题

289

帖子

1975

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
236487
好友
7
蛮牛币
7028
威望
0
注册时间
2017-8-8
在线时间
1550 小时
最后登录
2020-8-31
9#
7 天前 只看该作者
goooooood
回复

使用道具 举报

6蛮牛粉丝
1444/1500
排名
4167
昨日变化

18

主题

407

帖子

1444

积分

Rank: 6Rank: 6Rank: 6

UID
18541
好友
7
蛮牛币
150
威望
0
注册时间
2014-3-22
在线时间
661 小时
最后登录
2020-8-31
10#
楼主 6 天前 只看该作者
xyx1985feng 发表于 2020-8-20 19:17
很厉害了,不知道是否用的三角剖分算法

应该不是吧 这个是耳切法 就是首先查看每个角是内凹还是外凸 如果是外凸的加入到外凸集合中 然后查看外凸点和相邻点是否包含其他点(防止出现重叠) 找出第一个不包含的来 然后组成三角形 然后把这个凸点从点集合中移除 然后循环上面的流程

不知道你说的三角剖分算法是什么意思
回复 支持 反对

使用道具 举报

5熟悉之中
869/1000
排名
5261
昨日变化

5

主题

268

帖子

869

积分

Rank: 5Rank: 5

UID
209710
好友
0
蛮牛币
2567
威望
0
注册时间
2017-6-15
在线时间
328 小时
最后登录
2020-8-31
多谢分享,
回复

使用道具 举报

3偶尔光临
200/300
排名
11820
昨日变化

1

主题

7

帖子

200

积分

Rank: 3Rank: 3Rank: 3

UID
211467
好友
0
蛮牛币
600
威望
0
注册时间
2017-3-12
在线时间
110 小时
最后登录
2020-8-29
支持一下.......
回复

使用道具 举报

4四处流浪
302/500

0

主题

74

帖子

302

积分

Rank: 4

UID
319338
好友
0
蛮牛币
475
威望
0
注册时间
2019-4-11
在线时间
228 小时
最后登录
2020-8-28
6666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则