阿赵的MaxScript学习笔记分享十三《导出Obj模型》

文章介绍了如何使用MaxScript编写脚本来导出3DsMax中的Obj格式模型,包括顶点、法线、纹理坐标等信息,并解释了为何自定义导出以及代码中的关键部分,如坐标轴转换、保留小数位数和处理多个对象的索引。此外,还讨论了Obj文件结构和MaxScript中处理数据的一些注意事项,如添加修改器、删除无用数据等。

MaxScript学习笔记目录
大家好,我是阿赵。
之前分享了很多MaxScript的学习笔记,但很多细节,我觉得只有在实际应用里面才能讲明白,因为MaxScript包含很多命令,没有办法一一列举,其实也没必要一一列举,因为MaxScript官网上是有帮助手册的,只是手册里面内容太多,反而不好查找,所以我才写了一部分常用的学习笔记。
这次用MaxScript写一个导出Obj格式模型的完整例子。可以把很多内容整合在一起运用一下。
3DsMax本身有导出Obj格式的功能,为什么我还要自己写一个能?这是因为之后我会介绍一些需要配合着模型数据来导出的技术,如果通过3DsMax自带的导出功能,可能会导致某些数据的索引和我需要的不一致。
其实我很多工具都是一时兴起的时候写的,可能写的时候并没有什么用,但说不定在某个时候会觉得还是挺好用的,所以也无所谓了。如果觉得没什么实际用途,也可以当做是写脚本的案例来查看一下

一、完整代码

(
local ShowTips
local FloorNum
local FloorVector
local VectorToString
local VectorPosToString
local GetOneSaveObjContent
local CheckObjHasMeshInfo
local ExportObjFun
local ExportSelectedFun
local ExportAllFun
--习惯加一个工具版本号,可以在出问题的时候检查是哪个版本工具导出的
local toolVerStr = "1.0.0"

--弹窗提示	
fn ShowTips content = 
(
	messagebox content
)

--保留小数位数
--val1:原始数字
--val2:保留小数位数
fn FloorNum val1 val2 = 
(
	local val3 = pow 10 val2
	local val4 = (floor (val1*val3))/val3
	return val4
)

--保留Point的小数位数(比起point,我还是更习惯叫他vector)
--val1:原始的point
--val2:保留小数位数
fn FloorVector val1 val2 = 
(
	local val3 = [(FloorNum val1.x val2),(FloorNum val1.y val2),(FloorNum val1.z val2)]
	return val3
)

--获得Point的保存字符串
fn VectorToString vect = 
(
	local str = (vect.x as string)+" "+(vect.y as string)+" "+(vect.z as string)
	return str
	
)

--获得Point在转换坐标轴之后的保存字符串
--所以y和z要调转,并且y要乘以-1
fn VectorPosToString vect = 
(
	local str = (vect.x as string)+" "+((vect.z) as string)+" "+((vect.y*-1) as string)
	return str
)

--获得一个物体需要保存的数据字符串
--如果同时导出多个物体,顶点坐标、法线、uv等是多个物体的数据排在一起的
--所以要知道当前导出的物体的顶点、法线、uv的开始的索引,以便接着上一个物体的索引
fn GetOneSaveObjContent obj posStartIndex normalStartIndex uvStartIndex = 
(
	select obj
	
	--每个单独物体都加一个对象名称,便于阅读
	local saveContent = "#\n"
	saveContent += ("#  Object "+obj.name+"\n")
	saveContent +="#\n"
	
	--一开始添加了Edit_Mesh和Edit_Normals两个修改器
	--这是因为我们收集的是三角面,所以转成Editable Mesh会方便获取三角面的索引
	--然后为了收集准确的法线数据,所以用Edit_Normal来收集
	--注意两个修改器的添加顺序
	--Edit_Mesh只要在堆栈里面,就可以使用meshop的方法
	--但Edit_Normals一定要在堆栈顶部,才能用相关的方法获取
	local addModNum = 2
	if (getNumTVerts obj.mesh) == 0 then
	(
		--假如物体没有展过UV,下面获取UV信息时会报错,所以强制给加一个Unwrap_UVW修改器
		modPanel.addModToSelection (Unwrap_UVW ()) ui:on
		addModNum = 3
	)
	modPanel.addModToSelection (Edit_Mesh ()) ui:on
	modPanel.addModToSelection (Edit_Normals()) ui:on
	local modN = obj.modifiers[1]

	--收集顶点坐标
	local vertexNum = GetNumVerts obj.mesh
	local vertPosArr = #()
	local vertPosList = #()
	for i in 1 to vertexNum do
	(
		local vertPos = meshop.getvert obj i
		vertPosArr[i] = vertPos
		local findIndex = findItem vertPosList vertPos
		if findIndex == 0 then
		(
			append vertPosList vertPos
		)
	)
	for i in 1 to vertPosList.count do
	(
		saveContent += "v  "
		saveContent += VectorPosToString(vertPosList[i])
		saveContent +="\n"
	)
	saveContent+= "# "+(vertPosList.count as string)+" vertices"
	saveContent+="\n"
	
	--收集法线数据
	--这部分之前的文章介绍过,不再重复介绍
	local myVerts = #{1..vertexNum}
	local myNormals = #{}
	modN.ConvertVertexSelection &myVerts &myNormals
	local normalArr = #()
	local normalList = #()
	for i in myNormals do
	(
		--由于获取的法线向量有很长的小数位数,这里只保留4位小数
		local normalPos = FloorVector (modN.GetNormal i) 4
		normalArr[i] = normalPos
		--由于可能出现很多重复的法线向量,所以这里只保存不重复的
		local findIn
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值