3D MAX脚本原理

 

3D MAX脚本原理

 分类:
三维图形建模(9) 
为什么要学习3D MAX脚本?
3D MAX Script是我迄今为止见过编程语言最自由的一种脚本开源环境,他的自由程度远远超过了Sun 的JAVA,她没有大小写的区分,以及固定的公式和程序工作流程树,MAX Script一旦被编写,人们就可以从任何一行进行代码的编译,不需要符合格式的束缚。而且MAX Script的功能相当强大。
详细的说明一下MAX Script功能到底有多强大:MAX Script是完全基于OpenGL开源以及VC核心制作出来的,而当今世界上任何一款CG制作软件也主要依赖这两点编写,也就是说如果MAX Script使用的好,我们完全有那个能力在3D MAX里面集成Maya的所有功能!这不光光是二次开发的乐趣,我想她更是一次CGer思维的革命,很多使用传统制作方法难以完成的任务,在使用了MAX Script后就会变的非常简便、快捷!
我认为想要学好MAX Script不在于你前面有多少编程的基础和学习经验,关键在于是否能很好的理解MAX Script里面每一个字串符的使用方法和他的作用。举个很简单的例子:“()小夸号”和“[]中夸号”有什么区别呢?他们可以在什么地方使用?两个符号可以结合在一起使用吗?怎么结合在一起使用更加科学合理?其实就是这样的几个问题解决好了,你甚至可以模仿出一些美国大片级别的视频特效!(以上的几点我会在接下来的杂志中进行详细讲解)
第一讲:MAX Script基础片
认识MAX Script界面:





按下键盘上的F11,或者按照图示单鸡按钮,即可弹出MAX Script窗口



第一讲,第二节:基础应用片:
用实例讲解MAX Script的基础符号.

很多人感觉MAX Script很难,其实我觉得他们觉得很难的原因是因为基础没有学好,而我认为的MAX Script基础就是符号,倘若能把几个基本符号理解的很好的话,相信很多问题就可以迎刃而解. MAX Script真的不难,关键是在于你对他的理解. 

现在我开始讲解MAX Script中最基础的符号,希望大家认真学习,因为在这一节学好了,接下来的学习就会显的很轻松

MAX Scrip中:使用―― $、””、()、[]、和. 的理解。
接下来我向大家演示两个例子,并且在此例中向大家讲解以上几个符号的使用方法,和如何理解.
首先,来看一张效果图:比较抽象些,只是表达个意思

一张大数量,宏观城市景观,共15376个BOX,怎样制作速度最快?
最简单的方法就是――制作许许多多个BOX,然后一个一个的对他们进行高度、大小设置(― | | |)―凸―)~_~)――_―)。。。不过这个。。这个这个。。呵呵,冷不?好冷。。。
而我使用了MAX Script后,只要一句就可以高定! 








1:随便拉一个BOX
2:阵列一下(我的是30*30一共900个BOX)
3:选中所有物体!写入脚本
4:渲染,完成局部的制作。
我使用的语句是:for a in selection do a.height=(random 0 10)
有人说:“老师,你写的那句话是什么意思?”好,我现在说明一下。
首先是:for a in selection。什么意思?for a in selection是一个固定搭配,表示“被选择的物体”而被选择的物体就是用――a来表示。
然后是――do,这个不用多解释了,“做,做一件事情” 被选中的物体去做一件事情;那是去做什么事情?这就是代码运算的结果――a.height=(random 0 10)
a.  height=(random 0 10):
表示被选择的物体――a的 高度等于(0到10之间的一个随机数)
random是随机的意思; 0 10表示范围;height表示物体的高。他应该=…………

有了上面的这些解释,下面我们返回这一讲的主题:
仔细观察上面所给的代码,首先我们发现一个有趣的表达式a.height,很有意思,a表示已选择的物体,而height表示物体的高度,而者怎么联系到一起去的呢?原来是中间的一个 . 号。这个符号是关键,如何理解?你可以把他理解成――“什么什么的属性”这个后面再跟具体属性,比如这个a.height,他的意思是说a的高的属性。然后再继续接表达式。a.height=什么什么(一个可选的数)
再仔细观察,有没有发现什么?呵呵――小夸号!小夸号()怎么理解?不能说理解了,应该说怎么使用,在这里小夸号的使用方法为――“(加可选的客观数值,或者运算表达式)”向在这里,小夸号()里面就是一个表达式,他的取值范围在0到10之间。连接上前面的a.height,意思就是“被选择的物体高度在0到10之间随机变化。”讲到这里,你已经豁然开朗了吧

其实原理是很简单的,关键在于你能不能想的到。
第一讲第三部分:实例2:

完成了上一个例子.好,有人又说了:“丁,怎么样把那些房子都做成不一样的颜色?”最简单的方法就是一个一个的点击物体,然后一个一个的对他们的线筐颜色进行调整。(― | | |)―凸―)~_~)――_―)。这个这个。呵呵。。倘若想使用MAX Script,仔细想一下,其实这也是很简单的,学会一个属性命令――wirecolor就可以做到了,这个属性命令我是在――亓鑫辉老师的公开讲课中学到的。在此非常感谢火星培训部的亓鑫辉老师!也希望大家支持亓鑫辉老师! 


 
1:这里有100个BOX,选中他们。
2:然后脚本
3:然后完成,我这里有100BOX他们的颜色都是不一样的。

