MaxScript是3dsmax和AutodeskVIZ内置的脚本语言,它的形式非常自由和简单,它比较浅层,也几乎不涉及内存与数据的操作
MaxScript有很多结构是非常有特色的。如坐标系关联、原始物体和材质结构;可自动设置关键帧的动画模式;还可以使用表示3dasmax层级关系的路径名来访问场景物体。
MaxScript的语法非常简单,标点符号和书写规则都非常少。通过与命令行侦听器窗口交互,把工具安装为按钮,提取操作记录为脚本命令,可以大大的提高工作效率;
MaxScript可以足够充分的能力完成复杂的程序任务,因为它拥有矢量、矩阵、四元数等数据类型进行代数运算。MaxScript非常适合大数量对象的工作。例如编写复杂的选择程序,构建星空
MaxScript与3ds Max界面的整合性非常好。可以把脚本打包进工具面板的卷帘窗或非模块化的窗口里,或者与工具条的按钮、菜单、四元菜单或快捷键相关联。MaxScript还可以扩展或替换物体、修改器、材质、贴图、渲染或大气效果的用户界面。还可以创建自定义的网格物体、修改器和渲染特效用户界面。这种良好的整合可以使技术部门针对特定任务用脚本编写工具,使艺术家或动画师可以象在原有的3dsmax用户界面中那样通过点击式操作使用脚本工具
MaxScript支持格式化文本和二进制数据的输入和输出。所以,可以直接从3dsmax场景文件中直接输出文档的结构报告,或者从其他程序管理软件中读取包含场景布局、名称、贴图细节等内容的文件。外部文件和目录访问功能使MaxScript十分适合执行数据收集和分析、形成数据结构和渲染文件等的报告,通过内置的命令行和壳的支持与其他程序或脚本语言进行交互访问 。
MAXScript还可以被用作高层场景的输出工具。通过输出包含物体生成命令的脚本,使输出对任何高层3dsmax结构的应用成为可能。MaxScript甚至可以用来把max高版本文件转换到低版本的max中去,而不必求诸第三方数据格式
入门部分 一 认识Maxscript界面 打开脚本编辑器 打开脚本侦听器 Mini脚本侦听器 在侦听器中查看操作记录 在操作记录中提取脚本 编辑器中运行脚本 数字键盘回车单行运行或运行被选择语句 Ctrl+e 执行整个脚本
二入门实例 书写规则
书写形式非常自由,对大小写不敏感,一个表达式结束后进行换行时不需要加分号 2+5 4*6-7-9 a+b与A+B是一样的
换行,并可以在任何操作符后面打断语句换行,MaxScript会读取代码直到读取一个完整的表达式 a+b*c /d - e + f * g / h a+b * c / d - e + f * g / h 错误的换行 a + b * c / d - e +f * g / h 用斜杠换行 a + b * c / d – e\ +f * g / h
如果在同一行中书写多个表达式,用分号分开 1+2;2^3;sin 30
注释,使用双减号 如 Sphere()--创建一个球体
变量赋值
变量赋值的语法 变量名=变量值 注意变量的名的书写由下划线或英文字母开头,可以包含任意数量的英文字母或数字 变量值可以是一个数,字符串或表达式
给变量赋予一个字符串 mystring = "This ismy string." 通过输入变量引用变量的值 Mystring 为这个变量重新赋值 mystring = "This isnot your string." Mystring
基本的运算 35.0*2 Pi Pi系统预定义的全局变量 4/3*pi*2.5^3 字符串操作 a=”MaxScript ” b=”is a freeform language” a+b
随机数的生成 Random 1 100 Random[0,0,0][100,100,100] 自运算 X=5 X=x+1 可以写作x+=1 加减乘除都可以使用这种快捷方式 X*=2 x-=2 x/=2
对物体进行操作 Box() b=box() b=box length:20 width:20height:20 对指定的物体进行操作 $box01 Select $box01 改变物体颜色 b.wirecolor=green b.wirecolor=color 0 0255 b.pos=[0,0,15] b.scale=[1,1,2] move b [0,0,-15] scale b [1,1.5,1] rotate b 30 z_axis rotate b -30 [0,0,1]
修改物体特有的属性 b.height=30 b.width=10 b.length=10
查看物体属性的两种办法 Showclass() 使用方法 Showclass “box.*” 可以在脚本侦听器窗口中显示 box类的属性 Box : GeometryClass {10,0} .height : float .length : float .lengthsegs : integer .width : float .widthsegs : integer .mapcoords : boolean .heightsegs : integer ShowProperties()
使用方法 showProperties b 需要针对专门物体
复制物体
Copyb 复制时可以修改一些通用属性,如位置,旋转,线框颜色 Copyb pos:(b.pos+[0,10,0]) wirecolor:green
使用循环语句进行阵列 P=b.pos Fori=1 to 50 do ( P.x+=50 Copy b pos:p ) -------------------------------- For i=1 to 50 do ( P.x+=50 C=Copyb pos:p c.height=50+25*sin(i*360/8.0) ) --------------------------- animateon
Fori=1 to 50 do ( P.x+=50 at time i (C=Copyb pos:p c.height=50+25*sin(i*360/8.0) ) )
创建星空
在+400和-400的空间中创建 用 showclass()查看球类的属性 Fori=1 to 500 do ( P=random [-400,-400,-400] [400,400,400] Sphere radius:(random 10 1.0) segs:4 pos:p )
定义函数 FnstarField size segs num:100 = ( For i=1 to num do ( P=random (size*[-1,-1,-1]) (size*[1,1,1]) Sphereradius:(random 10 1.0) segs:segs pos:p )
) 函数调用 Starfield500 4 num:300
MaxScript的基本结构——表达式 什么是表达式?在各种计算机语言的相关书籍中都有对其概念的介绍,尽管措辞不同,但都有一个共识,那就是——表达式是可以对其求值的任何语句。 在MAXScript中的任何结构都是表达式,都产生值,这种基于表达式的结构使MAXScript的书写非常简单,自由,而且十分直观。只要是可以书写<表达式>的地方,就可以书写MAXScript的任何结构。 我们用if结构来说明。 例如: if a> b then print c else print d 我们可以把这个if表达式写进赋值语句中: x = ifa > b then c else d 而if结构和赋值语句本身也是表达式,所以又可以把它们嵌套在一个if结构中: x = if(if a > b then c else d) < e then f else (g = 23) 还有一个例子是块表达式。块表达式就是用圆括号括起来的一连串表达式,在语法描述中被标记为<块表达式>。 ( printa printb if a> b then print "the big a" ) 块中的表达式用换行分割,你还可以把这些表达式写到一行里,用分号(“;”)隔开: printa; print b; if a > b then print "the big a") 块表达式本身也是表达式。它按顺序执行执行每一个子表达式,然后把最后一个表达式的值作为块表达式的值,一定要记住这一点。
Number String BooleanClass Point3 Matrix3 Quat Array
1. Number MAXScript有两种数的类型:单精度浮点数和32位整型数。 这两种数的类型相当于max中使用的浮点数和整数类型。 123 123.45 -0.00345 1.0e-6 0x0E .1
abs<数> 求绝对值,返回类型与给定的参数一致 mod<数1> <数>。模运算,即第一个数被第二个数除后的余数,返回结果为浮点数 ceil<数> ceiling是上限的意思,返回大于或等于给定数的那个最近的整数,返回类型总是为浮点数,如ceil 15.1的结果为16 floor<数> 求小于或等于给定数的那个最近的整数,返回类型总为浮点数.如floor 1.5的结果为15 三角函数 MAXScript中还有标准三角函数,角度以度为单位,返回结果为浮点数。这些三角函数是: acos<数> --反余弦函数 asin<数> --反正弦函数 atan<数> --反正切函数 atan2<数> <数>--反正切函数的另一种形式 cos<数> --余弦函数 cosh<数> --双曲余弦函数 sin<数> --正弦函数 sinh<数> --双曲正弦函数 tan<数> --正切函数 tanh<数> --双曲正切函数 exp <数> -- e的指数函数 log<数> -- 以e为底的自然对数 log10<数> --以10为底的常用对数 pow<数> <数> --指数函数 sqrt<数> --平方根函数
随机函数 random<数> <数> --随机函数,返回值的类型为第一个参数的类型 seed<数>--随机种子函数 角度转换函数 degToRad<数> 把度转换为弧度,结果总为浮点数 radToDeg<数> 把弧度转换为度,结果总为浮点数
2. String
字符串是用括号括起来的一系列字符 如: s1= "Truth, Justice And The American Way" s2= "The American Way" s3= "All That Stuff" 用.count属性访问字符个数 访问某个字符用索引数(下标) 如 s1[3]
3. BooleanClass
字面常量 true false on–-相当于true off-- 相当于false "true"as booleanClass "false"as booleanClass "on"as booleanClass "off"as booleanClass 运算符 not<布尔值> 如果布尔值为false返回true,为true则返回false <布尔值> and <布尔值> 如果两个布尔值都为true则返回true,否则为false <布尔值> or <布尔值> 如果只有其中一个为true就可返回true。 And和or运算是非严格的。就是说,第一个布尔值就有可能决定整个运算的结果。 在一个and表达式里,如果第一个操作数如果为false,则结果必定为false,因此,第二个操作数就不再被执行 在一个or表达式里,如果第一个操作数为true,则结果必定为true,因此,第二个操作数就不再被执行 这种非严格的运算特性节省了运行时间,例如你想计算sin a,但是变量a的值有可能为undefined,
Point3和Point2 坐标是描述空间位置的数据类型,在MXS程序中被大量运用,如物体坐标、点的坐标、位图像素的坐标等等。二维坐标和三维坐标的书写方法: [320,240] -- 二维点 [10,20, 30] -- 三维点
a=10 b=45 [10,20, 30] [sina, 2 * b, a^2 + b^2] -- 包含表达式的坐标 讲述下 Normalize() Dot cross
Matrix3 这个变换矩阵是一个3D齐次矩阵,主要用于处理物体的坐标系统和变换信息。其实它的原型是4 x4矩阵 构造语法: matrix3<row1_point3> <row2_point3> <row3_point3> <row4_point3> matrix3[1,0,0], [0,1,0], [0,0,1], [0,0,0] matrix3[0,-0.707107,0.707107] [1.41421,0,0] [0,1,1] [0,0,0]
Quat(四元数) 四元数常用于存储3ds Max物体的旋转信息。一个四元数由四个分量组成,一个实数标量部分,指定旋转的角度,另外三个指定一个虚拟的矢量,用来定义旋转轴。 MAXScript中的旋转是遵循右手定则的,显然角度为正数的旋转是逆时针的,与3ds Max UI中的习惯是一致的 构造器: quat<x_float> <y_float> <z_float> <w_float> x、y、z组成矢量部分,w是围绕矢量旋转的角度 quat<浮点数角度> <point3旋转轴>
Time 时间是MAXScript用来处理动画时间的。时间的解析单位为tick,解析度为每秒4800个tick,每帧160ticks。你可以使用ticks,帧,h.m.s或者标准化时间工作。 你可以混合数和时间进行运算。运算时,数总是被解释为帧数,如果为浮点数,则对应的帧为小数帧。 数在MAXScript内部总是被转换为tick为单位的时间再进行计算。 你可以数和时间值进行数学或比较运算,用as运算符进行时间和数之间的类型转换。 字面常量示例: 2.5s --2.5 秒 1m15s --1分15秒 2m30s5f2t--2分30秒5帧2ticks 125f--125帧 18.25f --18.25帧 1f20t--1frame20ticks 2:10.0 --2分10秒0帧 (SMPTE) 0:0.29-- 29帧(SMPTE) 0.45n -- 标准化时间
Array 组是一个经过排序的值的集合,组中的任何一个元素都可以是任何数据类型。你可以直接在程序中书写组常量,或者用MXS提供的组函数建立一个组。组常量有两种表达方式: #(<expr> { , <expr> } ) #()-- 空组 例如:
#(1,2, 3) #() #(1,"foo",#(1.2,-4,#fred),[1,2,3]) – 注意组中包含一个嵌套的组 在组常量中包含表达式,如: a=10 x=45 #(1,sin x, a * 2.3) 输出: 10.0 45 #(1,0.707107, 23.0)
控制程序流程 If 表达式
If表达式根据一个判断表达式的结果来确定是否执行一个表达式。 If表达式的语法有两种形式: if<表达式> then <表达式> [else <表达式> ] if<表达式> do <表达式> ifa > b do (print d; print e) a= (if d == 0 then 0 else a / d)
Case表达式的语法是:
case[ <表达式> ] of ( <条件> ) 其中,<表达式>是一个测试表达式,<条件>是一系列被标记的表达式: <因子>: <表达式> default:<表达式> 例如: new_obj= case copy_type.state of ( 2:copy $foo 3:instance $foo default:reference $foo )
For循环
for <变量名> ( in | = )<序列> ( do |collect ) <表达式> 其中<变量名>是访问<序列>时所使用变量的变量名,为了方便描述,我们把这个变量称为循环变量。循环变量从<序列>中依次取值。序列是一个值的集合。
fori = 1 to 10 do print i -- sequence numbers foritem in table1 do x = x + item.height -- sequence an array fort in 0f to 100f by 5f do sliderTime=t -- sequence time (given as frames, here) bigones= for obj in $box* -- you can sequence pathnames! whereobj.height > 100 collect obj
While和 Do循环 While和 Do循环都是用于重复执行一个表达式,直到判断表达式的结果为false终止。While和 Do循环是比较相似的。 语法为: do <表达式> while <表达式> while <表达式> do <表达式>
只要while <表达式>的结果为true,两种循环方式就一直重复执行do <表达式>。因为do形式的循环判断表达式在后,所以,至少会执行一次;而while形式的循环开始就要执行判断表达式,所以,有可能一次循环都不执行
界面编辑 界面的生成主要有三种办法 1. 用createDialog()生成窗口,必须有卷帘窗定义才可生成 2. 用newRolloutFloater()生成浮动窗体框架,然后添加卷帘窗 3. 用Utility()在工具面板中生成窗体框架,然后添加卷帘窗
窗口的主要构件为Rollout。 Rollout的语法:Rollout 变量名 标题字符串
在Rollout中添加局部变量,鼠标工具,函数定义 界面元素的常用属性
一个最简单的窗口生成 Rollout MyFirstUI "我的第一个窗口" ( ) createDialogMyfirstUI height:200
加入界面元素 Rollout MyFirstUI "我的第一个窗口" ( Button boxBt “Box” Button sphereBt “Sphere” ) createDialogMyfirstUI height:200
销毁窗口DestroyDialog() 加入界面元素 Try DestroyDialog MyFirstUI catch()
Rollout MyFirstUI "我的第一个窗口" ( Button boxBt “Box” Button sphereBt “Sphere” ) createDialog MyfirstUI height:100
加入事件 On boxbt pressed do box() On sphereBt pressed do Sphere ()
添加微调器修改物体属性 需要声明局部变量
Try DestroyDialog MyFirstUI catch()
Rollout MyFirstUI "我的第一个窗口" ( Local b,s Button boxBt “Box” Button sphereBt “Sphere”
Spinner xposSpn “x_offset” range:[-999,999,0] Spinner HSpn “BoxHeight” range:[-999,999,25]
On boxbt pressed do Undo on B=box height:hspn.value On sphereBt pressed do Undo on S=Sphere pos:[xposspn.value,0,0] On xposSpn changed val do Ifs!=undefined do s.pos.x=val On hspn changed val do Ifb!=undefined do b.height=val
) createDialog MyfirstUI height:100 让界面好看些 group "Create" ( Button boxBt "Box" width:60across:2 Button sphereBt "Sphere" width:60 ) group "Parameters" ( Spinner xposSpn "x_offset"range:[-999,999,0] Spinner HSpn "BoxHeight"range:[-999,999,25] )
其他常见界面元素 Label Checkbox Checkbutton
把生成星空的脚本生成界面 try destroyDialogStarfieldUI catch()
Fn starField size segs num:100 = ( For i=1to num do ( P=random (size*[-1,-1,-1]) (size*[1,1,1]) Sphere radius:(random 10 1.0) segs:segspos:p )
)
Rollout StarFieldUI "StarField" ( spinner szSpn "Space Size" range:[-100000,100000,400] spinner numSpn "Number" range:[1,10000,500] spinner segsSpn "Segs"range:[1,50,4]
button StarFldBt "Create StarFiled" on StarFldbt pressed do undo on starfield szspn.value segsSpn.valuenum:numSpn.value )
createDialog StarFieldUI
加入浮动窗口中:
nfloater=newRolloutFloater "Starfield" 200300 addRollout myfirstUInfloater
打包为宏脚本
MacroScript Starfiled category:”LearnMs”buttontext:”星空” ()
如果时间够用,简述下列应用
曲线生成 Spl=newSplineshape() Addnewspline spl Addknot() 编辑多边形 拉伸 移动点,获取表面法线
创建一个球体,分布一些box
|