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说明:
pathInterp [ <curve_num> ]
Return a point3 coordinate on the numbered curve (defaults to 1) corresponding to the
parameter value (0.0 to 1.0) that matches the 3ds Max Path controller percentage (vertex-based) interpolation.lengthInterp [ <curve_num> ] [ steps: ]
Return a point3 coordinate on the numbered curve (defaults to 1)
corresponding to the parameter value (0.0 to 1.0) that is that
fraction along the curve’s total length.resetLengthInterp ()
Clear length interpolation cache. Use this if
the curve you are length-interpolating along might have been edited
between calls.curveLength [ <curve_num> ]
Return the arc length of the
numbered curve. This length does not reflect any transform level
scaling performed on the shape.pathTangent [ <curve_num> ]
Return the tangent
direction vector at the 3ds Max Path (vertex-based) interpolated point
along the specified curve. You can use this function, for example, to
set an object’s direction to follow the curve.lengthTangent [ <curve_num> ] [steps: ]
Return the tangent direction vector at the arc-length-interpolated
point along the specified curve. You can use this function to set an
object’s direction to follow the curve.nearestPathParam [ <curve_num> ] [steps: ]
Return the interpolation parameter value (0.0 to 1.0) corresponding to
the point along the curve that is closest to the given
coordinate. The parameter is given as a 3ds MaxPath (vertex-based)
interpolation parameter value. You can then use pathInterp with this
value to find the nearest point’s coordinates, or use one of the
following functions for converting between arc-length parameters and
3ds Max Path percentage parameters.pathToLengthParam [ <curve_num> ] [steps:]
Return the uniform arc-length length parameter corresponding to the
given 3ds Max Path (vertex-based) parameter for this curve.lengthToPathParam [ <curve_num> ] [steps: ]
Return the 3ds Max Path (vertex-based) parameter corresponding to
the given uniform arc-length parameter for this curve.