来看一下代码:for a in selection do a.wirecolor=color(random 0 255) (random 0 255) (random 0 255)
有人说:“老师,什么意思?”在这里for a in selection不说了,do 后面跟的是a 及wircolor两个关键词。Wirecolor是线筐颜色的意思,中间 . 号连接表示a的线筐颜色,后面是一个新的表达式:color
现在我来说一下color的使用方法。
Color+RGB是理论表达式,RGB都用0到255之间的数字表示,好了这样就有人写出了这样的表达式:Color 50 250 150。回车执行代码后,发现是错误的。而我就觉得这些人在我前面说的内容还是没有理解。Color后面既然想表达3个数字分别对应RGB,能这样表达吗?是3个数字,不是一个数字。50 250 150,这是什么值?虽然可以表达RGB,但是格式不对。前面的内容我已经详细的讲解过了一点了:小夸号()的使用方法,小夸号()里面用来表示一个具体的数值。所以在这里,写成Color (50)(250)(150),就显的更加合理
跟上前面的表达式连起来看一下。for a in selection do a.wirecolor=color(random 0 255) (random 0 255) (random 0 255)显然,我把已选择的物体的RGB都在0到255上面进行随机取值,这样就可以做到颜色都不一样了。 



以上是MAX Script经常出现的几中情况错误,仔细观察。红色的文字告诉你是什么地方出了问题。
1:-- Error occurred in a loop
-- Frame:
-- a: $Box101
-- Argument count error: Color wanted 4, got 1
这个提示应该还是比较好理解的,他告诉你BOX101没有办法按照代码被赋予正确的线筐颜色。而且也告诉了你是在“Color”这一指令后出的问题,很明显这个就说明Color的表达有问题。
仔细观察,发现错误语句中的Color表达是:Color(0 255 255)。而实际上3DMAX Scrip中的――()小夸号,里面只能存一个固定的数值,0 255 255虽然是“RGB”色彩代码的表示方法,但是不符合语法,小夸号内必须存一个固定的数值,在MAX Scrip中“Color”指令后确实是要跟三个数字来表达R、G、B的,此时我们使用3个小夸号:()就比较合理了。
2:-- Syntax error: at keyword parameter, expected name
-- In line: for a in selection do a.wirecolor:color 
出错了没有关系,MAX Scrip中的错误是最好排除的,仔细观察红色的提示代码,要认认真真的找下在什么地方出错。他告诉你咯,这个“for a in selection do a.wirecolor:后出现了错误,”意思是这个“等于”号不能这么打,而输入“=”就比较合理了。(我上是用“冒号”代替“等于号”的)
3:我胡乱打的虾米…...看看他告诉我什么:undefined。意思是有定义。
解决办法比较传统,入下:“没有定义的变量或者名称”=*即可(*可以是任何数值或者表达式,总之必须是一个已经被定义过的语句。)
4:这是在MAX Script中一个比较典型的错误,如何判断一个有效的表达式。MAX Script中运行代码的时候,是从上向下依次逐行运算,仔细观察,发现错误代码为:
a+b/c
+d
MAX Script在进行运算的时候,在第一行,会把他当成a+b/c进行运算然后直接输出结果,执行第二行的时候,就会提示“+号”使用错误,这是一段断开的代码,没有从头到尾的连续性。VC 和JAVA在这方面都使用了――{}大夸号来表示一段完整的程序代码。然后一段代码中还能继续使用{}大夸号继续定义子程序树。在MAX Script,加上反斜杠\就显得比较合理了
a+b/c\
+d
这样效果就等同于a+b/c+d.。如果想要把几条表达式合并成一行,也可以使用分号隔离.比如如图.
 第二讲:第一节:学会使用语句 : showProperties() 
