unity3d 运行时动态生成模型《一》
2014-01-21 11:19:41| 分类:技术相关 | 标签:unity3d 动态生成模型 mesh shader colider |举报|字号订阅
一般,unity3d开发都是使用第三方工具提前做好模型,如3dmax,sketchUP,Maya等。这一点对于游戏行业基本已经够用了,甚至对于游戏行业来说,unity3d后续版本不断强化的动画系统也是一个无需求的产品。因为,对于游戏开发来说,unity3d就如他的名字一般,他只是一个整合工具,将3d 模型与代码粘合到一起,达到预期的效果。所以,对于游戏,个人觉得,其主要竞争力在于画面特效,即在于美工,而非coder。当然并不是说coder不重要。
不幸的是本人为一名coder,更为不幸的是,本人从事的并非游戏业,而是虚拟现实。对于该行业,很多人的认识还停留在厂区漫游等比较傻瓜化的互动,个人觉得这种傻瓜式的漫游,适用的行业,约莫也只有楼盘展示以及一些港口的面子工程了。对于工业控制系统的信息化需求来说,其没有任何实用价值。
本文要实现的功能是动态生成模型。为这个系列的第一章。其目标在于根据用户的输入生成出指定的模型。本文实现的是简单的隧道模型,如果对于复杂的模型,需要精细的数学知识扩充,但对于unity3d的使用则无两样,均通过指定的一些方法实现。这个需求,在非静态工厂的监控很为强烈,因为场景经常变化,不可能让工程人员或者研发人员在现场一直维护。
动态生成模型,则我们需要知道模型都需要哪些信息才能展现出来。此处,我们需要用到的是unity3d的Mesh(网格)、Material(材质,其中包含贴图)、Collider(碰撞体,游戏效果,否则就被当空气穿越了)。
模型,首先需要骨架,即哪些顶点。撑起一个骨架,另外还需要一些线把这些点连接起来,因为并不是所有的点都两两互联,那样就不是模型,而是打结的渔网了。
1、计算顶点,方法参考数学,因为不是本文重点,跳过。暂定顶点的寄存器为Vector3[] vertexArray。
2、计算三角面。此处三角面的计算,需要注意的是右手螺旋定律,即法线方向是根据顶点的右手螺旋,大拇指方向。搞清楚这一点,就运用你的数学知识计算三角面阵列吧。此处三角面阵列比较坑爹的是,我也不懂为什么
到了这里,动态生成模型任务收工。下一章会介绍,模型之间的布尔运算。毕竟对于隧道这个东西,我们是一截一截的生成,后续还要将其布尔运算,以符合实际情况。最后贴上一张我的效果图。
Unity3D 运行时动态生成模型<二> 选择模型
2014-01-23 10:01:37| 分类:技术相关 | 标签:unity3d 轮廓 |举报|字号订阅
接上一篇文章,动态生成了简单的模型。下一步就是需要对模型进行编辑,首
当其冲的是选择模型。即当鼠标移动到物体上时,物体有一定的特效,本文选
择的是给物体增加一个薄边。当对物体单击来选择或撤销选择时,也需要有一
定的特效,即当物体被选择之后,物体需要一个特效表示自己被选择了。本文
选择的是给物体一个厚边。
先来看下效果。
此处的实现参照https://www.sodocs.net/doc/3014391566.html,/forum/read.php?tid=3592。
此处对于实现的细节不再详细介绍,直接参考此文章即可。
本文主要对于原样例代码进行了整改,优化。以达到无入侵式显示轮廓。即为达到该效果,仅需把需要显示轮廓的物体调用全局函数即可实现,而无需按照上文中那般,需要提前绑定一些脚本以及创建轮廓摄像机(本质上这些事情依然存在,不过由代码自动完成)。
示例代码:
即哪里需要,直接调用OutLineManager的相关方法即可。相对而言,更好在项目中部署使用。项目下载地址
https://www.sodocs.net/doc/3014391566.html,/detail/u010302605/6876007.
最近缺分,不好意思各位了,望谅解
Unity3D 运行时动态生成模型<三> 编辑模型
2014-02-11 20:52:53| 分类:技术相关 | 标签:unity3d gizmo 位移旋转缩放 |举报|字号订阅年后开工第二天,整理了下去年年末写的功能。去年,先写了模型的生成
以及选择,但对于VR来说,这个还够,因为我们绕不开的一个问题,我们需
要在线对模型进行编辑,如移动位置旋转缩放等。如果纯粹代码实现移动缩放
旋转,相信入门的都会。但我们肯定要一个友好的交互,即给用户一个比较友
好的编辑方式。我个人认为这方面,也不用费脑筋了,直接看看3dmax或者unity3d自身提供的编辑方式即可,这种方式真的很好,也许还存在更好的。于
是我的目标就变成了山寨。
同网友聊天过程中得知在unity商店里面有一款RT Gizmo,价格五刀,实现的功能即为我需要的功能。果断,google之,最后花费一定资源分从某网站
下载到手,打开一看,竟然是UnityScript直接开发的,故而也触动了我的欲望,C#整改之。
在整改过程中不得不吐槽下,写代码的时候,能不能不要太面向过程。用着面向过程的思路,用着蛋痛的js写出的代码真的看起来很费力。最后,我不得不首先翻译成C#,再进行整改。这里推荐一个网站
http://files.m2h.nl//js_to_c.php,该网站可以直接将UnityScript翻译成C#,虽然会有错,需要自己再手动修改,但真的节约了很多工作量。
下一步就是对代码的详细修改,删去那些不必要的代码,如广告以及一些UI的代码。因为我想要的很简单,就是位移旋转缩放,不要其他花哨的没用的东西,如一个GUI绘制的界面用于一些信息交互。
整改代码之后,效果直接上图:
缩放:
位移:
旋转:
t'r 如五中所言,之前希望的是与Fbx文件的交互,但是现实的骨感让我不
得不另觅他径。如果有人也在搞fbx sdk的问题,希望能和我联系,不甚感激。
本文要讲述的是自定义文件保存模型信息。既然自定义,那么就是要搞
清楚一个模型的渲染到底需要哪些信息。
此处,因为我从事unity3d开发也不过半年时间,对于3d模型的理解还
很肤浅,故而此处,我也只能对着unity3d来思考,我渲染那一个模型需要哪
些信息。兴许等工作闲暇之后,再深层次分析fbx文件,再给出详细的3d模型
的数据结构。
我们首先在unity中创造一个cube,然后查看其属性。我们看到其存在
的组件有Transform、MeshFilter、MeshRender。
那我们依次分析。
Transform:
我们需要关注的属性包括:
1)表征子变换个数的childCount
3)表征相对父物体的空间角信息localEulerAngles
4)表征相当父物体的空间位置信息localPosition
5)表征相对父物体的缩放信息localScare
6)表征相互世界坐标系的空间角信息eulerAngles,rotation
7)表征相对世界坐标系的位置信息postion
8)表征相对世界坐标系的缩放信息lossyScale
9)表征从自身坐标系到世界坐标系转换的矩阵localToWorldMatrix
10)表征从世界坐标系到自身坐标系转换的矩阵worldToLocalMatrix
11)表征自身坐标系的X方向right
12)表征自身坐标系的Y方向up
13)表征自身坐标系的Z方向forward
14)表征父变换信息parent
本文讨论的为单物体信息,从中选取我们需要关注的信息,梳理出来:postion、rotation、localScare(对于无父物体时,该变量表征其相对于世界坐标系的缩放,之所以不选择lossyScale是因为彼属性为只读的。转换矩阵信息无需存储,会自动重新计算。)
于是我们得到第一批需要存储的信息:位置信息、空间角信息、缩放信息。
MeshRenderer:
我们看到MeshRenderer其本身不存在任何状态性成员,均为直接继承于其父级Renderer。Renderer的代码如下
我们查看其具有set类的属性(只能get的不会具有状态记忆功能,仅仅是从其他状态成员上计算所得而已。)
1)表征是否投射阴影的标志castShadows
2)表征是否启用的标志enabled。(很多人喜欢问如果隐藏一个物体,这个就是隐藏物体的开关)
3)表征应用到该渲染器的光照图的索引lightMapIndex
4)表征应用到该渲染器的光照图的位置以及偏移lightMapTillingOffset (Vertor4)
5)表征物体的材质信息material、materials(多材质)
6)表征是否接收阴影receiveShadows
于是我们得到另一组需要存储的信息:阴影信息(是否投射,是否接收)、光照图信息(索引、偏移),材质信息(需要注意的是多材质时,材质
表现为一个数组,其中每一项的index即为该材质对应的通道号,在后续mesh 中会使用到。)
MeshFilter
可以看到他只有两个属性,一个是mesh,一个是sharedMesh,两个都
i是Mesh对象。通过官方手册,我们得知这两个属性的区别在于,mesh是当
前物体独有的,你修改他,不会影响其他也使用这个网格的物体,但是如果修
改sharedmesh,则会连带其他使用该网格的物体一起变化。那么,对于此处,我们随便选择一个即可,因为我们自己保存加载物体,不会出现多个物体使用
同一个网格。
Mesh:
1)表征网格顶点信息vertices
2)表征顶点对应的颜色信息colors
3)表征三角面信息triangles
4)表征纹理坐标UV
5)表征子网格的数量subMeshCount,每一种材质均对应一个独立的网格列表
6)此处不考虑人物模型,骨骼类的成员不予考虑
7)表征网格包围体信息bounds(可使用重新计算方法,不需存储)
至此我们已经搞清楚了,在unity3d中存储一个物体需要存储的信息。于是着手编码。此处,使用C#本身支持的序列化,使得信息的存储解析异常简单。
最终调用代码: