Unity3D 动态创建Mesh_unity 动态创建mesh-程序员宅基地

技术标签: Unity3D  unity3d  mesh  

1.Mesh、MeshFilter、MeshRenderer关系整理

在Unity3D中创建一个Cube,在Inspector可以看到其中含有MeshFilter、MeshRenderer组件。

MeshFilter含有一个Public成员 Mesh。

在Mesh中存储着三维模型的数据:vertices(顶点数据数组Vector3[])、triangles(三角形顶点索引数组,int[])、normals(法线向量数组,Vector3[])、uv(纹理坐标数组,Vector2[])。

2.使用Mesh创建一个Cube

创建一个脚本dyn3d.cs,成为Main Camera的组件,点击运行即可看到动态生成的Cube

复制代码
 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class dyn3d : MonoBehaviour {
 5 
 6     // Use this for initialization
 7     void Start () {
 8     
 9         CreateCube();
10     }
11     
12     // Update is called once per frame
13     void Update () {
14 
15     }
16 
17     void CreateCube()
18     {
19 
20         GameObject obj=new GameObject("cube");
21         MeshFilter mf=obj.AddComponent<MeshFilter>();
22         MeshRenderer mr=obj.AddComponent<MeshRenderer>();
23         
24         
25         Vector3[] vertices=new Vector3[24];
26         int[] triangles=new int[36];
27 
28         //forward
29         vertices[0].Set(0.5f,-0.5f,0.5f);
30         vertices[1].Set(-0.5f,-0.5f,0.5f);
31         vertices[2].Set(0.5f,0.5f,0.5f);
32         vertices[3].Set(-0.5f,0.5f,0.5f);
33         //back
34         vertices[4].Set(vertices[2].x,vertices[2].y,-0.5f);
35         vertices[5].Set(vertices[3].x,vertices[3].y,-0.5f);
36         vertices[6].Set(vertices[0].x,vertices[0].y,-0.5f);
37         vertices[7].Set(vertices[1].x,vertices[1].y,-0.5f);
38         //up
39         vertices[8]=vertices[2];
40         vertices[9]=vertices[3];
41         vertices[10]=vertices[4];
42         vertices[11]=vertices[5];
43         //down
44         vertices[12].Set(vertices[10].x,-0.5f,vertices[10].z);
45         vertices[13].Set(vertices[11].x,-0.5f,vertices[11].z);
46         vertices[14].Set(vertices[8].x,-0.5f,vertices[8].z);
47         vertices[15].Set(vertices[9].x,-0.5f,vertices[9].z);
48         //right
49         vertices[16]=vertices[6];
50         vertices[17]=vertices[0];
51         vertices[18]=vertices[4];
52         vertices[19]=vertices[2];
53         //left
54         vertices[20].Set(-0.5f,vertices[18].y,vertices[18].z);
55         vertices[21].Set(-0.5f,vertices[19].y,vertices[19].z);
56         vertices[22].Set(-0.5f,vertices[16].y,vertices[16].z);
57         vertices[23].Set(-0.5f,vertices[17].y,vertices[17].z);
58         
59         int currentCount=0;
60         for(int i=0;i<24;i=i+4)
61         {
62             triangles[currentCount++]=i;
63             triangles[currentCount++]=i+3;
64             triangles[currentCount++]=i+1;
65             
66             triangles[currentCount++]=i;
67             triangles[currentCount++]=i+2;
68             triangles[currentCount++]=i+3;
69             
70         }
71 
72         mf.mesh.vertices=vertices;
73         mf.mesh.triangles=triangles;
74         
75     }
76 }
复制代码

在这里定义vertices数组存储顶点坐标信息,定义triangles数组存储三角形顶点索引。但是这个Mesh不包含normals和uv信息,所以显示出来的正方体是无纹理贴图,并且不能反应环境光照的。

 3.冗余的顶点坐标

正方体6个面,每个面由2个三角形组成,所以共需要36个三角形顶点索引。但是正方体只有8个顶点,为什么需要24个顶点坐标数据呢?

答案是:Unity3D的Mesh.triangles是三角形索引数组,不仅依靠这个索引值索引三角形顶点坐标,而且索引纹理坐标,索引法线向量。即正方体的每个顶点都参与了3个平面,而这3个平面的法线向量是不同的,该顶点在渲染这3个平面的时候需要索引到不同的法线向量。而由于顶点坐标和法线向量是由同一个索引值triangles[Index]取得的,例如,根据triangles[0],triangles[14],triangles[17]在vertices中索引到的顶点都为(0.5,-0.5,0.5),但是在normals中索引到的法向量值各不相同。这就决定了在正方体中一个顶点,需要有3份存储。(如果你需要创建其它模型,需要根据实际情况决定顶点坐标的冗余度。实质上顶点坐标的冗余正是方便了法线坐标、纹理坐标的存取。)

4.三角形的渲染

准则:三角形有两面,正面可见,背面不可见。三角形的渲染顺序与三角形的正面法线呈左手螺旋定则

这就决定了,如果我们需要渲染如下一个正方形面,那么就需要保证组成这个正方形的两个小三角形的正面法线都是指向屏幕外的。

我在程序中的顶点顺序为,三角形1: 0->3->1,三角形2: 0->2->3 。