顾名思义,Showproperties意思就是显示物体的信息,为什么要先学会使用这个表达语句呢?譬如,在3D MAX里面有个自带AEC插件,做树木用的,(尽管效果很假)。当我在场景中间创建了一个树木。想用脚本来控制他的一些参数,但是我也不知道他有那些参数。怎么办?这个时候Showproperties命令就派上用场了~
3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
当我把创建的这个树选中,输入showproperties$回车,立刻白色代码执行区显示出了这个物体的所有属性。(其中符号 “$” 表示别选中的物体,意思是in selection,但是二者不等同,$更倾向与一个表达试,而in selection更倾向与一个命令)譬如height表示他的高度,seed表示他的随机种子数等。仔细观察,会发现前面都有一个 “.”(点)这个点前面也都省略了一个”$”.倘若把$加上,相信大家一定一目了然了~
接下来我们就可以自由的使用这些命令了,利用第一讲的知识,我们可以很快的做出许多完全不一样的树~(如图:利用random命令,让他们的高度和种子随机变化,很简单的例子,第一期有详细的介绍.)
小结: 利用Showproperties命令,查看物体有那些可编辑属性参数,然后就可以使用命令对需要修改的参数进行控制了~
第二节:2.1.打开 宏记录:
你在3D MAX 里面创建了一些物体,或者对一些物体属性进行了修改,做的这些事情都会被3D MAX用脚本语言的形式给记录下来,所以,打开了宏记录我们就可以在脚本代码里面看见自己都是怎么对MAX进行操作的.但是宏记录也有不足的地方,那就是不是所有的操作行为都能被3DMAX的宏记录,记录下来.眼下灵活的使用宏记录,是学好3D MAX脚本的关键所在~
3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
如图,这就是打开3D MAX宏记录的方法,在书写脚本的窗口上端的MacroRecorder下拉菜单中勾选Enable起用勾选,这样就打开了3DMAX脚本的宏记录.图中是我在世界坐标系中央创建了一个BOX时候被记录下来的命令.
Box lengthsegs:1 widthsegs:1 heightsegs:1 length:29.8779 width:33.3667 height:48.5474 mapcoords:on pos:[-13.0051,-19.3169,0] isSelected:on
前面三句lengthsegs:1 widthsegs:1 heightsegs:1分别表示长宽高上面的片段数.接着就是长宽高的具体数值,然后pos后面中括号里面是XYZ轴的坐标值.接着是一个状态显示参数: isSelected:on表示这个物体正被选中的状态~
2.2.:执行一段代码的正规操作
现在我们要开始接触更多的MAX Script语言代码了,这意味着我们今后要执行什么命令不会象第一期中单句单句执行的那么简单了,我们将要执行大段大段的代码,而要执行大段大段的代码就不要想按下回车了事~
3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
看看这张图吧,由于直接用回车进行代码执行,导致了只执行了一行代码,白色的代码执行区显示出了红色的出错提示语句,而正确的代码执行规则是如图所示:首先保存成MAX Script 脚本的*.ms文件,然后再使用Run Script按钮执行。
2.3:小括号又一理解思路:
在前面第一期我解释过,小括号里面是来表示一个数值的,在这个,我讲一下小括号的又一理解思路,意思是:在小括号内写的是一段完整的可执行的MAX Script代码,有人用过JAVA的一定知道,在JAVA里面是大括号 { } ,大括号内括的是一段完整的可执行代码 “{”表示程序开始,“}”表示程序结束,在MAX Script里,小括号也是这么一个用法。


3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
Mental Ray大家都用过的吧。
3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
2.4添加控制菜单
通过这样的几句话,就完成了控制面板的添加,老规矩还是来解释一下是什么意思。
代码是这样写的哟
utility Publicname "标题名称" 
(
button Publicname "enjoy 3D MAX" pos:[12,20] width:140 height:30
)
什么意思?第一句有一个“utility”语句,他的意思是指在上面图中MAX Script面板里面那条下拉菜单里面添加一个选项。这个语句怎么用?我来说一下:首先他的固定语法是:utility + name +“标题名称”, 中间name指的是程序内部的名称,计算机运行代码的时候,他要知道你新添加的东西叫什么名字,才能执行这个东西下面的子代码,所以这个name只能是英文,他表示:你新添加的面板的名称,而后面“标题名称”就是标题名称了,观察下上面的图就明白了,我也不多说咯~
我们继续往下看:
button Publicname "enjoy 3D MAX" pos:[12,20] width:140 height:30
这句,首先button(按钮)也是一个他的固定语法也是和utility一模一样的:button + name + “标题名称”,这里我给的标题名称是:"enjoy 3D MAX" 。
最后这段代码在第一段小括号内还少一句话才显的完整——on Publicname pressed do意思是:当Publicname按钮被按下的时候do一件事情。(有关于do的语法第一期有讲)至于做什么事情,我们可以紧接着前面的代码继续一个小括号,在这个小括号内书写一段完整的可执行代码,作为“do“的具体内容
utility Publicname "标题名称"
(
button Publicname "enjoy 3D MAX" pos:[12,20] width:140 height:30
on Publicname pressed do 
)
)
--这里一对小括号内书写一段完整的可执行代码,用语承接上文中“do“的内容

关于button按钮语句,用客观一点的公式来表达应该是这样:
button <name> [ <caption> ] [ images:<image_spec_array> ] \
[ toolTip:<string> ] 
我不能把什么东西都解释完了,要不然大家的思想会变的很局限,所以关于按钮。我做了一个比较有意思的东西,也希望大家自己能够思考一下
3dmax脚本教程 2 - 九荣 - 鹏鹏的博客
这个东西比较有意思,一个渲染按钮,制作起来也比较方便,单击他后,原来按钮的位置就会被渲染出来场景中的物体。
大家仔细考虑一下我这个按纽是怎么制作的,其实方法很简单关键看你能不能想的到。
代码我也公布给大家,想不出来的时候自己可以对着这代码看一看思路。
rollout image_button_test "Image Button"
(
button theButton "Press To Render!" width:200 height:200
on theButton pressed do 
(
theBmp = render outputsize:[200,200] vfb:off
theButton.images = #(theBmp, undefined, 1,1,1,1,1 )
)
)
createDialog image_button_test 210 210

 

