MaxScript学习笔记目录
大家好,我是阿赵。之前有网友私信问了我一个相关的问题,我发现之前漏了MaxScript里面的Shape的内容,所以补一个例子,当做一个记录吧。
一、例子说明
这里做一个关于MaxScript读取二维形状(Shape)数据的例子,可能实际应用价值不是很大,因为3DsMax本身也带有这样的工具,不过作为一个例子来看看,留个记录,也算不错。
这个例子是这样的,有一条二维线条,然后做一个金字塔形状的网格模型
然后用MaxScript写一个工具,里面可以拾取二维线条,然后拾取模型,输入需要生成的数量,还有生成模型时的角度选择
点击create按钮,工具会复制指定的模型,沿着二维线条生成指定数量的模型。
比如上面的参数,生成500个模型,并且不改变模型的角度,得到的结果是这样的:
接下来改变一下角度的选项,可以生成这样的效果:
也可以选择反过来的角度,生成出这样的效果:
二、完整代码:
(
local CreateObjWin
local OnSelectShape
local OnSelectObj
local OnCreateObj
local selectedShape
local selectedObj
local ShowMsg
fn ShowMsg msg =
(
MessageBox msg title:"Tips"
)
fn OnSelectShape =
(
if $ == undefined then
(
selectedShape = undefined
)
else
(
local t = superclassof $
if t == shape then
selectedShape = $
else
selectedShape = undefined
)
if selectedShape == undefined then
CreateObjWin.selectShapeTxt.text = "no selected shape"
else
CreateObjWin.selectShapeTxt.text = selectedShape.name
)
fn OnSelectObj =
(
if $ == undefined then
(
selectedObj = undefined
)
else
(
selectedObj = $
)
if selectedObj == undefined then
CreateObjWin.selectObjTxt.text = "no selected shape"
else
CreateObjWin.selectObjTxt.text = selectedObj.name
)
fn OnCreateObj num angleType =
(
if selectedShape == undefined then
(
ShowMsg "please select shape first!"
return 0
)
if selectedObj == undefined then
(
ShowMsg "please select obj first!"
return 0
)
local space = 1.0/(num-1);
for i in 1 to num do
(
local tempObj = copy selectedObj
local sp = space*(i-1)
local pos = lengthInterp selectedShape sp
if angleType >1 then
(
local rota = lengthTangent selectedShape sp
local angleDir = -1
if angleType == 3 then
angleDir = 1
rota = rota * angleDir
tempObj.rotation = quat rota.x rota.y rota.z 1
)
tempObj.pos = pos
)
)
rollout CreateObjWin "CreateObjWin" width:246 height:300
(
label 'lbl1' "shape:" pos:[17,30] width:40 height:17 align:#left
label 'selectShapeTxt' "no selected shape" pos:[70,30] width:93 height:17 align:#left
label 'lbl3' "obj:" pos:[16,63] width:40 height:17 align:#left
label 'selectObjTxt' "no selected obj" pos:[70,63] width:93 height:17 align:#left
label 'lbl5' "num:" pos:[17,99] width:40 height:17 align:#left
edittext 'numInputBox' "" pos:[53,95] width:128 height:23 align:#left
button 'createBtn' "create" pos:[59,214] width:107 height:27 align:#left
button 'selectShapeBtn' "select" pos:[171,30] width:61 height:17 align:#left
button 'selectObjBtn' "select" pos:[171,61] width:61 height:17 align:#left
radiobuttons 'angleBtns' "angle:" pos:[17,137] width:79 height:62 labels:#("none", "positive", "negative") default:1 columns:1 align:#left
on createBtn pressed do
(
local str = numInputBox.text
local val = str as number
local angleType = angleBtns.state
print angleType
if val == undefined or val<=0 then
ShowMsg("please input create number")
else
OnCreateObj val angleType
)
on selectShapeBtn pressed do
OnSelectShape()
on selectObjBtn pressed do
OnSelectObj()
)
createDialog CreateObjWin
)
三、注意的地方:
这个代码相对不是很复杂,下面说一下用到的几个知识点:
1、判断对象属于Shape
在拾取Shape对象的时候,如果拾取的对象不是Shape,将会对后面的步骤产生影响,所以在拾取对象的时候,用superclassof 获取一下当前选择的物体的父类,看是不是 S h a p e 。这里我也是偷懒了,因为用 获取一下当前选择的物体的父类,看是不是Shape。 这里我也是偷懒了,因为用 获取一下当前选择的物体的父类,看是不是Shape。这里我也是偷懒了,因为用读取当前选择的物体,如果同时选择的物体有多个的时候,会返回一个数组,包括下面的选择网格模型也一样。按道理要先判断是否数组然后再进行类型判断的。各位有兴趣可以自己补充一下。
2、获取Shape上的某一个点的坐标
lengthInterp [ <curve_num> ] [ steps: ]
通过这个方法,可以获取某条shape上面的某个比例[0.0-1.0]的一个点的位置,比如输入0.5,就可以获取线段中间一个点的坐标
3、获取Shape上的某一个点的切线方向
lengthTangent [ <curve_num> ] [steps: ]
通过这个方法可以获取线条上某个比例的点的切线方向
4、Shape的其他方法
可以看一下官网的API说明: