Unity3D动态生成平面网格
程序员文章站
2023-12-11 08:03:16
在编写几何着色器的时候发现默认的plane无法满足需求,并且顶点顺序未知,于是便写了一个网格生成代码,便于生成指定大小的plane,且顶点顺序可控。
效果如下:
一...
在编写几何着色器的时候发现默认的plane无法满足需求,并且顶点顺序未知,于是便写了一个网格生成代码,便于生成指定大小的plane,且顶点顺序可控。
效果如下:
一个单元格由4个顶点,两个三角面组成。
四个顶点如下图
则生成面的顶点顺序为:
左上三角形:0 -> 1 -> 2
右下三角形:2 -> 3 -> 0
unity中顺时针绘制为正面,逆时针绘制为反面。
实现脚本如下:
//planebuilder.cs using system.collections; using system.collections.generic; using unityengine; #region editor #if unity_editor using unityeditor; [customeditor(typeof(planebuilder))] public class planebuildereditor : editor { public override void oninspectorgui() { planebuilder builder = (planebuilder)target; editorgui.beginchangecheck(); base.oninspectorgui(); if (editorgui.endchangecheck()) { builder.updatemesh(); } if (guilayout.button("更新网格")) { builder.updatemesh(); } } } #endif #endregion editor [requirecomponent(typeof(meshfilter), typeof(meshrenderer))] public class planebuilder : monobehaviour { [serializefield] private meshfilter _meshfilter; [serializefield] private meshrenderer _meshrenderer; /// <summary> /// 单元格大小 /// </summary> [serializefield] private vector2 _cellsize = new vector2(1, 1); /// <summary> /// 网格大小 /// </summary> [serializefield] private vector2int _gridsize = new vector2int(2, 2); public meshrenderer meshrenderer { get { return _meshrenderer; } } public meshfilter meshfilter { get { return _meshfilter; } } private void awake() { _meshfilter = getcomponent<meshfilter>(); _meshrenderer = getcomponent<meshrenderer>(); updatemesh(); } public void updatemesh() { mesh mesh = new mesh(); //计算plane大小 vector2 size; size.x = _cellsize.x * _gridsize.x; size.y = _cellsize.y * _gridsize.y; //计算plane一半大小 vector2 halfsize = size / 2; //计算顶点及uv list<vector3> vertices = new list<vector3>(); list<vector2> uvs = new list<vector2>(); vector3 vertice = vector3.zero; vector2 uv = vector3.zero; for (int y = 0; y < _gridsize.y + 1; y++) { vertice.z = y * _cellsize.y - halfsize.y;//计算顶点y轴 uv.y = y * _cellsize.y / size.y;//计算顶点纹理坐标v for (int x = 0; x < _gridsize.x + 1; x++) { vertice.x = x * _cellsize.x - halfsize.x;//计算顶点x轴 uv.x = x * _cellsize.x / size.x;//计算顶点纹理坐标u vertices.add(vertice);//添加到顶点数组 uvs.add(uv);//添加到纹理坐标数组 } } //顶点序列 int a = 0; int b = 0; int c = 0; int d = 0; int startindex = 0; int[] indexs = new int[_gridsize.x * _gridsize.y * 2 * 3];//顶点序列 for (int y = 0; y < _gridsize.y; y++) { for (int x = 0; x < _gridsize.x; x++) { //四边形四个顶点 a = y * (_gridsize.x + 1) + x;//0 b = (y + 1) * (_gridsize.x + 1) + x;//1 c = b + 1;//2 d = a + 1;//3 //计算在数组中的起点序号 startindex = y * _gridsize.x * 2 * 3 + x * 2 * 3; //左上三角形 indexs[startindex] = a;//0 indexs[startindex + 1] = b;//1 indexs[startindex + 2] = c;//2 //右下三角形 indexs[startindex + 3] = c;//2 indexs[startindex + 4] = d;//3 indexs[startindex + 5] = a;//0 } } // mesh.setvertices(vertices);//设置顶点 mesh.setuvs(0, uvs);//设置uv mesh.setindices(indexs, meshtopology.triangles, 0);//设置顶点序列 mesh.recalculatenormals(); mesh.recalculatebounds(); mesh.recalculatetangents(); _meshfilter.mesh = mesh; } #if unity_editor private void onvalidate() { if (null == _meshfilter) { _meshfilter = getcomponent<meshfilter>(); } if (null == _meshrenderer) { _meshrenderer = getcomponent<meshrenderer>(); if (null == _meshrenderer.sharedmaterial) { _meshrenderer.sharedmaterial = new material(shader.find("standard")); } } } #endif }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。