复制代码
 1 int currentCount=0;
 2 for(int i=0;i<24;i=i+4)
 3 {
 4         //三角形1
 5     triangles[currentCount++]=i;
 6     triangles[currentCount++]=i+3;
 7     triangles[currentCount++]=i+1;
 8     //三角形2        
 9     triangles[currentCount++]=i;
10     triangles[currentCount++]=i+2;
11     triangles[currentCount++]=i+3;
12 }
复制代码

这段代码保证了正方体的6个面,12个三角形的都正确被渲染(正面法线朝外)。



转载:http://www.cnblogs.com/kyokuhuang/p/4191169.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ycl295644/article/details/51276199

智能推荐

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例

在多媒体通信领域,MRCP(Media Resource Control Protocol)协议被广泛用于控制语音识别和合成等媒体资源。UniMRCP是一个开源的MRCP实现,提供了客户端和服务端的库。UmcFramework是一个基于UniMRCP客户端库的示例应用程序框架,它帮助开发者快速集成和测试MRCP客户端功能。本文将详细介绍如何使用UmcFramework和unimrcpclient.xml配置文件连接到多个SIP设置,以及如何用C代码进行示例说明。

java.net.ProtocolException: Server redirected too many times (20)-程序员宅基地

文章浏览阅读3k次。报错:java.net.ProtocolException: Server redirected too many times (20)1.没有检查到cookie,一直循环重定向。解决:CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));URL url = new URL(url); ..._java.net.protocolexception: server redirected too many times (20)

springboot启动报错 Failed to scan *****/derbyLocale_ja_JP.jar from classloader hierarchy_failed to scan from classloader hierarchy-程序员宅基地

文章浏览阅读4.1k次。问题这是部分报错信息2019-07-11 14:03:34.283 WARN [restartedMain][DirectJDKLog.java:175] - Failed to scan [file:/D:/repo/org/apache/derby/derby/10.14.2.0/derbyLocale_ja_JP.jar] from classloader hierarchyjava...._failed to scan from classloader hierarchy

MATLAB-ones函数_matlab中ones函数-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏7次。在MATLAB中,ones函数用于创建一个指定大小的由1组成的矩阵或数组。_matlab中ones函数

解决PS等软件出现应用程序无法正常启动(0xc000007b)_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。-程序员宅基地

文章浏览阅读3.9w次,点赞2次,收藏9次。  在使用电脑办公过程中,安装应用程序时难免遇到无法安装或者无法正常启动的问题,这对我们使用电脑带来了诸多不便。那遇到应用程序无法正常启动的问题要如何解决呢?相信大家肯定都是十分疑问的,每次都是只能忍痛重新安装软件。今天,小编就和大家探讨下应用程序无法正常启动的解决方法,帮助大家排忧解难。0xc000007b电脑图解1  第一种方案:SFC检查系统完整性来尝试修复丢失文件  1、打开电脑搜索输入cmd.exe,选择以管理员身份运行,跳出提示框时选择继续。0xc000007b电脑图解2_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。

oracle介质恢复和实例恢复的异同-程序员宅基地

文章浏览阅读396次。1、概念 REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:实例恢复(INSTANCE RECOVERY);介质恢复(MEDIA RECOVERY)。 实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的..._oracle 实例恢复和介质恢复

随便推点

springcloud(七) feign + Hystrix 整合 、-程序员宅基地

文章浏览阅读141次。之前几章演示的熔断,降级 都是 RestTemplate + Ribbon 和RestTemplate + Hystrix ,但是在实际开发并不是这样,实际开发中都是 Feign 远程接口调用。Feign + Hystrix 演示:  eruka(略)order 服务工程:  pom.xml<?xml version="1.0" encoding="U..._this is order 服务工程

YOLOv7如何提高目标检测的速度和精度,基于优化算法提高目标检测速度-程序员宅基地

文章浏览阅读3.4k次,点赞35次,收藏43次。学习率是影响目标检测精度和速度的重要因素之一。合适的学习率调度策略可以加速模型的收敛和提高模型的精度。在YOLOv7算法中,可以使用基于余弦函数的学习率调度策略(Cosine Annealing Learning Rate Schedule)来调整学习率。

linux中进程退出函数:exit()和_exit()的区别_linux结束进程可以用哪些函数,它们之间有何区别?-程序员宅基地

文章浏览阅读4k次,点赞4次,收藏9次。 linux中进程退出函数:exit()和_exit()的区别(1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。(2)调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr ...). exit函数是在_exit..._linux结束进程可以用哪些函数,它们之间有何区别?

sqlserver55555_sqlserver把小数点后面多余的0去掉-程序员宅基地

文章浏览阅读134次。select 5000/10000.0 --想变成0.5select 5500/10000.0 --想变成0.55select 5550/10000.0 --想变成0.555select 5555/10000.0 --想变成0.5555其结果分别为:0.5000000 0.5500000 0.5550000 0.5555000一、如果想去掉数字5后面多余的0 ,需要转化一下:selec..._sql server 去小数 0

Angular6 和 RXJS6 的一些改动_angular6,requestoptions改成了什么-程序员宅基地

文章浏览阅读3.1k次。例一:import { Injectable } from '@angular/core';import { Observable } from 'rxjs';import { User } from "./model/User";import { map } from 'rxjs/operators';import { Http, Response, Headers, RequestOp..._angular6,requestoptions改成了什么

C++解析XML文件_c++ xml解析-程序员宅基地

文章浏览阅读7.9k次,点赞17次,收藏110次。C++读取XML文件_c++ xml解析

推荐文章

热门文章

相关标签