【Unity3D】绘制物体表面三角形网格
1 仅绘制三角形网格
1)创建游戏对象
创建一个空对象,重命名为 Grid,并在其下添加需要绘制网格的对象,如下:

场景显示如下:

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 的范围: 0 ~ 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 对象上。
运行效果:

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 的范围: 0 ~ 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);
}
}
}
运行效果:

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 的范围: 0 ~ 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);
}
}
}
运行效果:

声明:本文转自【Unity3D】绘制物体表面三角形网格
【Unity3D】绘制物体表面三角形网格的更多相关文章
- Matlab绘图基础——绘制三维表面
%绘制三维表面 ------------------------------------- %1.绘制线框图:mesh:每一条曲线称为mesh line %首先利用meshgrid函数产生平面区域内的 ...
- unity3D 游戏物体同时绑定单击、双击事件
前言 在unity中我们常用的获取鼠标点击的方法有 在3D场景中,一般用在Update方法中,每一帧调用 void Update(){ )){ Debug.log("鼠标左键点击" ...
- Three.js之绘制物体的边框及修改lineWidth
本博文主要记录如何使用three.js绘制物体的边框及修改其lineWidth.three.js是个技术点比较多,查询资料又比较少的框架,单单就这个修改lineWidth就是一个坑.先放一个动态的效果 ...
- Unity3D 角色(物体) 移动方法 合集
1. 简介 在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position. 2. 通过Transform组件移动物体 Transform 组件用于描述物体在 ...
- 时光煮雨 Unity3D让物体动起来③—UGUI DoTween&Unity Native2D实现
本文首发蛮牛,次发博客园.接系列 第一篇,第二篇,本文为第三篇,再次感谢“武装三藏”在前两篇无私且精彩的问题解答 写在最前,时光煮雨,为了怀念 以下引用曾今读过的一些教程文章 其实这3种动画都有它特定 ...
- unity3d游戏物体跟着鼠标方向移动
效果:当点击鼠标左键时,游戏对象会朝鼠标点击的方向移动,类似魔兽争霸一样. 思路:把鼠标的坐标转化成世界坐标(鼠标默认是屏幕坐标),然后当点击鼠标时,物体将朝着鼠标的世界坐标方向移动. 如果你看到这的 ...
- unity3d中物体的控制
一.物体的循环移动和旋转 思路:通过对时间的计算,每隔一段时间让物体旋转,实现来回移动. float TranslateSpeed = 0.02f; float TranslateSpeedTime ...
- Unity3d创建物体,寻找物体,加载物体,添加脚本
GetCreateObject: using UnityEngine; public class GetCreateObject : MonoBehaviour { GameObject emptyG ...
- Unity3d 控制物体移动、旋转、缩放
在Unity中通过利用 Input Manager(输入管理器)可以很简单的实现对一个物体进行移动.旋转.缩放操作. 演示代码: //通过虚拟轴控制物体移动.旋转.缩放 public class Mo ...
- 【转】Unity3d实现物体围绕某一点进行旋转
1,让一个物体围绕某一点旋转,有几种方法?分别是什么? 答:在这个点处放一个空物体B,则问题变为A绕着B旋转, 方法1:B不动,A挂脚本实现transform的RotateAround(vector3 ...
随机推荐
- C++ 语法结构--堆
1.堆介绍 「堆 heap」是一种满足特定条件的完全二叉树,主要可分为图 8-1 所示的两种类型. 「大顶堆 max heap」:任意节点的值 其子节点的值. 「小顶堆 min heap」:任意节点的 ...
- Python Code_02
author : 写bug的盼盼 development time : 2021/8/27 19:59 变量定义 name = '阿哈' print(name) print('标识',id(name) ...
- Git-历史版本切换-log-reset
- [转帖]比快更快的 ELK 8 安装使用指南-Elasticsearch,Kibana,Logstash
https://juejin.cn/post/7133907643386560519 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情 Elastic 8 ...
- [转帖]Postmark - 存储性能测试工具
1. 引言 Postmark是由著名的NAS提供商NetApp开发,用来测试其产品的后端存储性能. Postmark主要用于测试文件系统在邮件系统或电子商务系统中性能,这类应用的特点是:需要频繁.大量 ...
- [转帖]Linux Page cache和Buffer cache
https://www.cnblogs.com/hongdada/p/16926655.html free 命令常用参数 free 命令用来查看内存使用状况,常用参数如下: -h human-read ...
- Rsync的一个高级应用
Rsync的一个高级应用 背景 2019年刚开始接触linux时. 有一个很恶心的场景. 很多人为了简单起见, 提交数据库的修改(数据结果和预制数据) 都不是增量处理, 都是全量提交过来. 所以会造成 ...
- 混沌测试平台 Chaos Mesh
混沌测试平台 Chaos Mesh Chaos Mesh 是PingCap团队研发的一款用于测试kubernetes环境的工具.通过人为地在集群中注入故障来检测集群对故障的处理以及恢复能力.更详细信息 ...
- 可持久化非确定状态AC自动分块维护线段平衡仙人掌优化最小费用最大流预处理混合图上莫比乌斯反演莫队带花舞蹈链并查集树状数组套主席树预处理动态DP分治FFT求多项式逆元对数函数的指数函数用可持久化并查集合并最小费用循环流上插头DP
P8946 - The Lost Symbol 这种类型的 dp 的特点就是大部分转移形如 \(f(i,j)\rightarrow f(i+1,j+1)\) 之类的,并且当以上转移出现时原数组被清空, ...
- (数据科学学习手札122)Python+Dash快速web应用开发——内网穿透篇
由我开源的先进Dash组件库feffery-antd-components正处于早期测试版本阶段,欢迎前往官网http://fac.feffery.tech/了解更多 1 简介 这是我的系列教程Pyt ...