u3d网格编程-绘制多面片长方体

2024-03-15 14:58

本文主要是介绍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网格编程-绘制多面片长方体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812346

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math