本文主要是介绍u3d网格编程-绘制多面片长方体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
写在前面:
unity3d中可以使用Mesh类,实现动态生成网格体,指定uv、法线等操作。本文将绘制一个指定长宽高的长方体,并在其内部划分指定距离的网格,多余的部分的顶底和uv也做了适当的使用。适合正在学习网格编程的同僚参考,下面是实现后的效果图:
\
本文目录按当时学习并制作的过程来划分如下:
一、用脚本实现一个简单的cube绘制
二、为cube指定法线和uv等
三、用脚本绘制一个Plane
四、绘制六个面的网格体
五、指定各个顶点的uv
六、尺寸缩减处理
一、用脚本实现一个简单的cube绘制
using UnityEngine;
using System.Collections;[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Test3D : MonoBehaviour
{// 注意:该类继承EditorWindow,只能包含静态成员static Mesh mesh; // 网格static Vector3[] Vs; // 模型顶点坐标数组static Vector2[] UVs; // UV贴图坐标static Vector3[] normals; // 法线static Vector4[] tangents; // 切线static int[] Ts; // 三角形的点序列// 添加菜单项,并放置最顶端void Start(){// 可自定义修改顶点和面SetVsAndTs();// 设置新顶点SetNewVs();// 生成网格生成需要的数据CreateOther();// 调用创建对象函数CreateObjectByMesh();}//设置顶点和三角面static void SetVsAndTs(){Vs = new Vector3[]{new Vector3(-0.5f, -0.5f, -0.5f),new Vector3(0.5f, -0.5f, -0.5f),new Vector3(0.5f, 0.5f, -0.5f),new Vector3(-0.5f,0.5f, -0.5f),new Vector3(-0.5f,0.5f, 0.5f),new Vector3(0.5f, 0.5f, 0.5f),new Vector3(0.5f, -0.5f, 0.5f),new Vector3(-0.5f, -0.5f, 0.5f)};Ts = new int[]{0,2,1,0,3,2,3,4,2,4,5,2,4,7,5,7,6,5,7,0,1,6,7,1,4,3,0,4,0,7,2,5,6,2,6,1};}//生成网格的核心代码static void SetNewVs(){//根据面的顺序,重新创建新的顶点数组,用于计算顶点法线Vector3[] newVs = new Vector3[Ts.Length];for (int i = 0; i < newVs.Length; i++){newVs[i] = Vs[Ts[i]];}Vs = newVs;}// 创建对象函数(这个功能提出来,方便以后扩展)void CreateObjectByMesh(){mesh = new Mesh(); // 创建网格mesh.vertices = Vs; // 网格的顶点mesh.triangles = Ts; // 网格的三角形mesh.uv = UVs; // 网格的UV坐标mesh.normals = normals; // 网格的法线mesh.tangents = tangents; // 网格的切线gameObject.GetComponent<MeshFilter>().mesh = mesh; // 添加网格}
}
在MeshRenderer中使用了带如下图片的材质球:
、
在没有划分uv之前,将创建出这样一个Cube:
二、为cube指定法线和uv等
//创建uv等static void CreateOther(){UVs = new Vector2[Vs.Length];normals = new Vector3[Vs.Length];tangents = new Vector4[Vs.Length];// 根据新的点,设置三角面的顶点ID并计算点法线for (int i = 0; i < Ts.Length - 2; i += 3){Vector3 normal = Vector3.Normalize(Vector3.Cross(Vs[i + 1] - Vs[i], Vs[i + 2] - Vs[i])); // 计算点的法线for (int j = 0; j < 3; j++){Ts[i + j] = i + j; // 重新设置面的顶点IDnormals[i + j] = normal; // 点的法线赋值}}// 设置每个点的切线和UVfor (int i = 0; i < Vs.Length; i++){tangents[i] = new Vector4(-1, 0, 0, -1); // 切线if (normals[i] == Vector3.back || normals[i] == Vector3.forward){UVs[i] = new Vector2((Vs[i].x + 0.5f) * 0.928f , (Vs[i].y + 0.5f) * 0.42f + 0.292f); // UV坐标}else if(normals[i] == Vector3.up){UVs[i] = new Vector2((Vs[i].x + 0.5f) * 0.928f, (Vs[i].z + 0.5f) * 0.292f + 0.708f); // UV坐标}else if (normals[i] == Vector3.down){UVs[i] = new Vector2((Vs[i].x + 0.5f) * 0.928f, (Vs[i].z + 0.5f) * 0.292f); // UV坐标}else if (normals[i] == Vector3.left || normals[i] == Vector3.right){UVs[i] = new Vector2((Vs[i].z + 0.5f) * 0.072f + 0.928f, (Vs[i].y + 0.5f) * 0.42f + 0.292f); // UV坐标}}}
在指定完每个顶点的uv之后,cube将变成如下形态:
三、用脚本绘制一个Plane
为实现文本最初的目标,应该想办法在一个面内划分出多个面:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;namespace Lin
{struct MeshStruct{public int[] Triangles;public Vector3[] Vertices;public Vector3[] Normals;public Vector4[] Tangents;public Vector2[] UV;public Color32[] Colors32;}public struct Vector2Int{public int x;public int y;public Vector2Int(int x, int y){this.x = x;this.y = y;}public Vector2Int(Vector2 value){x = (int)value.x;y = (int)value.y;}public static implicit operator Vector2Int(Vector2 value){return new Vector2Int((int)value.x, (int)value.y);}public override string ToString(){return "{" + x + ", " + y + "}";}}public class CreateMesh : MonoBehaviour{public int _quality = 20;// 面片最大大小 public Vector2 _size = new Vector2(1000, 1000);// 表格个数 private Vector2Int _grid = new Vector2Int();// 单元格大小 private float _nodeSize = 0f;private Mesh _mesh;// 网格结构体 private MeshStruct _meshStruct;private MeshFilter _meshFilter;void Start(){_mesh = new Mesh();_mesh.name = "DynamicWaterMesh";_meshFilter = gameObject.GetComponent<MeshFilter>();_meshFilter.mesh = _mesh;}public void Update(){_quality = Mathf.Clamp(_quality, 4, 256);// 根据质量计算单元格大小 _nodeSize = Mathf.Max(_size.x, _size.y) / _quality;// 根据【单元格大小】计算【格子个数】 _grid.x = Mathf.RoundToInt(_size.x / _nodeSize) + 1;_grid.y = Mathf.RoundToInt(_size.y / _nodeSize) + 1;_mesh.MarkDynamic();AllocateMeshArrays();CreateMeshGrid();AssignMesh();_meshFilter.mesh = _mesh;}private void AllocateMeshArrays(){int numVertices = _grid.x * _grid.y;_meshStruct.Vertices = new Vector3[numVertices];_meshStruct.Normals = new Vector3[numVertices];_meshStruct.Tangents = new Vector4[numVertices];_meshStruct.Colors32 = new Color32[numVertices];_meshStruct.UV = new Vector2[numVertices];_meshStruct.Triangles = new int[((_grid.x - 1) * (_grid.y - 1)) * 2 * 3];}private void CreateMeshGrid(){float uvStepXInit = 1f / (_size.x / _nodeSize);float uvStepYInit = 1f / (_size.y / _nodeSize);Color32 colorOne = new Color32(255, 255, 255, 255);Vector3 up = Vector3.up;bool setTangents = true;Vector4 tangent = new Vector4(1f, 0f, 0f, 1f);int k = 0;for (int j = 0; j < _grid.y; j++){for (int i = 0; i < _grid.x; i++){int index = j * _grid.x + i;// Set vertices _meshStruct.Vertices[index].x = i * _nodeSize;_meshStruct.Vertices[index].y = 0f;_meshStruct.Vertices[index].z = j * _nodeSize;// Set triangles if (j < _grid.y - 1 && i < _grid.x - 1){_meshStruct.Triangles[k + 0] = (j * _grid.x) + i;_meshStruct.Triangles[k + 1] = ((j + 1) * _grid.x) + i;_meshStruct.Triangles[k + 2] = (j * _grid.x) + i + 1;_meshStruct.Triangles[k + 3] = ((j + 1) * _grid.x) + i;_meshStruct.Triangles[k + 4] = ((j + 1) * _grid.x) + i + 1;_meshStruct.Triangles[k + 5] = (j * _grid.x) + i + 1;k += 6;}// Set UV float uvStepX = uvStepXInit;float uvStepY = uvStepYInit;_meshStruct.UV[index].x = i * uvStepX;_meshStruct.UV[index].y = j * uvStepY;// Set colors _meshStruct.Colors32[index] = colorOne;// Set normals _meshStruct.Normals[index] = up;if (setTangents){// set tangents _meshStruct.Tangents[index] = tangent;}// fix stretching float delta;if (_meshStruct.Vertices[index].x > _size.x){delta = (_size.x - _meshStruct.Vertices[index].x) / _nodeSize;_meshStruct.UV[index].x -= uvStepX * delta;_meshStruct.Vertices[index].x = _size.x;}if (_meshStruct.Vertices[index].z > _size.y){delta = (_size.y - _meshStruct.Vertices[index].z) / _nodeSize;_meshStruct.UV[index].y -= uvStepY * delta;_meshStruct.Vertices[index].z = _size.y;}if (_size.x - _meshStruct.Vertices[index].x < _nodeSize){delta = (_size.x - _meshStruct.Vertices[index].x) / _nodeSize;_meshStruct.UV[index].x += uvStepX * delta;_meshStruct.Vertices[index].x = _size.x;}if (_size.y - _meshStruct.Vertices[index].z < _nodeSize){delta = (_size.y - _meshStruct.Vertices[index].z) / _nodeSize;_meshStruct.UV[index].y += uvStepY * delta;_meshStruct.Vertices[index].z = _size.y;}}}}private void AssignMesh(){_mesh.vertices = _meshStruct.Vertices;_mesh.normals = _meshStruct.Normals;_mesh.tangents = _meshStruct.Tangents;_mesh.uv = _meshStruct.UV;_mesh.colors32 = _meshStruct.Colors32;_mesh.triangles = _meshStruct.Triangles;_mesh.RecalculateBounds();// Freeing the memory _meshStruct.Tangents = null;_meshStruct.Triangles = null;_meshStruct.UV = null;_meshStruct.Colors32 = null;}}
}
实现效果如下:
四、绘制六个面的网格体
在绘制平面网格的基础上,要实现六个面网格体的绘制相对也比较容易:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;namespace lin2
{public struct BeamMesh{public Vector3[] vertices; // 网格的顶点public int[] triangles; // 网格的三角形public Vector2[] uvs; // 网格的UV坐标public Vector3[] normals; // 网格的法线public Vector4[] tangents; // 网格的切线public Color32[] Colors32;public BeamMesh(Vector3[] vertices, int[] triangles, Vector2[] uvs, Vector3[] normals, Vector4[] tangents, Color32[] Colors32){this.vertices = vertices;this.triangles = triangles;this.uvs = uvs;this.normals = normals;this.tangents = tangents;this.Colors32 = Colors32;}}public struct Vector3Int{public int x;public int y;public int z;public Vector3Int(int x, int y, int z){this.x = x;this.y = y;this.z = z;}public Vector3Int(Vector3 value){x = (int)value.x;y = (int)value.y;z = (int)value.z;}public static implicit operator Vector3Int(Vector3 value){return new Vector3Int((int)value.x, (int)value.y, (int)value.z);}public override string ToString(){return "{" + x + ", " + y + ", " + z + "}";}}public class Create3DMesh : MonoBehaviour{//public int _quality = 20;// 面片最大大小 public Vector3 _size = new Vector3(1000, 1000, 1000);// 单元格大小 public float _nodeSize = 0f;// 表格个数 private Vector3Int _grid = new Vector3Int();private Vector3 _stapInit = new Vector3();private Mesh _mesh;// 网格结构体 private BeamMesh _meshStruct;private MeshFilter _meshFilter;private int vIndex, tIndex;void Start(){_mesh = new Mesh();_mesh.name = "DynamicWaterMesh";_meshFilter = gameObject.GetComponent<MeshFilter>();_meshFilter.mesh = _mesh;// 根据【单元格大小】计算【格子个数】 _grid.x = Mathf.RoundToInt(_size.x / _nodeSize) + 1;_grid.y = Mathf.RoundToInt(_size.y / _nodeSize) + 1;_grid.z = Mathf.RoundToInt(_size.z / _nodeSize) + 1;//单元格子所占比例_stapInit.x = _nodeSize / _size.x;_stapInit.y = _nodeSize / _size.y;_stapInit.z = _nodeSize / _size.z;_mesh.MarkDynamic();AllocateMeshArrays();CreateMeshGrid();AssignMesh();_meshFilter.mesh = _mesh;}private void AllocateMeshArrays(){int numVertices = 2 * (_grid.x * _grid.z + //上下_grid.y * _grid.z + //左右_grid.x * _grid.y); // 前后int NumTriangle = 2 * 2 * 3 * ((_grid.x - 1) * (_grid.z - 1) + //上下(_grid.y - 1) * (_grid.z - 1) + //左右(_grid.x - 1) * (_grid.y - 1)); // 前后_meshStruct.vertices = new Vector3[numVertices];_meshStruct.normals = new Vector3[numVertices];_meshStruct.tangents = new Vector4[numVertices];_meshStruct.Colors32 = new Color32[numVertices];_meshStruct.uvs = new Vector2[numVertices];_meshStruct.triangles = new int[NumTriangle];}private void CreateMeshGrid(){CreateMeshPlane(_grid.x,_grid.z,//上(i, j)=> { return i * _nodeSize - _size.x * 0.5f; },(i, j) => { return _size.y * 0.5f; },(i, j) => { return j * _nodeSize - _size.z * 0.5f; },_stapInit.x,_stapInit.z,new Rect(0,0.71f,0.928f,0.29f),Vector3.up);CreateMeshPlane(_grid.x, _grid.z,//下(i, j) => { return i * _nodeSize - _size.x * 0.5f; },(i, j) => { return -_size.y * 0.5f; },(i, j) => { return -j * _nodeSize + _size.z * 0.5f; },_stapInit.x, _stapInit.z, new Rect(0,0,0.928f,0.29f), Vector3.down);CreateMeshPlane(_grid.z, _grid.y,//左(i, j) => { return -_size.x * 0.5f; },(i, j) => { return j * _nodeSize - _size.y * 0.5f; },(i, j) => { return -i * _nodeSize + _size.z * 0.5f; },_stapInit.z, _stapInit.y, new Rect(0.928f,0.29f,0.072f,0.42f), Vector3.left);CreateMeshPlane(_grid.z, _grid.y,//右(i, j) => { return _size.x * 0.5f; },(i, j) => { return j * _nodeSize - _size.y * 0.5f; },(i, j) => { return i * _nodeSize - _size.z * 0.5f; },_stapInit.z, _stapInit.y, new Rect(0.928f, 0.29f, 0.072f, 0.42f), Vector3.right);CreateMeshPlane(_grid.x, _grid.y,//前(i, j) => { return i * _nodeSize - _size.x * 0.5f; },(i, j) => { return j * _nodeSize - _size.y * 0.5f; },(i, j) => { return -_size.z * 0.5f; },_stapInit.x, _stapInit.y, new Rect(0f,0.29f, 0.928f,0.42f), Vector3.back);CreateMeshPlane(_grid.x, _grid.y,//后(i, j) => { return -i * _nodeSize + _size.x * 0.5f; },(i, j) => { return j * _nodeSize - _size.y * 0.5f; },(i, j) => { return _size.z * 0.5f; },_stapInit.x, _stapInit.y, new Rect(0f, 0.29f, 0.928f, 0.42f), Vector3.forward);}/// <summary>/// 创建出一个面的mesh数据/// </summary>/// <param name="axisX"></param>/// <param name="axisY"></param>/// <param name="vx"></param>/// <param name="vy"></param>/// <param name="vz"></param>/// <param name="uvstapX"></param>/// <param name="uvstapY"></param>/// <param name="normal"></param>private void CreateMeshPlane(int axisX, int axisY, System.Func<int, int, float> vx, System.Func<int, int, float> vy, System.Func<int, int, float> vz, float uvstapX, float uvstapY,Rect uvRect, Vector3 normal){int start = vIndex;for (int j = 0; j < axisY; j++){for (int i = 0; i < axisX; i++){// Set vertices _meshStruct.vertices[vIndex].x = vx(i, j);_meshStruct.vertices[vIndex].y = vy(i, j);_meshStruct.vertices[vIndex].z = vz(i, j);// Set triangles if (j < axisY - 1 && i < axisX - 1){_meshStruct.triangles[tIndex + 0] = (j * axisX) + i + start;_meshStruct.triangles[tIndex + 1] = ((j + 1) * axisX) + i + start;_meshStruct.triangles[tIndex + 2] = (j * axisX) + i + 1 + start;_meshStruct.triangles[tIndex + 3] = ((j + 1) * axisX) + i + start;_meshStruct.triangles[tIndex + 4] = ((j + 1) * axisX) + i + 1 + start;_meshStruct.triangles[tIndex + 5] = (j * axisX) + i + 1 + start;tIndex += 6;}float uvx = uvRect.x + i * uvstapX * uvRect.width;float uvy = uvRect.y + j * uvstapY * uvRect.height;SetOther(uvx, uvy, normal);//ClampExtrVertials();vIndex++;}}}private void AssignMesh(){_mesh.vertices = _meshStruct.vertices;_mesh.normals = _meshStruct.normals;_mesh.tangents = _meshStruct.tangents;_mesh.uv = _meshStruct.uvs;_mesh.colors32 = _meshStruct.Colors32;_mesh.triangles = _meshStruct.triangles;_mesh.RecalculateBounds();// Freeing the memory _meshStruct.tangents = null;_meshStruct.triangles = null;_meshStruct.uvs = null;_meshStruct.Colors32 = null;}}
}
以上利用每个点相对于总长度的比例来实现网格坐标的确定,uv的设置如下:
五、指定各个顶点的uv
private void SetOther(float uvx, float uvy, Vector3 normal){Color32 colorOne = new Color32(255, 255, 255, 255);bool setTangents = true;Vector4 tangent = new Vector4(1f, 0f, 0f, 1f);// Set UV _meshStruct.uvs[vIndex].x = uvx;_meshStruct.uvs[vIndex].y = uvy;// Set colors _meshStruct.Colors32[vIndex] = colorOne;// Set normals _meshStruct.normals[vIndex] = normal;if (setTangents){// set tangents _meshStruct.tangents[vIndex] = tangent;}}
以上脚本可以实现三个边的公约数定义网格大小,但如果设定的格式大小不是公约数,将会产生如下的效果:
六、尺寸缩减处理
由于在用户可能会输入不是公约数的网格大小,因此,本人的解决办法是将格字数强制增加一列,同时在将各个顶点限制在长宽高之内,并利用最后的顶点坐标来设定uv.
将网格制作制作成一个工具类,如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Collections.Generic;
public struct Vector3Int
{public int x;public int y;public int z;public Vector3Int(int x, int y, int z){this.x = x;this.y = y;this.z = z;}public Vector3Int(Vector3 value){x = (int)value.x;y = (int)value.y;z = (int)value.z;}public static implicit operator Vector3Int(Vector3 value){return new Vector3Int((int)value.x, (int)value.y, (int)value.z);}public override string ToString(){return "{" + x + ", " + y + ", " + z + "}";}
}public static class MeshUtility
{static int vIndex, tIndex;/// <summary>/// 按要求创建网格体信息/// </summary>/// <param name="binfo"></param>/// <param name="size"></param>/// <returns></returns>public static MeshStruct CreateBeamMesh(BeamInfo binfo, bool dir = false){//不进行分割if (!dir){return GenerateSimpleBox(binfo);}else{return GenerateDirBox(binfo);}}/// <summary>/// 按要求将网格,得到新的网格/// </summary>/// <param name="meshData"></param>/// <param name=""></param>/// <returns></returns>public static void CurveMeshStruct(HandleData handle, MeshStruct meshDataTemp,ref MeshStruct meshData){for (int i = 0; i < meshData.vertices.Length; i++){Vector3 item = meshData.vertices[i];//区域内部if (item.x > handle.LeftCenterPoint.x && item.x < handle.RightCenterPoint.x){Vector3 newCenterPos = BezierUtility.CalculateBezierPoint((item.x - handle.LeftCenterPoint.x) / (handle.RightCenterPoint.x - handle.LeftCenterPoint.x), handle.LeftCenterPoint, handle.HandPoint1, handle.HandPoint2, handle.RightCenterPoint);meshData.vertices[i].y = meshDataTemp.vertices[i].y + newCenterPos.y;}}}/// <summary>/// 设置分割后的网格体/// </summary>/// <param name="binfo"></param>static MeshStruct GenerateDirBox(BeamInfo binfo){Vector3Int _grid = new Vector3Int();// 根据【单元格大小】计算【格子个数】 _grid.x = Mathf.CeilToInt((float)binfo.length / binfo.gridSize) + 1;_grid.y = Mathf.CeilToInt((float)binfo.height / binfo.gridSize) + 1;_grid.z = Mathf.CeilToInt((float)binfo.wigth / binfo.gridSize) + 1;MeshStruct _meshStruct = AllocateMeshArrays(_grid);CreateMeshGrid(_grid, binfo, ref _meshStruct);return _meshStruct;}static MeshStruct AllocateMeshArrays(Vector3Int _grid){int numVertices = 2 * (_grid.x * _grid.z + //上下_grid.y * _grid.z + //左右_grid.x * _grid.y); // 前后int NumTriangle = 2 * 2 * 3 * ((_grid.x - 1) * (_grid.z - 1) + //上下(_grid.y - 1) * (_grid.z - 1) + //左右(_grid.x - 1) * (_grid.y - 1)); // 前后MeshStruct _meshStruct = new MeshStruct();_meshStruct.vertices = new Vector3[numVertices];_meshStruct.normals = new Vector3[numVertices];_meshStruct.tangents = new Vector4[numVertices];_meshStruct.Colors32 = new Color32[numVertices];_meshStruct.uvs = new Vector2[numVertices];_meshStruct.triangles = new int[NumTriangle];return _meshStruct;}static void CreateMeshGrid(Vector3Int _grid, BeamInfo binfo, ref MeshStruct _meshStruct){vIndex = tIndex = 0;float xMin = -binfo.length * 0.5f;float xMax = binfo.length * 0.5f;float yMin = -binfo.height * 0.5f;float yMax = binfo.height * 0.5f;float zMin = -binfo.wigth * 0.5f;float zMax = binfo.wigth * 0.5f;CreateMeshPlane(_grid.x, _grid.z,//上(i, j) => { return Mathf.Clamp(i * binfo.gridSize + xMin, xMin, xMax); },(i, j) => { return yMax; },(i, j) => { return Mathf.Clamp(-j * binfo.gridSize + zMax, zMin, zMax); },/*new Rect(0, 0.7083f, 0.9278f, 0.2917f)*/(x, y, z) => { return 0 + ((x + xMax) / binfo.length) * 0.9278f; },(x, y, z) => { return 0.7083f + ((z + zMax) / binfo.wigth) * 0.2917f; },Vector3.up, ref _meshStruct, true);CreateMeshPlane(_grid.x, _grid.z,//下(i, j) => { return Mathf.Clamp(i * binfo.gridSize + xMin, xMin, xMax); },(i, j) => { return yMin; },(i, j) => { return Mathf.Clamp(-j * binfo.gridSize + zMax, zMin, zMax); },//new Rect(0, 0, 0.9278f, 0.2917f),(x, y, z) => { return 0 + ((x + xMax) / binfo.length) * 0.9278f; },(x, y, z) => { return 0 + ((z + zMax) / binfo.wigth) * 0.2917f; },Vector3.down, ref _meshStruct);CreateMeshPlane(_grid.z, _grid.y,//左(i, j) => { return xMin; },(i, j) => { return Mathf.Clamp(j * binfo.gridSize + yMin, yMin, yMax); },(i, j) => { return Mathf.Clamp(-i * binfo.gridSize + zMax, zMin, zMax); },//new Rect(0.9278f, 0.2917f, 0.0722f, 0.4167f), (x, y, z) => { return 0.9278f + ((z + zMax) / binfo.wigth) * 0.0722f; },(x, y, z) => { return 0.2917f + ((y + yMax) / binfo.height) * 0.4167f; },Vector3.left, ref _meshStruct);CreateMeshPlane(_grid.z, _grid.y,//右(i, j) => { return xMax; },(i, j) => { return Mathf.Clamp(j * binfo.gridSize + yMin, yMin, yMax); },(i, j) => { return Mathf.Clamp(-i * binfo.gridSize + zMax, zMin, zMax); },//new Rect(0.9278f, 0.2917f, 0.0722f, 0.4167f),(x, y, z) => { return 0.9278f + ((z + zMax) / binfo.wigth) * 0.0722f; },(x, y, z) => { return 0.2917f + ((y + yMax) / binfo.height) * 0.4167f; },Vector3.right, ref _meshStruct, true);CreateMeshPlane(_grid.x, _grid.y,//前(i, j) => { return Mathf.Clamp(i * binfo.gridSize + xMin, xMin, xMax); },(i, j) => { return Mathf.Clamp(j * binfo.gridSize + yMin, yMin, yMax); },(i, j) => { return zMin; },//new Rect(0f, 0.2917f, 0.9278f, 0.4167f),(x, y, z) => { return 0 + ((x + xMax) / binfo.length) * 0.9278f; },(x, y, z) => { return 0.2917f + ((y + yMax) / binfo.height) * 0.4167f; },Vector3.back, ref _meshStruct);CreateMeshPlane(_grid.x, _grid.y,//后(i, j) => { return Mathf.Clamp(i * binfo.gridSize + xMin, xMin, xMax); },(i, j) => { return Mathf.Clamp(j * binfo.gridSize + yMin, yMin, yMax); },(i, j) => { return zMax; },//new Rect(0f, 0.2917f, 0.9278f, 0.4167f),(x, y, z) => { return 0 + ((x + xMax) / binfo.length) * 0.9278f; },(x, y, z) => { return 0.2917f + ((y + yMax) / binfo.height) * 0.4167f; },Vector3.forward, ref _meshStruct, true);}/// <summary>/// 创建出一个面的mesh数据/// </summary>/// <param name="axisX"></param>/// <param name="axisY"></param>/// <param name="vx"></param>/// <param name="vy"></param>/// <param name="vz"></param>/// <param name="uvstapX"></param>/// <param name="uvstapY"></param>/// <param name="normal"></param>static void CreateMeshPlane(int axisX, int axisY,System.Func<int, int, float> vx,System.Func<int, int, float> vy,System.Func<int, int, float> vz,System.Func<float, float, float, float> vuvx,System.Func<float, float, float, float> vuvy,Vector3 normal, ref MeshStruct _meshStruct, bool revers = false){int start = vIndex;for (int j = 0; j < axisY; j++){for (int i = 0; i < axisX; i++){// Set vertices _meshStruct.vertices[vIndex].x = vx(i, j);_meshStruct.vertices[vIndex].y = vy(i, j);_meshStruct.vertices[vIndex].z = vz(i, j);// Set triangles if (j < axisY - 1 && i < axisX - 1){_meshStruct.triangles[tIndex + 0] = revers ? (j * axisX) + i + 1 + start : (j * axisX) + i + start;_meshStruct.triangles[tIndex + 1] = ((j + 1) * axisX) + i + start;_meshStruct.triangles[tIndex + 2] = revers ? (j * axisX) + i + start : (j * axisX) + i + 1 + start;_meshStruct.triangles[tIndex + 3] = revers ? (j * axisX) + i + 1 + start : ((j + 1) * axisX) + i + start;_meshStruct.triangles[tIndex + 4] = ((j + 1) * axisX) + i + 1 + start;_meshStruct.triangles[tIndex + 5] = revers ? ((j + 1) * axisX) + i + start : (j * axisX) + i + 1 + start;tIndex += 6;}float uvx = vuvx(_meshStruct.vertices[vIndex].x, _meshStruct.vertices[vIndex].y, _meshStruct.vertices[vIndex].z);//uvRect.x + i * uvstapX * uvRect.width;float uvy = vuvy(_meshStruct.vertices[vIndex].x, _meshStruct.vertices[vIndex].y, _meshStruct.vertices[vIndex].z);//uvRect.y + j * uvstapY * uvRect.height;SetOther(uvx, uvy, normal, ref _meshStruct);vIndex++;}}}static void SetOther(float uvx, float uvy, Vector3 normal, ref MeshStruct _meshStruct){Color32 colorOne = new Color32(255, 255, 255, 255);bool setTangents = true;Vector4 tangent = new Vector4(1f, 0f, 0f, 1f);// Set UV _meshStruct.uvs[vIndex].x = uvx;_meshStruct.uvs[vIndex].y = uvy;// Set colors _meshStruct.Colors32[vIndex] = colorOne;// Set normals _meshStruct.normals[vIndex] = normal;if (setTangents){// set tangents _meshStruct.tangents[vIndex] = tangent;}}/// <summary>/// 默认网格体绘制/// </summary>/// <param name="binfo"></param>static MeshStruct GenerateSimpleBox(BeamInfo binfo){Color32 colorOne = new Color32(255, 255, 255, 255);Vector3[] Vs = new Vector3[]{new Vector3(-0.5f * binfo.length, -0.5f * binfo.height, -0.5f * binfo.wigth),new Vector3(0.5f * binfo.length, -0.5f* binfo.height, -0.5f* binfo.wigth),new Vector3(0.5f * binfo.length, 0.5f* binfo.height, -0.5f* binfo.wigth),new Vector3(-0.5f * binfo.length, 0.5f* binfo.height, -0.5f * binfo.wigth),new Vector3(-0.5f * binfo.length, 0.5f* binfo.height, 0.5f* binfo.wigth),new Vector3(0.5f * binfo.length, 0.5f* binfo.height, 0.5f* binfo.wigth),new Vector3(0.5f * binfo.length, -0.5f* binfo.height, 0.5f * binfo.wigth),new Vector3(-0.5f * binfo.length, -0.5f * binfo.height, 0.5f* binfo.wigth)};int[] Ts = new int[]{0,2,1,0,3,2,3,4,2,4,5,2,4,7,5,7,6,5,7,0,1,6,7,1,4,3,0,4,0,7,2,5,6,2,6,1};//根据面的顺序,重新创建新的顶点数组,用于计算顶点法线Vector3[] newVs = new Vector3[Ts.Length];for (int i = 0; i < newVs.Length; i++){newVs[i] = Vs[Ts[i]];}Vs = newVs;Vector2[] UVs = new Vector2[Vs.Length];Vector3[] normals = new Vector3[Vs.Length];Vector4[] tangents = new Vector4[Vs.Length];Color32[] colors = new Color32[Vs.Length];// 根据新的点,设置三角面的顶点ID并计算点法线for (int i = 0; i < Ts.Length - 2; i += 3){Vector3 normal = Vector3.Normalize(Vector3.Cross(Vs[i + 1] - Vs[i], Vs[i + 2] - Vs[i])); // 计算点的法线for (int j = 0; j < 3; j++){Ts[i + j] = i + j; // 重新设置面的顶点IDnormals[i + j] = normal; // 点的法线赋值colors[i + j] = colorOne;}}// 设置每个点的切线和UVfor (int i = 0; i < Vs.Length; i++){tangents[i] = new Vector4(-1, 0, 0, -1); // 切线if (normals[i] == Vector3.back || normals[i] == Vector3.forward){UVs[i] = new Vector2((Vs[i].x + 0.5f * binfo.length) * 0.928f / binfo.length, (Vs[i].y + 0.5f * binfo.height) * 0.42f / binfo.height + 0.292f); // UV坐标}else if (normals[i] == Vector3.up){UVs[i] = new Vector2((Vs[i].x + 0.5f * binfo.length) * 0.928f / binfo.length, (Vs[i].z + 0.5f * binfo.wigth) * 0.292f / binfo.wigth + 0.708f); // UV坐标}else if (normals[i] == Vector3.down){UVs[i] = new Vector2((Vs[i].x + 0.5f * binfo.length) * 0.928f / binfo.length, (Vs[i].z + 0.5f * binfo.wigth) / binfo.wigth * 0.292f); // UV坐标}else if (normals[i] == Vector3.left || normals[i] == Vector3.right){UVs[i] = new Vector2((Vs[i].z + 0.5f * binfo.wigth) * 0.072f / binfo.wigth + 0.928f, (Vs[i].y + 0.5f * binfo.height) * 0.42f / binfo.height + 0.292f); // UV坐标}}MeshStruct bMesh = new MeshStruct(Vs, Ts, UVs, normals, tangents, colors);return bMesh;}}
最后说明的是,这个脚本需要使用其他脚本来调用才能生成网格。
这篇关于u3d网格编程-绘制多面片长方体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!