Unity 网格 绘制
网格绘制主要用是对Mesh进行操作,通过对vertex和triangles进行操作生成对应的面片;
这里首先得用到一个类:Triangulator(根据vertex生成triangles数组)
using UnityEngine;
using System.Collections.Generic; public class Triangulator
{
private static List<Vector2> points;
private static Vector3 cameraPosition; public static Vector2[] ToVector2(Vector3[] m_points)
{
Vector2[] vertices2d = new Vector2[m_points.Length];
for (int i = ; i < m_points.Length; i++)
{
Vector3 pos = m_points[i];
vertices2d[i] = new Vector2(pos.x, pos.z);
}
return vertices2d;
} public static int[] Triangulate(Vector2[] m_points, Vector3 m_cameraPosition)
{
points = new List<Vector2>(m_points);
cameraPosition = m_cameraPosition; List<int> indices = new List<int>(); int n = points.Count;
if (n < )
return indices.ToArray(); int[] V = new int[n];
if (Area() > )
{
for (int v = ; v < n; v++)
V[v] = v;
}
else
{
for (int v = ; v < n; v++)
V[v] = (n - ) - v;
} int nv = n;
int count = * nv;
for (int m = , v = nv - ; nv > ;)
{
if ((count--) <= )
break; int u = v;
if (nv <= u)
u = ;
v = u + ;
if (nv <= v)
v = ;
int w = v + ;
if (nv <= w)
w = ; if (Snip(u, v, w, nv, V))
{
int a, b, c, s, t;
a = V[u];
b = V[v];
c = V[w];
indices.Add(a);
indices.Add(b);
indices.Add(c);
m++;
for (s = v, t = v + ; t < nv; s++, t++)
V[s] = V[t];
nv--;
count = * nv;
}
} bool reversFlag = true;
int i0 = indices[];
int i1 = indices[];
int i2 = indices[];
Vector3 pos0 = new Vector3(points[i0].x, 0f, points[i0].y);
Vector3 pos1 = new Vector3(points[i1].x, 0f, points[i1].y);
Vector3 pos2 = new Vector3(points[i2].x, 0f, points[i2].y);
Vector3 v1 = pos1 - pos0;
Vector3 v2 = pos2 - pos1;
Vector3 crossVec = Vector3.Cross(v1, v2);
if (Vector3.Dot(cameraPosition, crossVec) > )
{
reversFlag = false;
}
if (reversFlag)
{
indices.Reverse();
} return indices.ToArray();
} private static float Area()
{
int n = points.Count;
float A = 0.0f;
for (int p = n - , q = ; q < n; p = q++)
{
Vector2 pval = points[p];
Vector2 qval = points[q];
A += pval.x * qval.y - qval.x * pval.y;
}
return (A * 0.5f);
} private static bool Snip(int u, int v, int w, int n, int[] V)
{
int p;
Vector2 A = points[V[u]];
Vector2 B = points[V[v]];
Vector2 C = points[V[w]];
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
return false;
for (p = ; p < n; p++)
{
if ((p == u) || (p == v) || (p == w))
continue;
Vector2 P = points[V[p]];
if (InsideTriangle(A, B, C, P))
return false;
}
return true;
} private static bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
{
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp; ax = C.x - B.x; ay = C.y - B.y;
bx = A.x - C.x; by = A.y - C.y;
cx = B.x - A.x; cy = B.y - A.y;
apx = P.x - A.x; apy = P.y - A.y;
bpx = P.x - B.x; bpy = P.y - B.y;
cpx = P.x - C.x; cpy = P.y - C.y; aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}
}
Triangulator.cs
然后我们创建一个脚本:DrawMesh.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System; public class DrawMesh : MonoBehaviour
{
#region 公共变量
/// <summary>
/// 绘制模式,间断、连续
/// </summary>
public enum DrawMeshModel { Intermittently, Continuously }; /// <summary>
/// 线段材质、网格材质
/// </summary>
public Material lineMat, meshMat; /// <summary>
/// 绘制模式
/// </summary>
public DrawMeshModel drawModel = DrawMeshModel.Intermittently; public float lineWidth = 0.5f;//线段宽度
public float meshAlpha = 0.2f;//网格透明度
#endregion #region 私有变量
Vector3[] points = new Vector3[]; LineRenderer lineTemp;
GameObject lineObject; MeshFilter meshFilter;
GameObject meshObject;
Mesh mesh;//网格 Ray ray;
RaycastHit hit; /// <summary>
/// 记录上一点位置
/// </summary>
Vector3 last = Vector3.zero;
#endregion void Start()
{
lineObject = new GameObject("LineGameObject");
lineTemp = lineObject.AddComponent<LineRenderer>();
lineTemp.SetWidth(lineWidth, lineWidth);
lineTemp.material = lineMat; meshObject = new GameObject("MeshGameObject");
meshFilter = meshObject.AddComponent<MeshFilter>();
meshObject.AddComponent<MeshRenderer>();
meshObject.GetComponent<Renderer>().material = meshMat;
Color tempColor = meshMat.color;
tempColor.a = meshAlpha;
meshMat.color = tempColor;
mesh = new Mesh(); lineObject.SetActive(false);
} void Update()
{
if (Input.GetMouseButton() && drawModel == DrawMeshModel.Continuously
|| Input.GetMouseButtonDown() && drawModel == DrawMeshModel.Intermittently)
{
if (!lineObject.activeInHierarchy)
lineObject.SetActive(true); ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
if (drawModel == DrawMeshModel.Continuously)
{
if (last == Vector3.zero)
{
last = hit.point;
return;
}
else if (Vector3.Distance(last, hit.point) < 1f)
{
return;
}
last = hit.point;
} Array.Resize(ref points, points.Length + );
points[points.Length - ] = hit.point + new Vector3(, 0.25f, );
lineTemp.SetVertexCount(points.Length);
lineTemp.SetPosition(points.Length - , points[points.Length - ]); if (points.Length > )
{
mesh.vertices = points;
mesh.triangles = Triangulator.Triangulate(Triangulator.ToVector2(points), Camera.main.transform.position);
meshFilter.mesh = mesh;
}
}
}
}
}
将DrawMesh脚本放置到物体上,给LineRenderer和Mesh赋上材质,这里我创建了一个枚举:DrawMeshModel;
通过选择Draw Model为Intermittently进行点击绘图,选择Continuously进行连续绘图;
设置线段宽度Line Width,网格透明度Mesh Alpha;
最后通过鼠标在Collider上绘制Mesh形状。
最终效果1:
最终效果2:
截图和GIF并非同一次画的,录的视频没上传成功,只好转成了gif,另外又截了图。
Unity 网格 绘制的更多相关文章
- Unity网格合并_材质合并
[转]Unity网格合并_材质合并 原帖请戳:Unity网格合并_材质合并 写在前面: 从优化角度,Mesh需要合并. 从换装的角度(这里指的是换形状.换组成部件的换装,而不是挂点型的换装),都需要网 ...
- 【转】Unity网格合并_材质合并
原帖请戳:Unity网格合并_材质合并 写在前面: 从优化角度,Mesh需要合并. 从换装的角度(这里指的是换形状.换组成部件的换装,而不是挂点型的换装),都需要网格合并.材质合并.如果是人物的换装, ...
- Unity Gizmos绘制指定长宽的网格
using UnityEngine; using System.Collections; public class GridMap : MonoBehaviour { ; //宽度 ; //长度 vo ...
- ICEM(2)—机翼翼稍网格绘制
有时我们需要观察翼尖涡,这就需要将机翼全部被网格包围.但是网上比较多的教程都是机翼边缘即为网格边缘,机翼位于网格内部的不多.若是直接将网格拉伸,则会产生结构和非结构网格交错的情况.下面是绘制步骤 1. ...
- Unity 网格合并
从优化角度,Mesh需要合并. 从换装的角度(这里指的是换形状.换组成部件的换装,而不是挂点型的换装),都需要网格合并.材质合并.如果是人物的换装,那么需要合并SkinnedMeshRenderer, ...
- unity EditorGUILayer绘制报错
最近在开发一个可视化工具的时候,遇到了一个代码错误,小小的记录一下 具体的报错信息:ArgumentException: Getting control 0's position in a group ...
- unity gizmo绘制圆形帮助调试
using UnityEngine; using System.Collections; using System; public class LearnGrazio : MonoBehaviour ...
- unity中绘制战争迷雾
接上一篇中说的游戏,我们已经实现了client.host上的一个物体可见不可见的行为.之后我们可以加入类似检查两个单位之间的距离.或是两个单位之间有无阻挡物来进一步实现游戏机制. 在这篇随笔中我会首先 ...
- ICEM(1)—边界结构网格绘制
以两个圆为例 1. geometry→ create curve→ 选择圆,随便画两个圆 2. block下选择create block,选择第一项,initial block,设置改为2D Plan ...
随机推荐
- NServiceBus官方文档翻译(二)NServiceBus 入门
在这篇教程中我们将学习如何创建一个非常简单的由客户端向服务端发送消息的订单系统.该系统包括三个项目:Client.Server 和 Messages,我们将按照以下步骤来完成这个任务. 创建 Clie ...
- PAT 1044 火星数字
https://pintia.cn/problem-sets/994805260223102976/problems/994805279328157696 火星人是以13进制计数的: 地球人的0被火星 ...
- springMVC的接受参数三种样例
- POJ 1125 Stockbroker Grapevine(最短路基础题)
Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spre ...
- 【刷题】BZOJ 4945 [Noi2017]游戏
Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 字符串里的'x'看起来很烦,于是考虑枚举这些'x' ...
- 年度编程语言最佳候选人:Kotlin vs. C
转瞬之间,今年已进入为期不足一个月的倒计时模式.在编程语言界,谁将问鼎 2017 年度编程语言?诸多开发者众说纷纭,有人说是最近风头正盛且被纳入中国高考科目的 Python.有人认为还是老牌常青藤 J ...
- 【Revit API】FamilyInstance、FamilySymbol、Family的寻找关系
话不多说,做个笔记 FamilyInstance instance; var typeid = instance.GetTypeId(); var symbol = RevitDoc.GetEleme ...
- Graham's Scan法求解凸包问题
概念 凸包(Convex Hull)是一个计算几何(图形学)中的概念.用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的.严谨的定义和相关概念参 ...
- Java 8 中 Date与LocalDateTime、LocalDate、LocalTime互转
Java 8中 java.util.Date 类新增了两个方法,分别是from(Instant instant)和toInstant()方法 // Obtains an instance of Dat ...
- 关于xmlhttp会使用ie的缓存的问题及解决
在浏览器(如:IE)的客户端使用xmlhttp读取网络资源的时候,需要考虑到浏览器本地缓存的问题. 如果希望读取的数据是实时更新的,也就是不想从本地缓存中读取数据,我之前常用的方法是在请求网址后面加一 ...