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

相关文章

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87