第三节:实例:飞船火焰制作
思路:创建大气物体,使用环境火焰特效,进行制作,并打开宏录,记录制作流程,最后结合前面所学的命令进行制作优化。
3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
创建大气物体——圆柱,3D MAX的宏记录记录了下他的创建过程:
CylGizmo radius:15.6403 pos:[0.166849,0.496013,0] isSelected:on height:44.8379
当然我们知道很多都是没有用的废话,经过修改后得到
CylGizmo radius:10 height:33
把过长的浮点修改整,去掉一些类似于isSelected:on的废话 ,pos[]语句也被删除了,pos[]是表示物理坐标位置的语句,如果被删除了,那么物体会自动的被创建在[0,0,0]世界坐标轴中间。
3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
宏记录的时候记录的不是很完全了,如图粉色的部分有用的只有这两句其中addAtmospheric (Fire_Effect ())表示给物体添加Fire_Effect这个大气特效的意思
CylGizmo radius:10 height:33
addAtmospheric (Fire_Effect ())
这就是宏记录后被我选择的语句,其中addAtmospheric (Fire_Effect ())表示添加Fire Effect这个大气特效的意思,但是添加归添加,要把Fire Effect这个大气特效添加给哪个物体?通常我们会在环境特效编辑器里面拾取,但是这样的拾取在3DMAX里面是不能被宏记录的,如果想要让Fire Effect这个特效指定给特定的大气Gizmo的话,就要用到下面这句话
appendGizmo (Fire_Effect ()) CyLGizmo 01
意识是:把Fire Effect这个特效指定给 CylGizmo 01。语言是这个意思了,但这样表达不好,因为他只能使用一次,在这里CylGizmo 01是一个物体,他不是变量,所以以后的代码再出现CylGizmo 01就不能被循环使用了。
为了避免这个现象,我们得给这个大气Gizmo设置一个变量
这个变量这样写:
wy=Fire_Effect ()
GZM=CylGizmo radius:10 height:33
使得一个 Fire Effect 特效等于变量wy ,由变量wy替代,大气Gizmo由变量GZM替代。加上3DMAX的宏记录就有了以下代码
utility Cosmicbrid "飞船尾焰"
(
button Cosmic "飞船尾焰" pos:[12,20] width:140 height:30
on Cosmic pressed do --当按钮按下时候做 ↓↓↓
(
GZM=CylGizmo radius:10 height:33 ---创建园柱形大气线框
wy=Fire_Effect ()
addAtmospheric wy ---增加火焰特效
appendGizmo wy GZM——将火焰特效赋予给相应的大气Gizmo


3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
基本上这样就创建了一个尾焰,下面的事情就需要我们来对他进行参数设置,首先看看上面的图。先来将第一个color面板:
这里有3个颜色选择Inner Color:内部颜色 , Out Color: 外部颜色,Smoke Color: 烟雾颜色。Inner Color:内部颜色是火焰内部的颜色,飞船尾焰内部应该是很亮的,到了外部应该是蓝色的(氢气燃烧显淡蓝色的火焰)
Shape: flame Type:Fireball : 火球 。
Stretch 拉伸 ,Regularity 规则性
Stretch 拉伸:这里数值越大拉伸的越厉害,飞船应该是比较长的火焰,所以可以设置的高一些。
Regularity 规则性:当他小于 1.0,将压缩火焰,使火焰更短更粗。 当他大于 1.0,将拉伸火焰,使火焰更长更细。
Characteristics: 特性 Flame Size : 火焰大小,单位和系统默认单位一样。 
Density:密度,火焰的密度大小。 Flame Detail 火焰细节,飞船尾焰的尾处有很多类似“须须“形状的火焰,很细,这个值调的越高,那么这种效果就会越明显。
Samples:采样数,数值越大采样越大,效果越好,渲染时间越长
进行了一下颜色的调节,完整的记录下了宏记录,这是调节到图中所给颜色所记录下的宏记录
(getAtmospheric 1).Inner_Color = color 153 199 255
(getAtmospheric 1).Outer_Color = color 29 56 255
(getAtmospheric 1).Smoke_Color = color 206 240 248 
你可以把他插入到你的代码第二节中(按钮按下后发生的事件),并且可以通过使用一个Random命令(第一期有非常详细的介绍)进行色彩上微弱的变化调节,这样就可以做到每次生成的Gizmo的颜色都不一样了。
3.2使用Showproperties和Showclass命令参看 Fire Effect具有的属性。
3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
可以发现,这些数值都是和面板上面相对应的。
插入卷帘:
rollout property "Shape" width:160 height:150
(
)
on Cosmicbrid open do
(
addRollout property rolledup:true
)
这一段完整的卷帘代码,用到了一个新的命令——rollout卷帘命令。固定语法不说了,后面是他的宽和高,接下来的一对小括号里面书写一段完整的可执行代码。这样虽然没有问题了但是执行代码这样的卷帘他不会被显示出来。还要添加一段:
on Cosmicbrid open do
(
addRollout property rolledup:true
)
他的意思是“Cosmicbrid ”这个面板必须打开,添加“property”这个卷帘。后面rolledup:true表示允许添加到Cosmicbrid 这个面板当中。(我在这个程序中的主面板的名字是Cosmicbrid ,大家在最早定义自己添加的面板的时候起的什么名字,在这里就用什么名字,或者你想把这个卷帘添加到别的面板当中去,那个面板叫什么名字。)
3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
把这段代码接到后面,发现并不能运行。仔细观察一下,发现代码分上下两段,上面一段代码在结束的时候,有一个小括号作为结束命令,(红色加重显示的地方)这样导致了下面一段没被包涵到上面的一整段代码中,所以就没有能被执行下来了。
这样把那个小括号移到下面来,作为整段程序的最终结束语句就可以了。
添加控制滑竿:
这里我演示只一个哦,其他的留给大家自己做,呵呵,我把所有的都做了就不太好玩了
在刚才
rollout property "Shape" width:160 height:150
(
)
的小括号中,输入以下语句:,
spinner spn1 "Stertch拉伸" range:[0,40,1] type:#float scale:0.1
on spn1 changed val do
wy.Stretch =spn1.value
我们主要想对火焰的拉伸值进行控制,前面也已经使用了Classof命令查看了Fire_Effect的属性项目表,里面的拉伸选项是.Stretch: float。这里正好可以用上了。
来说一下这句话是什么意思,spinner spn1 "Stertch拉伸"。这里有是一个新的语句,spinner,他是一个滑竿的控制命令,语法同上(基本上3D MAX脚本都是这个语法:一个物体指令+ name +“标题名称”)后面紧接着了一个range:[0,40,1]命令,这个命令的意思是取值范围,我需要把火焰的拉伸在1—40之间随便选择,所以这里定义了range:[0,40,1],你也可以定义自己想要的值域。
接着on spn1 changed val do。这里和前面的button按钮语句差不多
(
button Cosmic "飞船尾焰" pos:[12,20] width:140 height:30
on Cosmic pressed do --当按钮按下时候做 ↓↓↓
(
on Cosmic pressed do,
on spn1 changed val do
上面的是按钮的,下面的是滑块的比较一下你就了解了,不多说了。两者的原理一模一样。
最后:wy.Stretch =spn1.value 前面我们定义过了一句话,不知道大家还记得不?wy=Fire_Effect ()这句话是给了Fire_Effect这个东东一个变量,让Fire_Effect等于变量wy,wy. Stretch意思就是Fire_Effect特效中的Stretch(拉伸)数值了,这个数值又跟了一个表达式子-- spn1.value。spn1是前面我们制作的滑块名字,他加上一个“点“后面跟value一词,意思就是说spn1的数值大小了。
连起来的意思就是:火焰特效中火焰拉伸的数值等于滑块spn1的数值大小。
3dmax脚本教程 3 - 九荣 - 鹏鹏的博客
执行后出现了问题
仔细观察,发现是Fire_Effect语句出了问题,他说Stretch这个语句没有定义?分析一下,首先Stretch的拼写是没有错误的,那就说明系统没有找到Stretch对应的具体变量,或者说,是什么东西的Stretch?而出错的地方表达式是wy.Stretch =spn1.value 说的是wy的Stretch。而上文有定义了wy= Fire_Effect。那是什么情况呢?
原来上文定义的wy= Fire_Effect只能给上文使用,当那一段代码结束的时候wy= Fire_Effect就不在成立了,那怎么样可以让wy= Fire_Effect这句话在全文都成立呢?其实,这个很简单只要在上文的wy= Fire_Effect前面加一个Global语句就OK了~意思是全局适用
 
 
 
 
 

旋转和缩放
在3DMAX中可以有3中方式来对对象进行旋转:Euler Angles(欧拉角) ,Angleaxis(角轴),Quaternions(四元素)
这里我只介绍Euler Angles欧拉角。其语法是:
rot_obj=eulerangles x y z
其中rot_obj是旋转变量,x ,y, z分代表各个轴向上旋转的角度。

 

1:addmodifier()语句
addmodifier()语句的作用是给场景中的某一个物体添加指定的修改器。譬如我们如果想给一个BOX添加一个UVW Map的修改器,就可以通过使用这个addmodifier()语句来实现。在3D MAX脚本字典中给出了它的标准使用方式为
2: distance() 用来计算2物体间的距离
标准使用方法为: distance <point3> <point3>
读高中的时候碰到一道超级爆难几何题,要用空间向量求2个点之间的距离,想了一个下午还没有头绪。呵呵,后来晚上急了,我就拿3DMAX的distance()语句把这道题目给搞定了。

addModifier <node> <modifier> [before:index]

 

图片点击可在新窗口打开查看


观察图例:第一个窗口中给出了一条为:
-- Unable to convert: Taper to type: Modifier 
的报错返回值,现在我们来分析一下这句话的意思:他说不知道 Taper修改器的子类别参数,也就是说在taper导边修改器下面有那一个参数起作用?导边的片段数?还是圆滑程度?在现阶段的3DMAX中,使用addmodifier()语句这个参数是不能省的。如果我们只想添加一个修改器,不想去设置这个修改器,那么我们就可以添加一个:() 圆括号来解决这个问题。
如图第二次,我们添加了一个() 园括号,里面不写任何表达试和参数,他表示:不修改任何修改器中的指令。

图片点击可在新窗口打开查看

 

如图,在第二段代码进行了编译后,就得到了这张图中的BOX了
在这里我要特别的说一下UVWMap修改器的添加,这个比较特别。

 

图片点击可在新窗口打开查看


观察如图的内容,第一个窗口返回了一段报错提示:
-- Error occurred in anonymous codeblock 
-- Frame: 
-- uvwmapping: undefined 
-- Type error: Call needs function or class, got: undefined 
他的意思是说uvwmapping这个语句没有定义,这是为什么?为什么uvwmapping会没有定义,仔细观察我们3DMAX的修改器下拉菜单如下图。

图片点击可在新窗口打开查看


如果我们直接用鼠标来添加这个UVWMap修改器,那么在添加之前,他的名称是——UVWMap,但在添加个一个物体后,他的名称就变成了UVW Mapping。也就是说我们书写表达式的时候要使用UVWMap被添加给物体前的名称——“UVWMap”,添加后如果想对这个修改器进行什么参数设置的话,我们就要使用他被添加给一个物体后的名字“UVW Mapping”。

图片点击可在新窗口打开查看


distance()语句的使用方法很简单只要在distance这个单词后根上2个<Point 3>坐标点就OK了。来举一个比较简单的例子:有两个坐标点:a = [10,20,30], b = [100,30.5,41.3],现在a和b已经代表的是2个坐标点的数值了,我们只要直接输入distance a b然后回车,系统就会返回点a和点b之间的距离了。

图片点击可在新窗口打开查看

 

 

图片点击可在新窗口打开查看
缩放scale
缩放场景中的一个物体可以通过scale语句来实现,例如,mybox.scale=[1,2,3] ,执行这个语句后,mybox在X轴向上不被缩放,在Y轴向上缩放2倍,在Z轴方向上缩放3倍。
图片点击可在新窗口打开查看
图片点击可在新窗口打开查看
1:addmodifier()语句
addmodifier()语句的作用是给场景中的某一个物体添加指定的修改器。譬如我们如果想给一个BOX添加一个UVW Map的修改器,就可以通过使用这个addmodifier()语句来实现。在3D MAX脚本字典中给出了它的标准使用方式为
addModifier <node> <modifier> [before:index] 
图片点击可在新窗口打开查看
观察图例:第一个窗口中给出了一条为:
-- Unable to convert: Taper to type: Modifier 
的报错返回值,现在我们来分析一下这句话的意思:他说不知道 Taper修改器的子类别参数,也就是说在taper导边修改器下面有那一个参数起作用?导边的片段数?还是圆滑程度?在现阶段的3DMAX中,使用addmodifier()语句这个参数是不能省的。如果我们只想添加一个修改器,不想去设置这个修改器,那么我们就可以添加一个:() 圆括号来解决这个问题。
如图第二次,我们添加了一个() 园括号,里面不写任何表达试和参数,他表示:不修改任何修改器中的指令。
图片点击可在新窗口打开查看
如图,在第二段代码进行了编译后,就得到了这张图中的BOX了
在这里我要特别的说一下UVWMap修改器的添加,这个比较特别。
图片点击可在新窗口打开查看
观察如图的内容,第一个窗口返回了一段报错提示:
-- Error occurred in anonymous codeblock 
-- Frame: 
-- uvwmapping: undefined 
-- Type error: Call needs function or class, got: undefined 
他的意思是说uvwmapping这个语句没有定义,这是为什么?为什么uvwmapping会没有定义,仔细观察我们3DMAX的修改器下拉菜单如下图。
图片点击可在新窗口打开查看
如果我们直接用鼠标来添加这个UVWMap修改器,那么在添加之前,他的名称是——UVWMap,但在添加个一个物体后,他的名称就变成了UVW Mapping。也就是说我们书写表达式的时候要使用UVWMap被添加给物体前的名称——“UVWMap”,添加后如果想对这个修改器进行什么参数设置的话,我们就要使用他被添加给一个物体后的名字“UVW Mapping”。
2: distance() 用来计算2物体间的距离
标准使用方法为: distance <point3> <point3>
读高中的时候碰到一道超级爆难几何题,要用空间向量求2个点之间的距离,想了一个下午还没有头绪。呵呵,后来晚上急了,我就拿3DMAX的distance()语句把这道题目给搞定了。
图片点击可在新窗口打开查看
distance()语句的使用方法很简单只要在distance这个单词后根上2个<Point 3>坐标点就OK了。来举一个比较简单的例子:有两个坐标点:a = [10,20,30], b = [100,30.5,41.3],现在a和b已经代表的是2个坐标点的数值了,我们只要直接输入distance a b然后回车,系统就会返回点a和点b之间的距离了。
图片点击可在新窗口打开查看3:if 和case of语句
if 表达式用于有条件地执行一个表达式,这个表达式以布尔测试表达为结果为基础
if语句的使用方法为:
if <expr> then <expr> [else <expr> ]
if <expr> do <expr>
  
第一个<expr>是测试表达式,他的值一定要是true或者false,如果在这第一个<expr>测试表达式这里返回的值是true的话,那么就程序就回继续执行then或者do语句,然后结束。而如果第一个<expr>返回了一个false,则后面的else语句将会被执行。
注意:如果表达式中没有else语句,或者你编写的是第二中 if , do的格式,那么在第一个<expr>表达试返回false后,系统会自动中断程序编译,并返回一个undefined值。
例如:
mybox=box()
if mybox.height==25 
then mybox.width=40 
else mybox.width=100
他的意思是创建一个名称为mybox的BOX几何体,如果mybox的高为25那么,他的宽就为40,否则宽等于100。
在这里要特别理解我前面说的那句话:第一个<expr>是测试表达式,他的值一定要是true或者false。怎么理解?来看看下面这短代码为什么出错了:
图片点击可在新窗口打开查看
第一个窗口中返回了一句为:
-- Type error: if-test requires BooleanClass, got: 25
的报错,他的意思是说第一个<expr>测试表达式需要布尔函数类(真或假)。自己的体会一下这句话的意思,然后我们再来看看第一个<expr>测试表达式的代码:
if mybox.height=25
你能看出什么问题吗?系统说缺少布尔函数类这句话为什么会缺少布尔函数类呢?其实问题出在这个“=”等于号上面,在这里,等于号没有判断性,不能判断这个BOX的高度是否等于25。如果我们想让一句代码有布尔性质,那么我们就要使用“==”双等号,他表判断。这样程序就可以判断第一个<expr>测试表达式的真或者假,然后,把真或假的值传递给下一句代码。
如图,第2个窗口中使用了“==”双等号,使得程序按我们的表意进行正确的返回。
接下来我们就刚才的“==”双等号的问题来谈谈if语句中比较表达式,他可以是以下形式中的任何一种:
== 等于判断
!=不等于判断
>大于判断
>=大于或者等于判断
<小于判断
<=小于或者等于判断
其实我们可以发现,只要牵扯到了有关大于小于号的表达式,他们就已经具有了判断性了。
此外If语句还可以作为表达式的一部分,例如:x if a>b then else d
3.2:case of 表达试
case of表达式你可以把他看做是if语句的一个高级形式,你可以给出一组条件,这一组条件中可以有多个测试表达试,还可以为这多个测试表达式分别去定义他们的返回值,相比较if语句而言,他的选择不会局限于then 或者else的概念,case语句的选择可以是多个的。
个人观点:3DMAX的if语句设计的没有C++的更科学,不管从格式上说,还是执行方式来说,或许C++中if语句的设计,是为了更适合大型的复杂程序使用,但总的来说3DMAX的if语句并不是一个很好的编程风格,尤其是让别人阅读你程序的时候,程序思路就显的不如C++那么整洁和清晰。
他的标准语法是:
case [ <expr> ] of ( <cases> )
在这里<expr>是测试表达式,<cases>是表达失序列,譬如:
<factor>:<expr>
default:<expr>
default是一个标记,在case语句中是可以进行选择的,如果你给出一个组的条件都没有一条能和测试表达式匹配,default可以选择继续case 表达式。如果没有default标记,而且前面的一组条件中也都没有一条和测试表达式匹配,case表达式将返回一个undefined值。
以下是一个小例子
图片点击可在新窗口打开查看
 
3:if 和case of语句
if 表达式用于有条件地执行一个表达式,这个表达式以布尔测试表达为结果为基础
if语句的使用方法为:
if <expr> then <expr> [else <expr> ]
if <expr> do <expr>
  
第一个<expr>是测试表达式,他的值一定要是true或者false,如果在这第一个<expr>测试表达式这里返回的值是true的话,那么就程序就回继续执行then或者do语句,然后结束。而如果第一个<expr>返回了一个false,则后面的else语句将会被执行。
注意:如果表达式中没有else语句,或者你编写的是第二中 if , do的格式,那么在第一个<expr>表达试返回false后,系统会自动中断程序编译,并返回一个undefined值。
例如:
mybox=box()
if mybox.height==25 
then mybox.width=40 
else mybox.width=100
他的意思是创建一个名称为mybox的BOX几何体,如果mybox的高为25那么,他的宽就为40,否则宽等于100。
在这里要特别理解我前面说的那句话:第一个<expr>是测试表达式,他的值一定要是true或者false。怎么理解?来看看下面这短代码为什么出错了:
图片点击可在新窗口打开查看
第一个窗口中返回了一句为:
-- Type error: if-test requires BooleanClass, got: 25
的报错,他的意思是说第一个<expr>测试表达式需要布尔函数类(真或假)。自己的体会一下这句话的意思,然后我们再来看看第一个<expr>测试表达式的代码:
if mybox.height=25
你能看出什么问题吗?系统说缺少布尔函数类这句话为什么会缺少布尔函数类呢?其实问题出在这个“=”等于号上面,在这里,等于号没有判断性,不能判断这个BOX的高度是否等于25。如果我们想让一句代码有布尔性质,那么我们就要使用“==”双等号,他表判断。这样程序就可以判断第一个<expr>测试表达式的真或者假,然后,把真或假的值传递给下一句代码。
如图,第2个窗口中使用了“==”双等号,使得程序按我们的表意进行正确的返回。
接下来我们就刚才的“==”双等号的问题来谈谈if语句中比较表达式,他可以是以下形式中的任何一种:
== 等于判断
!=不等于判断
>大于判断
>=大于或者等于判断
<小于判断
<=小于或者等于判断
其实我们可以发现,只要牵扯到了有关大于小于号的表达式,他们就已经具有了判断性了。
此外If语句还可以作为表达式的一部分,例如:x if a>b then else d
3.2:case of 表达试
case of表达式你可以把他看做是if语句的一个高级形式,你可以给出一组条件,这一组条件中可以有多个测试表达试,还可以为这多个测试表达式分别去定义他们的返回值,相比较if语句而言,他的选择不会局限于then 或者else的概念,case语句的选择可以是多个的。
个人观点:3DMAX的if语句设计的没有C++的更科学,不管从格式上说,还是执行方式来说,或许C++中if语句的设计,是为了更适合大型的复杂程序使用,但总的来说3DMAX的if语句并不是一个很好的编程风格,尤其是让别人阅读你程序的时候,程序思路就显的不如C++那么整洁和清晰。
他的标准语法是:
case [ <expr> ] of ( <cases> )
在这里<expr>是测试表达式,<cases>是表达失序列,譬如:
<factor>:<expr>
default:<expr>
default是一个标记,在case语句中是可以进行选择的,如果你给出一个组的条件都没有一条能和测试表达式匹配,default可以选择继续case 表达式。如果没有default标记,而且前面的一组条件中也都没有一条和测试表达式匹配,case表达式将返回一个undefined值。
以下是一个小例子
图片点击可在新窗口打开查看如何将一个空间用标准几何体填满
图片点击可在新窗口打开查看
想做一个漫游动画,在一个很大的空间里面漫游,周围全是一个有一个的细胞模型。类似于这样的在生物体内漫游的动画应该怎么去做?很多很多的细胞(也就是标准几何体—sphere)被放置在这个空间里面,这么多的细胞如何放?还是那个最简单的方法——一个一个的创建,然后调整位置 —_+++。呵呵,要是需要100万个细胞那就做死你去吧—凸—。
显然我们又需要使用到脚本工具了,正好有那么一条语句是我们需要的,在脚本字典上定义为:
Random <point3><ponit3>
他的功能是可以通过2个已经确定了的点的对角线确定一个空间,然后在这个空间里面随机寻找坐标点!有这样功能的语句,我们实现用小球去填充一个空间的目的就不难了,不管是100个小球、1万个小球还是1000万个小球,都能让他们很快的填充在一个空间里面,以下是我做的范例,大家也可以式一式。
a = [-10,-20,-30] -- 定义一个坐标为 a的值
b = [20,30,50] -- 定义一个坐标为 b的值
p1 = Point pos:a 
p2 = Point pos:b 
for i = 1 to 2000 do 
sphere pos:(random a b) radius:2 wirecolor:red
这短代码的意思是:先定义一个坐标为a的值,和一个坐标为b的值,然后在空间中创建2个实点:p1和p2,他们的坐标分别为a和b。
接着定义一个循环函数,从1到2000,也就是创建2000个小球,他们的坐标在p1点和p2点之间随即选择,这样,我们就完成了这个用标准几何体来填充一个空间的制作
图片点击可在新窗口打开查看
内存分配:运行一段脚本内存不够时怎么办?
MaxScript工作的时候是需要占用一定的内存空间的,系统默认的占用量是5.5MB,同所有的3DMAX内存一样,MaxScript工作时候的内存也是虚拟的,并且按页管理。通常情况下默认的5.5MB内存就已经够用了,如果要运行一些大的脚本,需要更多的内存,可以通过系统全局变量的heapSize来增加内存:
HeapSize+=1000000 (另增1MB,一共6.5MB)
需要额外掉用内存的时候,把这句话添加到脚本当中即可,因为这样的内存调用方式会使系统所有的内存资源下降,所以一般情况下输入这句话3DMAX是不会执行的,只有在MaxScript返回了“Out of memory”的错误信息后,才能使用heapSize语句调用系统内存供MaxScript使用。当重新启动3DMAX后,MaxScript内存占用
 
http://blog.csdn.net/chinamming/article/details/16863847

转载于:https://www.cnblogs.com/muyouking/p/6401480.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值