淄博淘宝网站建设,烟台html5网站建设,网站营销不同阶段的网站分析目标,信誉好的赣州网站建设大家好#xff0c;我是阿赵#xff0c;周日的早上继续分享MaxScript学习笔记#xff0c;这是第十二篇#xff0c;获取和导出各种数据
1、导出数据的目的
使用3DsMax建立3D模型后#xff0c;很多时候需要输出模型到别的引擎去使用#xff0c;常用的格式有Obj、FBX、SLT等…大家好我是阿赵周日的早上继续分享MaxScript学习笔记这是第十二篇获取和导出各种数据
1、导出数据的目的
使用3DsMax建立3D模型后很多时候需要输出模型到别的引擎去使用常用的格式有Obj、FBX、SLT等。有时候这些通用的格式里面的数据不够比如obj里面就没有带顶点颜色。有时候是因为某些格式的解析比较复杂比如FBX之类我们会需要根据自己的需要来导出各种的数据。 一般来说导出模型数据会包括以下这些 顶点坐标 UV UV2 顶点颜色 顶点法线 面的索引信息 蒙皮信息 材质贴图 动画关键帧 等
首先要明白一个概念比如一个box他是由8个顶点、6个四角面组成的。但在导出到引擎使用的时候其实他是24个点12个面的因为游戏引擎绘制的一般是三角面所以一个四角面会拆分成2个三角面。然后从UV和法线的角度同一个顶点有可能是被多个面同时使用的所以顶点在属于不同的面的时候顶点的UV坐标和法线方向也是不一样的。 所以在导出数据的时候可以使用自己的方式去处理数据。其中一个方法是可以参数obj格式他把重复的顶点、UV坐标、法线方向进行合并每个数据有一个索引index然后在记录面数据的时候比如一个box有12个面他会记录12个面的信息每个面有3个顶点每个顶点包含了顶点索引、法线索引和uv索引的数据。这样操作下来存储的数据量最少也不会丢失任何数据。当然如果想把顶点颜色的数据也加进去也可以再增加一个顶点颜色的索引把它带在面的顶点数据里面导出。 下面还是以一个box为思考的参考列出了获取各种信息的方法结合着之前讲过的字符串操作方法和文件读写方法就可以根据自己的需要取导出自己的模型格式了
2、各种数据的获取方式举例
--获得网格顶点数
GetNumVerts boxt1.mesh
8
--获得某个通道的顶点数据数量1通道代表UV通道
--这里我能用1通道是因为我已经展过UV了如果没有展过UV会报错
polyop.getNumMapVerts boxt1 1
24
--获得实际的三角面数
GetNumFaces boxt1.mesh
12
--获得第一个顶点的坐标
getVert boxt1.mesh 1
[-12.5,-12.5,0]
--获得第12个面使用了哪几个顶点对应网格顶点数的索引
getface boxt1.mesh 12
[3,1,5]
--获得第12个面的法线方向
GetFaceNormal boxt1.mesh 12
[-1,0,0]
--获得第12个面引用的UV索引对应UV坐标索引
GetTVFace boxt1.mesh 12
[9,10,11]
--获得第9个UV索引点的UV坐标
getTVert boxt1.mesh 9
[0.0005,0.0005,0]特别说一下法线的获取方式和设置方式
法线的获取和赋值比较特殊一点需要注意以下几点
1.如果不通过Edit_Normals修改器来获取法线的数据是不正确的
box02 box()
$Box:Box003 [0.000000,0.000000,0.000000]converttopoly box02
$Editable_Poly:Box003 [0.000000,0.000000,0.000000]faceNum polyop.getnumfaces box02
6
for i in 1 to faceNum do
(
local faceNormal polyop.getfacenormal box02 i
print faceNormal
)
[0,0,-1]
[0,0,1]
[0,-1,0]
[1,0,0]
[0,1,0]
[-1,0,0]
OKvertNum box02.numverts
8
for i in 1 to vertNum do
(local vertNormal getNormal box02.mesh iprint vertNormal
)
[0,0,-1.5708]
[0,0,-1.5708]
[0,0,-1.5708]
[0,0,-1.5708]
[0,0,1.5708]
[0,0,1.5708]
[0,0,1.5708]
[0,0,1.5708]
OK通过以上的代码似乎可以通过polyop来获取某个面的法线方向然后也可以用点的index通过getNormal的方法来获取到mesh里面某个点的法线方向。 但其实这个获取的方法是有问题的 1首先来说这个面的法线这个面的发现方向从一个box的4个面的角度看是正确的但如果我们通过添加Edit_Normals编辑器修改其中一个面的法线然后再次打印6个面的法线方向会发现结果根本没有变化。所以我个人感觉这个从polyop里面获取的面法线方向并不是通过4个顶点的法线方向计算出来的值只是通过4个顶点的坐标位置算出来的一个法线方向。如果在不修改顶点法线的情况下应该是可以用的但我们谈论的获取法线方向一般是指顶点的法线方向所以这个面的法线方向其实没什么意义 2再来看通过getNormal方法获得的顶点法线会发现这个值有点莫名其妙首先8个点只有2种法线方向然后这个法线也没有归一化长度并不是1的所以这个获取的结果我觉得也是并没有什么用途的。实际上一个顶点有可能不止一个法线方向的下面会继续分析。
2.一个顶点具体包含多少个法线要看具体的平滑组设置 box03 box()
$Box:Box003 [0.000000,0.000000,0.000000]
converttopoly box03
$Editable_Poly:Box003 [0.000000,0.000000,0.000000]
select box03
OK
modPanel.addModToSelection (Edit_Normals()) ui:on
OK通过一段代码创建一个box然后添加了一个Edit_Normals的修改器这时候我们可以看到场景里面的box每个顶点上面伸出了3条线这些线其实就是法线了。由于一个box有8个顶点所以这个时候应该有24条法线。 为什么会有24条这么多呢那是因为这个box每个面的光滑组都不一样所以面与面之间是硬转角而虽然我们看来这个box只有8个顶点但每个顶点同时被3个面共用所以一个顶点需要3个法线方向来分别代表组成不同面时该顶点的法线方向。
这时候做一下修改返回Editable Poly选择所有面把它们的光滑组都改成1
再回到Edit_Normals这时候可以看到每个顶点只有1根法线了。这究竟是真的一个顶点变成1根法线还是由于同一个顶点的法线都重叠在一起了呢我们可以通过代码去验证一下。
local myVerts #{1,2,3,4,5,6,7,8} local myNormals #{} local modN box03.modifiers[1] modN.ConvertVertexSelection myVertsmyNormals print myNormals
这里有一段代码由于现在box03的第一个修改器就是Edit_Normals所以modN获取了这个Edit_Normals修改器然后通过ConvertVertexSelection 获取指定的myVerts的8个顶点使用到的法线id到myNormals数组 当把box03的光滑组取消的时候得到的打印结果是 #{1…24} 当把box03的所有面光滑组设置成1后得到的打印结果是 #{1…8} 很明显在把所有面的光滑组设置成1后这个box03的法线方向的确是只剩下了8个。于是我们能得出结论模型的一个顶点具体有多少个法线方向是根据面的光滑组来分的。或者换个说法面与面之间是硬边过渡还是光滑过渡是看组成面之间的边缘的顶点是否共用法线。
3.通过Edit_Normals修改器来获取法线数据
通过了上面的实验我们知道只有通过Edit_Normals修改器才能比较准确的获得和修改模型的法线。所以接下来就使用这个修改器来获取数据。 具体的步骤是这样的 1通过ConvertVertexSelection 方法获取到所有的NormalId 2通过GetFaceDegree方法逐个面获取当前的面有多少个不同角度的点组成 3通过GetNormalID方法获得组成每个面每个顶点的对应NormalId 4根据1和4的结果就可以知道每个顶点的发现方向了 具体代码
local vertNum box03.numVertslocal myVerts #{1..vertNum}local myNormals #{}local modN box03.modifiers[1]--通过ConvertVertexSelection把所有顶点用到的normalId存到myNormals数组modN.ConvertVertexSelection myVertsmyNormals--通过GetNormal方法把每一个normalId对应的法线方向存到normalArr里面local normalArr #()for i in myNormals do(local norPos modN.GetNormal inormalArr[i] norPos)print 法线集合:print normalArr--获得面的数量local faceNum modN.GetNumFaces()local faceNormalIdList #()for i in 1 to faceNum do(--corner的含义可以理解成这个面由多少个不同角度的点组成local corners modN.GetFaceDegree i--遍历组成面的这些conner通过GetNormalID方法获得组成这个面的顶点对应的normalIdlocal tempFaceNormalList #()for j in 1 to corners do(local norInd modN.GetNormalID i jappend tempFaceNormalList norInd)faceNormalIdList[i] tempFaceNormalList) print 面对应法线Idprint faceNormalIdList运行的结果
法线集合:
[0,0,-1]
[0,0,-1]
[0,0,-1]
[0,0,-1]
[0,0,1]
[0,0,1]
[0,0,1]
[0,0,1]
[0,-1,0]
[0,-1,0]
[0,-1,0]
[0,-1,0]
[1,0,0]
[1,0,0]
[1,0,0]
[1,0,0]
[0,1,0]
[0,1,0]
[0,1,0]
[0,1,0]
[-1,0,0]
[-1,0,0]
[-1,0,0]
[-1,0,0]
面对应法线Id
#(1, 2, 3, 4)
#(5, 6, 7, 8)
#(9, 10, 11, 12)
#(13, 14, 15, 16)
#(17, 18, 19, 20)
#(21, 22, 23, 24)根据需要把这些数据保存你的文件里面就可以了。
4.修改法线
顺便提一下怎样修改法线。 之前用GetNormalId可以获取到某个点的NormalId然后用GetNormal可以获得对应NormalId的具体法线方向值。那么反过来通过SetNormal方法就可以改变对应NormalId的点的法线方向了比如刚才那个例子需要把第16个NormalId的值改成[0.5,0.6,0.7]可以这样
modN.SetNormal 16 [0.5,0.6,0.7]