找回密碼
 注冊帳號

掃一掃,訪問微社區

Unity 動態創建不規則平面多邊形并貼上貼圖

15
回復
2998
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
7日久生情
1684/5000
排名
4167
昨日變化

19

主題

422

帖子

1684

積分

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

UID
18541
好友
7
蠻牛幣
629
威望
0
注冊時間
2014-3-22
在線時間
885 小時
最后登錄
2020-11-30

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

x
首先感謝https://blog.csdn.net/nanggong/article/details/54728823博主 這好像是個大妹子

如果要研究原理的請去原博主那里去研究 腦子已經被數學燒炸了

上效果圖


底部紅色區域是一個正方形的plan 為了方便表示 特意多創建了一個Material進行對比 UV展好了


也可以創建雷達圖
自己搞吧

我使用的版本比較高 版本比較低的可以對比著操作 就是一通綁定

不會上傳 比較笨 直接發放了

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


回復

使用道具 舉報

7日久生情
1684/5000
排名
4167
昨日變化

19

主題

422

帖子

1684

積分

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

UID
18541
好友
7
蠻牛幣
629
威望
0
注冊時間
2014-3-22
在線時間
885 小時
最后登錄
2020-11-30
沙發
樓主 2020-8-14 14:56:58 只看該作者
對了 里面的點要逆時針排列 要不然會報錯的
回復 支持 反對

使用道具 舉報

7日久生情
1684/5000
排名
4167
昨日變化

19

主題

422

帖子

1684

積分

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

UID
18541
好友
7
蠻牛幣
629
威望
0
注冊時間
2014-3-22
在線時間
885 小時
最后登錄
2020-11-30
板凳
樓主 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
}
回復 支持 反對

使用道具 舉報

7日久生情
1684/5000
排名
4167
昨日變化

19

主題

422

帖子

1684

積分

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

UID
18541
好友
7
蠻牛幣
629
威望
0
注冊時間
2014-3-22
在線時間
885 小時
最后登錄
2020-11-30
地板
樓主 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日久生情
3647/5000

4

主題

400

帖子

3647

積分

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

UID
330509
好友
0
蠻牛幣
1144
威望
0
注冊時間
2019-8-30
在線時間
3281 小時
最后登錄
2020-11-30
5#
2020-8-20 09:38:55 只看該作者
6666666666666666666666666666
回復 支持 反對

使用道具 舉報

7日久生情
2158/5000
排名
1363
昨日變化

2

主題

182

帖子

2158

積分

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

UID
148089
好友
0
蠻牛幣
2421
威望
0
注冊時間
2016-5-10
在線時間
1066 小時
最后登錄
2020-11-24
6#
2020-8-20 19:17:10 只看該作者
很厲害了,不知道是否用的三角剖分算法
回復 支持 反對

使用道具 舉報

7日久生情
3326/5000
排名
4092
昨日變化

0

主題

2386

帖子

3326

積分

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

UID
254705
好友
1
蠻牛幣
2859
威望
0
注冊時間
2017-11-16
在線時間
578 小時
最后登錄
2020-11-30
7#
2020-8-21 08:12:36 只看該作者
666666666666666666666
回復 支持 反對

使用道具 舉報

4四處流浪
403/500
排名
39867
昨日變化

0

主題

82

帖子

403

積分

Rank: 4

UID
253407
好友
0
蠻牛幣
396
威望
0
注冊時間
2017-11-9
在線時間
315 小時
最后登錄
2020-11-3
8#
2020-8-24 10:35:18 只看該作者
學習學習一下
回復

使用道具 舉報

7日久生情
2449/5000
排名
8747
昨日變化

0

主題

336

帖子

2449

積分

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

UID
236487
好友
9
蠻牛幣
7592
威望
0
注冊時間
2017-8-8
在線時間
1977 小時
最后登錄
2020-11-30
9#
2020-8-24 11:12:02 只看該作者
goooooood
回復

使用道具 舉報

7日久生情
1684/5000
排名
4167
昨日變化

19

主題

422

帖子

1684

積分

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

UID
18541
好友
7
蠻牛幣
629
威望
0
注冊時間
2014-3-22
在線時間
885 小時
最后登錄
2020-11-30
10#
樓主 2020-8-25 16:57:39 只看該作者
xyx1985feng 發表于 2020-8-20 19:17
很厲害了,不知道是否用的三角剖分算法

應該不是吧 這個是耳切法 就是首先查看每個角是內凹還是外凸 如果是外凸的加入到外凸集合中 然后查看外凸點和相鄰點是否包含其他點(防止出現重疊) 找出第一個不包含的來 然后組成三角形 然后把這個凸點從點集合中移除 然后循環上面的流程

不知道你說的三角剖分算法是什么意思
回復 支持 反對

使用道具 舉報

5熟悉之中
926/1000
排名
5261
昨日變化

5

主題

269

帖子

926

積分

Rank: 5Rank: 5

UID
209710
好友
0
蠻牛幣
2620
威望
0
注冊時間
2017-6-15
在線時間
384 小時
最后登錄
2020-11-25
11#
2020-8-27 13:30:07 只看該作者
多謝分享,
回復

使用道具 舉報

3偶爾光臨
214/300
排名
11820
昨日變化

1

主題

8

帖子

214

積分

Rank: 3Rank: 3Rank: 3

UID
211467
好友
0
蠻牛幣
679
威望
0
注冊時間
2017-3-12
在線時間
123 小時
最后登錄
2020-11-30
12#
2020-8-28 09:06:14 只看該作者
支持一下.......
回復

使用道具 舉報

4四處流浪
332/500

0

主題

76

帖子

332

積分

Rank: 4

UID
319338
好友
0
蠻牛幣
637
威望
0
注冊時間
2019-4-11
在線時間
256 小時
最后登錄
2020-11-30
13#
2020-8-28 09:09:19 只看該作者
6666666666666
回復

使用道具 舉報

7日久生情
3326/5000
排名
4092
昨日變化

0

主題

2386

帖子

3326

積分

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

UID
254705
好友
1
蠻牛幣
2859
威望
0
注冊時間
2017-11-16
在線時間
578 小時
最后登錄
2020-11-30
14#
2020-9-7 15:44:56 只看該作者
66666666666666666666666
回復 支持 反對

使用道具 舉報

3偶爾光臨
245/300
排名
9679
昨日變化

0

主題

73

帖子

245

積分

Rank: 3Rank: 3Rank: 3

UID
255527
好友
0
蠻牛幣
6
威望
0
注冊時間
2017-11-21
在線時間
56 小時
最后登錄
2020-9-19
15#
2020-9-16 11:42:12 只看該作者
漏掉了,可以自己下載下工程 導入 就可以查看的都
回復 支持 反對

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

内蒙古麻将app 四川快乐12走势图怎么看 1.16公牛vs骑士直播 贵阳微乐捉鸡麻将 好友房间麻将 中国福利彩票3d布衣 六会彩管家婆精选全年资料 河南22选5走势图带连线 麻将单机版闯关 打广东推倒胡麻将心得 金博棋牌app苹果版 快乐10分稳赚技巧 福建快3开奖结果走势 七乐彩百度预测 独行侠vs北京 卡五星麻将免费下 友乐广西麻将2元微信群