怎样通过Mesh创建的投影几何图元元怎么改变颜色

怎么改变物体颜色【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:77,664贴子:
怎么改变物体颜色收藏
我想改变物体颜色,但是材质球不变,求大神指点
承办方:丽江市体育局 丽江斐瑞康网络科技有限公司
xxx.GetComponent&MeshRenderer&().material.color=Color.red
写反了,哈哈
登录百度帐号推荐应用 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
unity3d学习之利用mesh绘制几何图形实现
下载积分:900
内容提示:unity3d学习之利用mesh绘制几何图形实现
文档格式:DOC|
浏览次数:862|
上传日期: 00:55:03|
文档星级:
全文阅读已结束,如果下载本文需要使用
 900 积分
下载此文档
该用户还上传了这些文档
unity3d学习之利用mesh绘制几何图形实现
关注微信公众号创建mesh - CSDN博客
原文:/archives/76484
什么是程序几何体?
程序几何体就是用代码建模的几何体。通常情况下,制作3D mesh(3D网格模型)是手动操作美术软件如Maya、3DS Max或者Blender等完成的,而本文要介绍的做法却是使用程序指令构建mesh。(请点击此处阅读本文)
这可以在运行时间(mesh直到终端用户运行程序时才完成)、编辑时间(当应用正在开发时,使用脚本或工具)或在3D美术包(使用脚本语言如MEL或MaxScript)里完成。
showcase_quarters(from gamasutra)
程序生成mesh的优点在于:
多样性:可以用随机变量生成mesh,也就是说,你可以避免重复制作几何体。
可扩展性:mesh的细节程度可以由终端用户的机器性能或偏好来决定。
可控制性:不了解3D建模软件的游戏/关卡设计师可以理好地控制关卡的外观。
速度:一个对象可以简单迅速地生成多个变体。
以下是本人的背景:我是一名3D美工转游戏程序员再转独立开发者,我认为思考如何用脚本制作出一样东西是非常有趣的。当然,这种乐趣不是谁都能体会,不过没关系。
以下是我自己的游戏项目中的案例:
project_strangers_call(from gamasutra)
(《Stranger’s Call》的由程序生成的关卡:左半边是最高细节设置,右半边是最低细节设置,因为这些是根据随机生成的布局产生的,所以不可能出现相同的关卡)。
project_ludus_silva(from gamasutra)
(《Ludus silva》中的植物——这些是玩家在游戏中制作/编辑的)。
曾经有人看到这些图像后问我怎么做出来的。好吧,是用一些基本的形状再添加一些细节做成的。我做过的大部分程序生成的东西都是由两种基本形状构成的:平面和圆柱体。
接下来我们就来学习如何制作吧。
本文中出现的所有案例都是使用C#和Unity制作的。所有重要的概念都可以转化为你自己习惯的语言/引擎。
你必须掌握C#的基础,如果还懂一些3D几何体的知识就更好了。
不确定自己的知识储备是否足够的人可以做下面的测试:
1、什么是class、function、array,以及loop?
2、如果我用C#语言写出来,你会不会认得出?
3、你了解3D向量是什么吗?(Unity中的Vector3结构)
4、你知道如何获得从一个点到另一点的方向吗?
怎么样?全部会吗?那就太好了。
不太会?那你可能得去学习一下《官方Unity脚本教程》和“基础C#教程”。
什么是mesh?
大部分学过3D美术或至少了解过3D美术的人都可以跳过这部分。对于那些完全不懂3D美术的人,可以学习一下这些简要的介绍。
我们后面要构建的是一个polygon mesh(多边形网格模型)。可以把它当成3D空间中的一系列顶点(vertices)构成的一系列三角形,每个三角形三个顶点之间形成平面。三角形可以也可以不共享顶点。
demo_sphere_cube_wireframe(from gamasutra)
(两个3D mesh。左边是灯光渲染后的模型,右边是三角形线条结构。)
三角形和多边形
在我们继续学习以前,首先要理清一些常用的术语。你可能听说过“poly-count”或“high-poly”/“low-poly”之类的术语。这其中的“多poly”通常是指三角形,但最好还能了解一下谁使用这些术语。大多数3D建模软件允许美工用任意边的多边形制作模型。这种软件生成的poly-count通常计算的是那些图形。但当需要渲染时,那些形状通常得分成三角形,因为那样形像软件才能理解。Unity的Mesh class也只能理解三角形。所以我们也将使用三角形建模。
除了三角形和3D位置,我们还要给mesh添加其他数据,如法线(normal)。所谓的“法线”就是与顶点垂直的向外方向。在光照mesh时要用到法线。
demo_normals(from gamasutra)
另一个要添加的另一个东西是UV座标(或简称为UV)。当给网格模型添加材质时就会用到UV。UV座标是2D空间的位置。在那个座标上的材质的像素会被贴到mesh的对应位置上。UV通常是打开的,因为这样可以把它们理解为从mesh上剥离下来的表面,然后摊平放在材质空间中。
demo_uvs(from gamasutra)
以上就是mesh的基本知识。下面我们来做几个mesh。
本教程有些长度,所以我分成了如下几个部分:
1-1、平面:从平面到盒子
1-2、平面的进一步运用:制作两个物品—-房子和围栏
2-1、圆柱体:基本物品—-蘑菇和花
Unity材料:Unity程序包中包含本教程使用到的脚本和场景。
资源文件夹:就是资源文件。
好吧,我们从quad(四方形)开始吧。
screen_plane(from gamasutra)
最简单的形状。这是一个基本平面,有4个顶点,和两个三角形。
我们从我们必需的组件开始制作。这个mesh有顶点、三角形、法线和UV座标。绝对必要的部分只有顶点和三角形。如果你的模型不需要在场景中光照,那么就不需要法线。如果你的模型不需要贴材质,那么就不需要UV。
Vector3[] vertices = new Vector3[4];
Vector3[] normals = new Vector3[4];
Vector2[] uv = new Vector2[4];
现在我们给顶点赋一些值。以上代码有两个之前定义好的变量:m_Width和m_Length。你应该知道表示的是quad的宽度和长度吧。
这个mesh是在XZ面创建的,所以法线的方向与Y轴一致(适合做地面)。你也可以按自己的习惯改用XY面,用Z轴做法线(适合做看板)。
位置值从0.0f开始到长度/宽度,也就是用[0.0, 0.0] 作为mesh的一个顶点位置。mesh的源点就是它的轴点,所以这个mesh就会以那个顶点为旋转点。如果你愿意,还可以通过偏移宽度和长度来使那个值减半,这样轴点位于中央。
vertices[0] = new Vector3(0.0f, 0.0f, 0.0f);
uv[0] = new Vector2(0.0f, 0.0f);
normals[0] = Vector3.
vertices[1] = new Vector3(0.0f, 0.0f, m_Length);
uv[1] = new Vector2(0.0f, 1.0f);
normals[1] = Vector3.
vertices[2] = new Vector3(m_Width, 0.0f, m_Length);
uv[2] = new Vector2(1.0f, 1.0f);
normals[2] = Vector3.
vertices[3] = new Vector3(m_Width, 0.0f, 0.0f);
uv[3] = new Vector2(1.0f, 0.0f);
normals[3] = Vector3.
diagram_plane_stage1(from gamasutra)
现在我们来做三角形。三角形是由3个整数确定的,各个整数就是角的顶点的index。各个三角形的顶点的顺序通常由下往上数的,可以是顺时的也可以是逆时的,这取决于我们从哪个方向看三角形。通常,当mesh渲染时,逆时针的面会被挡掉。我们希望保证顺时针的面与法线的主向一致(即向上)。
int[] indices = new int[6]; //2 triangles, 3 indices each
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
diagram_plane_stage2(from gamasutra)
现在我们整理一下。在Unity中,这只是给我们刚才做的所有array赋给一个Unity Mesh class的实例。我们在最后调用RecalculateBounds()来重新计算mesh的大小(渲染需要)。
Mesh mesh = new Mesh();
mesh.vertices =
mesh.normals =
mesh.triangles =
mesh.RecalculateBounds();
现在我们做好一个mesh了。在Unity场景中,我们把这个脚本添加到包含mesh过滤器和渲染器组件的GameObject中。以下代码寻找mesh过滤器并把刚做好的模型赋给它。这个模型现在作为一个物品的一个部分存在于场景中。
MeshFilter filter = GetComponent();
if (filter != null)
filter.sharedMesh =
You have now made your first procedural mesh.
这样你就做好了你的第一个程序生成mesh。
好吧,我们现在假设要做一个程序生成的物品。最无聊的部分就是一次又一次地写相同的mesh初始代码,但还不至于像因为出现错误而被迫重写那么让人郁闷。
using UnityE
using System.C
using System.Collections.G
public class MeshBuilder
private List m_Vertices = new List();
public List Vertices { get { return m_V } }
private List m_Normals = new List();
public List Normals { get { return m_N } }
private List m_UVs = new List();
public List UVs { get { return m_UVs; } }
private List m_Indices = new List();
public void AddTriangle(int index0, int index1, int index2)
m_Indices.Add(index0);
m_Indices.Add(index1);
m_Indices.Add(index2);
public Mesh CreateMesh()
Mesh mesh = new Mesh();
mesh.vertices = m_Vertices.ToArray();
mesh.triangles = m_Indices.ToArray();
//Normals are optional. Only use them if we have the correct amount:
if (m_Normals.Count == m_Vertices.Count)
mesh.normals = m_Normals.ToArray();
//UVs are optional. Only use them if we have the correct amount:
if (m_UVs.Count == m_Vertices.Count)
mesh.uv = m_UVs.ToArray();
mesh.RecalculateBounds();
你需要的所有数据都在一个class中,它很容易在两个函数之间通过。另外,因为我们使用的是列表,而不是array,所以不会误算顶点或三角形的数量。这样还更容易组合mesh:只要用相同的MeshBuilder生成就行了。
注:这是我在自己的项目中使用的class的简化版。本版不能做的事,包括切线和顶点颜色,或为大mesh保留的空间,或者变更这个Mesh class中已存在的实例。
现在,使用这个class,我们的quad生成代码如下:
MeshBuilder meshBuilder = new MeshBuilder();
//Set up the vertices and triangles:
meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, 0.0f));
meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, m_Length));
meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(m_Width, 0.0f, m_Length));
meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(m_Width, 0.0f, 0.0f));
meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.AddTriangle(0, 1, 2);
meshBuilder.AddTriangle(0, 2, 3);
//Create the mesh:
MeshFilter filter = GetComponent();
if (filter != null)
filter.sharedMesh = meshBuilder.CreateMesh();
开始做几何体
screen_ground(from gamasutra)
你的关卡地形,其实是一个平坦的平面。
注:这里的“不平坦”是由于给各个顶点赋了随机高度。这么做是因为可以让代码漂亮简单,不是因为可以让地形好看。如果你是很认真地要做一个地形mesh,你最好使用heightmap或perlin noise等算法。
这个地形可以当作是一系列排列在网格中的quad。这正是我们要做的第一步。首先,我们定度一个生成我们刚才做的quad的函数。只有这个函数会把参数作为位置offset(平移)值,这是添加到顶点位置的。
void BuildQuad(MeshBuilder meshBuilder, Vector3 offset)
meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, 0.0f) + offset);
meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, m_Length) + offset);
meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(m_Width, 0.0f, m_Length) + offset);
meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
meshBuilder.Normals.Add(Vector3.up);
meshBuilder.Vertices.Add(new Vector3(m_Width, 0.0f, 0.0f) + offset);
meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
meshBuilder.Normals.Add(Vector3.up);
int baseIndex = meshBuilder.Vertices.Count – 4;
meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);
注意,三角形的顶点指数。这次,我们添加未知数量的quad到MeshBuilder中。不是从index0开始,我们必须从刚添加的顶点开始。
现在调用我们刚写的函数。相当简单,只是一对调用BuildQuad()的循环,每次循环都增加offset的X和Y值:
MeshBuilder meshBuilder = new MeshBuilder();
for (int i = 0; i & m_SegmentC i++)
float z = m_Length *
for (int j = 0; j & m_SegmentC j++)
float x = m_Width *
Vector3 offset = new Vector3(x, Random.Range(0.0f, m_Height), z);
BuildQuad(meshBuilder, offset);
现在运行代码,你会看到如下图所示的模型:
screen_ground_stage1(from gamasutra)
现在看它的基本布局,但mesh效果似乎不太好。我们把这些分散的平面组合成一个吧。为此,我们要先使邻近的quad共享顶点,而不是给每一个quad做4个顶点。事实上,我们只需给各个面做一个顶点。然后这个quad就可以使用这个点做出之前的行和列。新函数如下:
void BuildQuadForGrid(MeshBuilder meshBuilder, Vector3 position, Vector2 uv,
bool buildTriangles, int vertsPerRow)
meshBuilder.Vertices.Add(position);
meshBuilder.UVs.Add(uv);
if (buildTriangles)
int baseIndex = meshBuilder.Vertices.Count – 1;
int index0 = baseI
int index1 = baseIndex – 1;
int index2 = baseIndex – vertsPerR
int index3 = baseIndex – vertsPerRow – 1;
meshBuilder.AddTriangle(index0, index2, index1);
meshBuilder.AddTriangle(index2, index3, index1);
你会发现这个和之前的版本有许多不同之处。我们使用的位置offset作为顶点位置,因为这是可以增加的。另外,UV座标从外部代码通过,以避免和模型中的所有顶点相同。你会发现没有确定法线——我们之后再做这个。
最有趣的是三角形。它们并不是每次做的。这是因为各个quad 使用之前的行和列的顶点。如果这是任何行或列的第一个顶点,那么就没有之前的顶点可以做quad 了。
index也不同。我们从最后一个顶点index出发,并反向。前面的index是来自前一列的顶点。前一行的index必须减去这一行的index值。
以我的经验,计算三角形index是程序模型生成中最麻烦的部分,因为每次mesh算法改变,就要返回修改index。
我们再看一下调用这个函数的代码:
for (int i = 0; i &= m_SegmentC i++)
float z = m_Length *
float v = (1.0f / m_SegmentCount) *
for (int j = 0; j &= m_SegmentC j++)
float x = m_Width *
float u = (1.0f / m_SegmentCount) *
Vector3 offset = new Vector3(x, Random.Range(0.0f, m_Height), z);
Vector2 uv = new Vector2(u, v);
bool buildTriangles = i & 0 && j & 0;
BuildQuadForGrid(meshBuilder, offset, uv, buildTriangles, m_StepCount + 1);
注意,我们是在根据位置offset计算UV。另外还要注意i和j要大于0。这就是我们停止每行或列的第一个顶点再做三角形的办法。
还有一个小小的不同。这个i和j循环的结束条件是“ &=”而不是“&”。因为第一个顶点不生成三角形,我们的地面平面在各个方向上现在还是比较小。作为弥补,我们让循环再进行一次。
最后,还记得那些我们没有计算的法线吗?在模型中,各个顶点的法线取决于与周围顶点有关的顶点位置。因为我们在各个顶点位置都有一些随机性,所以直到所有顶点都生成后才能计算法线。
事实上,我们可以作弊。Unity提供了一种计算法线的函数。
Mesh mesh = meshBuilder.CreateMesh();
mesh.RecalculateNormals();
注意那个Mesh.RecalculateNormals()并不总是最好的解决方案,可能产生奇怪的结果,特别是如果mesh有缝合处的话。这个我们之后再说。但对于我们现在这个平面,它是够用了。
screen_cube(from gamasutra)
盒子并不比quad来得复杂。它其实只是6个quad。
做一个盒子,我们要使用BuildQuad函数,以决定quad的面向。
the box(from gamasutra)
void BuildQuad(MeshBuilder meshBuilder, Vector3 offset,
Vector3 widthDir, Vector3 lengthDir)
Vector3 normal = Vector3.Cross(lengthDir, widthDir).
meshBuilder.Vertices.Add(offset);
meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
meshBuilder.Normals.Add(normal);
meshBuilder.Vertices.Add(offset + lengthDir);
meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
meshBuilder.Normals.Add(normal);
meshBuilder.Vertices.Add(offset + lengthDir + widthDir);
meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
meshBuilder.Normals.Add(normal);
meshBuilder.Vertices.Add(offset + widthDir);
meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
meshBuilder.Normals.Add(normal);
int baseIndex = meshBuilder.Vertices.Count – 4;
meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);
这看起来非常像我们之前使用的BuildQuad(),除了这里我们使用方向向量并添加到offse中,而不是直接把值插到X和Y位置。
这里,法线也可以轻易地计算了。只是两个方向的向量积。
注:或者,你可以写一个直接取四个角的位置的函数BuildQuad(),然后使用那些值。对于非常复杂的mesh,那可能是必须的,但对于我们的这个mesh,方向代码更简单清楚。
现在调用新函数:
MeshBuilder meshBuilder = new MeshBuilder();
Vector3 upDir = Vector3.up * m_H
Vector3 rightDir = Vector3.right * m_W
Vector3 forwardDir = Vector3.forward * m_L
Vector3 nearCorner = Vector3.
Vector3 farCorner = upDir + rightDir + forwardD
BuildQuad(meshBuilder, nearCorner, forwardDir, rightDir);
BuildQuad(meshBuilder, nearCorner, rightDir, upDir);
BuildQuad(meshBuilder, nearCorner, upDir, forwardDir);
BuildQuad(meshBuilder, farCorner, -rightDir, -forwardDir);
BuildQuad(meshBuilder, farCorner, -upDir, -rightDir);
BuildQuad(meshBuilder, farCorner, -forwardDir, -upDir);
Mesh mesh = meshBuilder.CreateMesh();
diagram_plane_directional(from gamasutra)
这里,所有平面都来源于两个盒子中相对的角。注意近处的角是源头,意味着mesh将以此为轴点。把farCorner值除以2,nearCorner取其结果的负值。
Vector3 farCorner = (upDir + rightDir + forwardDir) / 2;
Vector3 nearCorner = -farC
用心的读者会发现,第个quad都有4个顶点,所以整个盒子共有24个顶点。当然,如果只有8个,一角一个,使所有三角形共用顶点,那效率就更高了。是不是跟地面mesh一样?
答案是否。这24个顶点我们都需要。这是因为即使顶点位置与各个角一样,法线(和UV)也是不一样的。如果法线共享,那么光照效果就会非常差。
通过分离各个quad的顶点,我们制作了一个沿着边的接合,使法线分到各个面。
注:也就是说,如果出于某些原因,你的mesh不使用法线或UV,那就重写代码共享顶点也是可以的——任何形状都行。如果你要渲染上百个物品,或者制作高模,这么做节约性能的效果是非常明显的。
好好做盒子吧。下一部分,我们将看看如何更好地利用基本形状,以做出更有意思的mesh。
本文已收录于以下专栏:
相关文章推荐
private float _wallHeight=3.5f;
private float _wallLength=3.0f;
private float _wallWidth=0.24f;//默...
三维开发渲染最多的对象大概是网格mesh了,Webgl开发三维也不例外。
网格就是一系列的多边形组成的,三角形或者四边形,网格一般由顶点来描绘,我们看见的三维开发的模型就是由一系列的点组成的。
在一个可以正常运行的ogre程序里边,找到createscene函数,添加如下代码:
//定义对象并设置材质名称与绘制模式
ManualObject* manual = mSce...
在一个可以正常运行的ogre程序里边,找到createscene函数,添加如下代码: //定义对象并设置材质名称与绘制模式ManualObject* manual = mSceneMgr-&creat...
篇unity3d教程我们来学习下,如何动态创建Mesh来制作一个闪亮的星星Star,看下最终效果图
unity star下面开始,本篇unity3d教程将让你学会如何创建一个星型控件以及如何制作...
1 创建mesh元素  我们在创建简单的网格模型或者为已存在的网格模型添加元素的时候,我们应该使用AddVertices和AddFaces这两个函数,新的元素被添加到网格模型的尾部,函数会返回指向第一...
Unreal Engine 4的物理引擎用的是PhysX。支持网格破坏、布料,物理粒子等,很强大。以前需要编码才能完成的工作,在Unreal Engine 4 中只需要拖拖拽拽就完成了,很方便。
官网上有教程,只是拷贝代码时格式混乱,还得自己调整,故讲自己调整好的保存一下。void createColourCube()
/// Create the mesh via the Mesh...
转载:/kyokuhuang/p/4191169.html
http://blog.csdn.net/familycsd000/article/details/
有节操的引用……上面为本日志引用来源 
本文做了些许改动
//我使用的功能让...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)君,已阅读到文档的结尾了呢~~
unity3d学习之利用mesh绘制几何图形实现【最新资料】,unity3d mesh绘制图形,unity mesh 绘制,unity3d mesh 几何体,ps绘制几何图形,绘制动态几何图形软件,绘制几何图形软件,几何图形绘制,webgl 绘制几何图形,如何绘制几何图形
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
unity3d学习之利用mesh绘制几何图形实现【最新资料】
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 所创建的图元在视图 的文章

 

随机推荐