首页 > 其他分享 >【Unity3D】绘制物体表面三角形网格

【Unity3D】绘制物体表面三角形网格

时间:2023-03-21 10:02:15浏览次数:57  
标签:Unity3D meshFilter int 网格 transform mesh indices 绘制 triangles

1 仅绘制三角形网格

1)创建游戏对象

​ 创建一个空对象,重命名为 Grid,并在其下添加需要绘制网格的对象,如下:

img

​ 场景显示如下:

img

2)添加脚本组件

​ GridController.cs

using System;
using UnityEngine;

public class GridController : MonoBehaviour {

	private void Start () {
		ForAllChildren(transform, RebuildMesh);
	}

	private void RebuildMesh(Transform transform) {
		MeshFilter meshFilter = transform.GetComponent<MeshFilter>();
		if (meshFilter != null && meshFilter.mesh != null) {
			int[] indices = MakeIndices(meshFilter.mesh.triangles);
			meshFilter.mesh.SetIndices(indices, MeshTopology.Lines, 0);
		}
	}

	private int[] MakeIndices(int[] triangles) {
		int[] indices = new int[2 * triangles.Length];
		for( int i = 0; i < triangles.Length; i += 3 ) {
			for (int j = 0; j < 6; j++) {
				// 每个三角形转换为3条线段, 每个顶点使用2次, 对应的顶点序列是: 0, 1, 1, 2, 2, 0, 通式: (j + 1) % 6 / 2, j 的范围: 1 ~ 5
				indices[2 * i + j] = triangles[i + (j + 1) % 6 / 2];
			}
		}
		return indices;
	}

	private void ForAllChildren(Transform transform, Action<Transform> action) {
		action.Invoke(transform);
		for (int i = 0; i < transform.childCount; i++) {
			ForAllChildren(transform.GetChild(i), action);
		}
	}
}

点击并拖拽以移动

​ 说明: GridController 脚本组件挂在 Grid 对象上。

​ 运行效果:

img

3)给网格添加新材质

​ GridController.cs

using System;
using UnityEngine;

public class GridController : MonoBehaviour {
	public Material material;

	private void Start () {
		ForAllChildren(transform, RebuildMesh);
	}

	private void RebuildMesh(Transform transform) {
		MeshFilter meshFilter = transform.GetComponent<MeshFilter>();
		MeshRenderer meshRenderer = transform.GetComponent<MeshRenderer>();
		if (meshFilter != null && meshFilter.mesh != null && meshRenderer != null) {
			meshRenderer.material = material;
			int[] indices = MakeIndices(meshFilter.mesh.triangles);
			meshFilter.mesh.SetIndices(indices, MeshTopology.Lines, 0);
		}
	}

	private int[] MakeIndices(int[] triangles) {
		int[] indices = new int[2 * triangles.Length];
		for( int i = 0; i < triangles.Length; i += 3 ) {
			for (int j = 0; j < 6; j++) {
				// 每个三角形转换为3条线段, 每个顶点使用2次, 对应的顶点序列是: 0, 1, 1, 2, 2, 0, 通式: (j + 1) % 6 / 2, j 的范围: 1 ~ 5
				indices[2 * i + j] = triangles[i + (j + 1) % 6 / 2];
			}
		}
		return indices;
	}

	private void ForAllChildren(Transform transform, Action<Transform> action) {
		action.Invoke(transform);
		for (int i = 0; i < transform.childCount; i++) {
			ForAllChildren(transform.GetChild(i), action);
		}
	}
}

​ 运行效果:

img

2 绘制表面和三角形网格

​ 场景中所有对象同第 1 节,脚本组件如下:

​ GridController.cs

using System;
using UnityEngine;
using UnityEngine.Rendering;

public class GridController : MonoBehaviour {
	public Material material;

	private void Start () {
		ForAllChildren(transform, RebuildMesh);
	}

	private void RebuildMesh(Transform transform) {
		MeshFilter meshFilter = transform.GetComponent<MeshFilter>();
		MeshRenderer meshRenderer = transform.GetComponent<MeshRenderer>();
		if (meshFilter != null && meshFilter.mesh != null && meshRenderer != null) {
			InitMaterials(meshRenderer);
			int[] indices = MakeIndices(meshFilter.mesh.triangles);
			InitSubMesh(meshFilter.mesh, indices, indices.Length / 3);
		}
	}

	private void InitMaterials(MeshRenderer meshRenderer) {
		Material[] materials = new Material[meshRenderer.materials.Length + 1];
		meshRenderer.materials.CopyTo(materials, 0);
		materials[materials.Length - 1] = material;
		meshRenderer.materials = materials;
	}

