构建三角形
首先创建一个物体
创建一个脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]//这样便会在默认情况下给物体一个网格
public class Meshtest : MonoBehaviour
{
private void OnEnable()
{
var mesh = new Mesh{
name = "Procedural Mesh" };//设置mesh的名字
mesh.vertices = new Vector3[]
{
Vector3.zero, Vector3.right, Vector3.up,
new Vector3(1.1f,0f),new Vector3(0f,1.1f),new Vector3(1.1f,1.1f)
};//设置三角形的顶点
mesh.normals = new Vector3[] {
Vector3.back, Vector3.back, Vector3.back, Vector3.back,Vector3.back,Vector3.back};//三角形三个点的法线向量
mesh.tangents = new Vector4[]
{
new Vector4(1f, 0f, 0f, -1f) ,
new Vector4(1f,0f,0f,-1f),
new Vector4(1f,0f,0f,-1f),
new Vector4(1f,0f,1f,-1f),
new Vector4(1f,0f,1f,-1f),
new Vector4(1f,0f,1f,-1f)
};
mesh.uv = new Vector2[]
{
Vector2.zero, Vector2.right, Vector2.up,
Vector2.right,Vector2.up,Vector2.one
};//设置三角形的uv
mesh.triangles = new int[] {
0, 2, 1 ,3,4,5};//设置三角形顶点顺序,当为012时三角形透明
GetComponent<MeshFilter>().mesh = mesh;//获取mesh组件
}
}
将贴图填入之后便可获得
最后获得的图形为
这就构建了两个三角形
这是纹理贴图:
这是法线贴图:
构建正方形
若要构建正方形则需要将
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]//这样便会在默认情况下给物体一个网格
public class Meshtest : MonoBehaviour
{
private void OnEnable()
{
var mesh = new Mesh{
name = "Procedural Mesh" };//设置mesh的名字
mesh.vertices = new Vector3[]
{
Vector3.zero, Vector3.right, Vector3.up,new Vector3(1.0f,1.0f)
//new Vector3(1.1f,0f),new Vector3(0f,1.1f),new Vector3(1.1f,1.1f)
};//设置三角形的顶点
mesh.normals = new Vector3[] {
Vector3.back, Vector3.back, Vector3.back, Vector3.back/*,Vector3.back,Vector3.back*/};//三角形三个点的法线向量
mesh.tangents = new Vector4[]
{
new Vector4(1f, 0f, 0f, -1f) ,
new Vector4(1f,0f,0f,-1f),
new Vector4(1f,0f,0f,-1f),
// new Vector4(1f,0f,1f,-1f),
// new Vector4(1f,0f,1f,-1f),
new Vector4(1f,0f,1f,-1f)
};
mesh.uv = new Vector2[]
{
Vector2.zero, Vector2.right, Vector2.up,
/*Vector2.right,Vector2.up,*/Vector2.one
};//设置三角形的uv
mesh.triangles = new int[] {
0, 2, 1 ,1,2,3};//设置三角形顶点顺序,当为012时三角形透明
GetComponent<MeshFilter>().mesh = mesh;//获取mesh组件
}
}
多流方法
网格的内存被分成多个区域。我们需要了解的两个区域是顶点区域和索引区域。顶点区域由一个或多个数据流组成,这些数据流是相同格式的顶点数据的连续块。Unity 每个网格最多支持四个不同的顶点数据流。
由于我们有顶点位置、法线、切线和纹理坐标,我们可以将每个坐标存储在单独的流中。我们称之为多流方法。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using Unity.Collections;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using float3 = Unity.Mathematics.float3;
[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]//创建一个新的元件类型,与之前一样,该类型最初仅创建一个空网格并将其分配
public class NewMesh : MonoBehaviour
{
private void OnEnable()
{
int vertexAttributeCount = 4;
int vertexCount = 4;
int triangleIndexCount = 6;
Mesh.MeshDataArray meshDataArray = Mesh.AllocateWritableMeshData(1);//调用静态方法写入本机网格数据
Mesh.MeshData meshData = meshDataArray[0];//为了填充网格数据,我们必须从数组中检索单个元素,并通过变量跟踪它
var vertexAttributes = new NativeArray<VertexAttributeDescriptor>(vertexAttributeCount, Allocator.Temp,NativeArrayOptions.UninitializedMemory/*这意味着数组的内容是任意的,可能是无效的,但我们覆盖了所有内容,这样就没关系了。*/);//网格的每个顶点都有四个属性:位置、法线、切线和一组纹理坐标。我们将通过分配一个带有元素的临时本机数组来描述这些内容。
vertexAttributes[0] = new VertexAttributeDescriptor(dimension: 3);
vertexAttributes[1] = new VertexAttributeDescriptor(VertexAttribute.Normal, dimension: 3, stream: 1);
vertexAttributes[2] = new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float16,4,2);
vertexAttributes[3] = new VertexAttributeDescriptor(VertexAttribute.TexCoord0,VertexAttributeFormat.Float16, 2, 3);
meshData.SetVertexBufferParams(vertexCount,vertexAttributes);//然后通过调用网格数据来分配网格的顶点流,顶点计数和属性定义作为参数。
vertexAttributes.Dispose();//最后不在需要之后处理掉
NativeArray<float3> positions = meshData.GetVertexData<float3>();
positions[0] = 0f;
positions[1] = right();
positions[2] = up();
positions[3] = float3(1f, 1f, 0f);
NativeArray<float3> normals = meshData.GetVertexData<float3>(1);
normals[0] = normals[1] = normals[2] = normals[3] = back();
half h0 = half(0f), h1 = half(1f);
NativeArray<half4> tangents = meshData.GetVertexData<half4>(2);
tangents[0] = tangents[1] = tangents[2] = tangents[3] = half4(h1, h0, h0, half(-1f));
NativeArray<half2> texCoords = meshData.GetVertexData<half2>(3);
texCoords[0] = h0;
texCoords[1] = half2(h1, h0);
texCoords[2] = half2(h0, h1);
texCoords[3] = h1;
meshData.SetIndexBufferParams(triangleIndexCount,IndexFormat.UInt16);
NativeArray<ushort> triangleIndices = meshData.GetIndexData<ushort>();
triangleIndices[0] = 0;
triangleIndices[1] = 2;
triangleIndices[2] = 1;
triangleIndices[3] = 1;
triangleIndices[4] = 2;
triangleIndices[5] = 3;
var bounds = new Bounds(new Vector3(0.5f, 0.5f), new Vector3(1f, 1f));
meshData.subMeshCount = 1;
meshData.SetSubMesh(0,new SubMeshDescriptor(0,triangleIndexCount)
{
bounds = bounds,
vertexCount = vertexCount
},MeshUpdateFlags.DontRecalculateBounds);
var mesh = new Mesh
{
bounds = bounds,
name = "Procedural Mesh"
};
Mesh.ApplyAndDisposeWritableMeshData(meshDataArray,mesh);
GetComponent<MeshFilter>().mesh = mesh;
}
}
单流方法
不需要将每个属性放在单个流中,否则最多只能支持四个顶点属性。另一个极端是将所有属性放在一个流中。在这种情况下,属性按顶点分组,因此数据是混合的。
尽管我们可以按任意顺序定义属性,但 Unity 需要每个流的固定属性顺序:位置、法线、切线、颜色、从 0 到 7 的纹理坐标集、混合权重和混合索引。
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.Rendering;
using Unity.Collections;
using static Unity.Mathematics.math;
using float3 = Unity.Mathematics.float3;
using half = Unity.Mathematics.half;
[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class OneStream : MonoBehaviour
{
[StructLayout(LayoutKind.Sequential)]
struct Vertex//创捷一个结构体
{
public float3 position, normal;
public half4 tangent;
public half2 texCoord0;
}
private void OnEnable()
{
int vertexAttributeCount = 4;
int vertexCount = 4;
int triangleIndexCount = 6;
Mesh.MeshDataArray meshDataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData meshData = meshDataArray[0];
var vertexAttributes = new NativeArray<VertexAttributeDescriptor>(vertexAttributeCount, Allocator.Temp,NativeArrayOptions.UninitializedMemory);
vertexAttributes[0] = new VertexAttributeDescriptor(dimension: 3);
vertexAttributes[1] = new VertexAttributeDescriptor(VertexAttribute.Normal, dimension: 3);
vertexAttributes[2] = new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float16,4);
vertexAttributes[3] = new VertexAttributeDescriptor(VertexAttribute.TexCoord0,VertexAttributeFormat.Float16, 2);
meshData.SetVertexBufferParams(vertexCount,vertexAttributes);
vertexAttributes.Dispose();
// NativeArray<float3> positions = meshData.GetVertexData<float3>();
// positions[0] = 0f;
// positions[1] = right();
// positions[2] = up();
// positions[3] = float3(1f, 1f, 0f);
// NativeArray<float3> normals = meshData.GetVertexData<float3>(1);
// normals[0] = normals[1] = normals[2] = normals[3] = back();
//
// half h0 = half(0f), h1 = half(1f);
// NativeArray<half4> tangents = meshData.GetVertexData<half4>(2);
// tangents[0] = tangents[1] = tangents[2] = tangents[3] = half4(h1, h0, h0, half(-1f));
// NativeArray<half2> texCoords = meshData.GetVertexData<half2>(3);
// texCoords[0] = h0;
// texCoords[1] = half2(h1, h0);
// texCoords[2] = half2(h0, h1);
// texCoords[3] = h1;
NativeArray<Vertex> vertices = meshData.GetVertexData<Vertex>();//检索单个流的本机数组
half h0 = half(0f), h1 = half(1f);
var vertex = new Vertex
{
normal = back(),
tangent = half4(h1,h0,h0,half(-1f))
};
//添加了各个顶点的位置,和纹理坐标
vertex.position = 0f;
vertex.texCoord0 = h0;
vertices[0] = vertex;
vertex.position = right();
vertex.texCoord0 = half2(h1, h0);
vertices[1] = vertex;
vertex.position = up();
vertex.texCoord0 = half2(h0, h1);
vertices[2] = vertex;
vertex.position = float3(1f, 1f, 0f);
vertex.texCoord0 = h1;
vertices[3] = vertex;
meshData.SetIndexBufferParams(triangleIndexCount,IndexFormat.UInt16);
NativeArray<ushort> triangleIndices = meshData.GetIndexData<ushort>();
triangleIndices[0] = 0;
triangleIndices[1] = 2;
triangleIndices[2] = 1;
triangleIndices[3] = 1;
triangleIndices[4] = 2;
triangleIndices[5] = 3;
var bounds = new Bounds(new Vector3(0.5f, 0.5f), new Vector3(1f, 1f));
meshData.subMeshCount = 1;
meshData.SetSubMesh(0,new SubMeshDescriptor(0,triangleIndexCount)
{
bounds = bounds,
vertexCount = vertexCount
},MeshUpdateFlags.DontRecalculateBounds);
var mesh = new Mesh
{
bounds = bounds,
name = "Procedural Mesh"
};
Mesh.ApplyAndDisposeWritableMeshData(meshDataArray,mesh);
GetComponent<MeshFilter>().mesh = mesh;//获取mesh组件
}
}