Mesh网格编程(1)

构建三角形

首先创建一个物体
在这里插入图片描述
创建一个脚本

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组件
    }


}

猜你喜欢

转载自blog.csdn.net/tongmeng_yiran/article/details/129337254