	private void InitSubMesh(Mesh mesh, int[] indices, int divide) {
		mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt32);
        mesh.SetIndexBufferData(indices, 0, 0, indices.Length);
        mesh.subMeshCount = 2; // 设置2个子网格
		// 第一部分绘制三角形内部
        SubMeshDescriptor subMeshDescriptor1 = new SubMeshDescriptor(0, divide, MeshTopology.Triangles);
        mesh.SetSubMesh(0, subMeshDescriptor1);
		// 第二部分绘制线段
        SubMeshDescriptor subMeshDescriptor2 = new SubMeshDescriptor(divide, indices.Length - divide, MeshTopology.Lines);
        mesh.SetSubMesh(1, subMeshDescriptor2);
	}

	private int[] MakeIndices(int[] triangles) {
		int[] indices = new int[3 * triangles.Length];
		triangles.CopyTo(indices, 0);
		for( int i = 0; i < triangles.Length; i += 3 ) {
			for (int j = 0; j < 6; j++) {
				// 每个三角形转换为3条线段, 每个顶点使用2次, 对应的顶点序列是: 0, 1, 1, 2, 2, 0, 通式: (j + 1) % 6 / 2, j 的范围: 1 ~ 5
				indices[triangles.Length + 2 * i + j] = triangles[i + (j + 1) % 6 / 2];
			}
		}
		return indices;
	}

	private void ForAllChildren(Transform transform, Action<Transform> action) {
		action.Invoke(transform);
		for (int i = 0; i < transform.childCount; i++) {
			ForAllChildren(transform.GetChild(i), action);
		}
	}
}

​ 运行效果:

img

​ 声明:本文转自【Unity3D】绘制物体表面三角形网格

标签:Unity3D,meshFilter,int,网格,transform,mesh,indices,绘制,triangles
From: https://www.cnblogs.com/zhyan8/p/17237942.html

相关文章

  • 【Unity3D】绘制物体外框线条盒子
    1需求描述​点选物体、框选物体、绘制外边框中介绍了物体投影到屏幕上的二维外框绘制方法,本文将介绍物体外框线条盒子绘制方法。内框:选中物体后,绘制物体的内框(紧......
  • 【Unity3D】点选物体、框选物体、绘制外边框
    1需求描述​绘制物体外框线条盒子中介绍了绘制物体外框长方体的方法,本文将介绍物体投影到屏幕上的二维外框绘制方法。点选物体:点击物体,可以选中物体,按住Ctrl追......
  • 【Unity3D】使用GL绘制线段
    1前言​线段渲染器LineRenderer、拖尾TrailRenderer、绘制物体表面三角形网格从不同角度介绍了绘制线段的方法,本文再介绍一种新的绘制线段的方法:使用GL绘制线段。......
  • 【Unity3D】VideoPlayer组件
    1简介​AudioSource组件中介绍了音频的播放,本文将介绍基于VideoPlayer组件实现视频播放。​VideoPlayer属性面板如下:Source:视频源类型,有2种类型:VideoC......
  • 【Unity3D】固定管线着色器二
    1前言​固定管线着色器一中介绍了Shader中外部属性、光照、贴图等基础用法,本文将进一步讲解固定管线着色器,介绍正面与反面剔除、Alpha测试、深度测试、混合、渲......
  • 【Unity3D】固定管线着色器一
    1前言​着色器(Shader)是渲染管线中最重要的一环,Unity3D底层基于OpenGL实现,读者可以通过渲染管线了解Unity3D渲染流程。​OpenGL1.x为固定管线,2.x之后......
  • 【Unity3D】协同程序
    1简介​1)协程概念​协同程序(Coroutine)简称协程,是伴随主线程一起运行的程序片段,是一个能够暂停执行的函数,用于解决程序并行问题。协程是C#中的概念,由于Unity3......
  • 【Unity3D】顶点和片元着色器
    1前言​上文介绍了渲染管线、固定管线着色器和表面着色器,如下:渲染管线固定管线着色器一固定管线着色器二表面着色器​固定管线着色器通过命令方式实现光......
  • 【Unity3D】表面着色器
    1前言​固定管线着色器一、固定管线着色器二中介绍了ShaderLib的基本用法,本文将接着讲解表面着色器(SurfaceShader)的用法。固定管线着色器基于ShaderLib命令实......
  • 【Unity3D】AudioSource组件
    1简介​1)AudioSource与AudioListener简介​AudioSource(音频源)组件用于控制播放AudioClip(音频片段),能够控制2D和3D(距离越远,声音越小)声音播放,它一般挂在产......