〇、说明
0.除自定义脚本,其余示例摘自3DS MAX 2017 Help
1.将乱码部分统一命名,调整规则如下;
a.mesh节点:如果mesh乱码,其父物体命名正确,则将其命名为与父物体同名;
b.对于所有节点,如果名称中含有"|:|",则截取第一个"|“前的字符作为名称,否则,删除名称中的非法字符,作为名称(第一个”|“前的字符相同的mesh多为同一对象,第二个”|“的猜测为类似索引值的标记),如果首字符为”_",则添加"Object"前缀(主要因为此种情况下经删除非法字符后保留的字符较少);
2.将指定文件夹下所有stp逐个导入到3ds Max并分别在各自路径下导出为fbx;
3.调整每个对象的缩放值(1,1,1)和轴心点(位于物体的中心);
4.删除同一虚拟节点下重复的Mesh(尚存问题,已弃用);
a.如果两个mesh中的一个是另一个的冗余部分,则删除顶点较少的mesh对象;
b.如果两个mesh是不同的对象,则保留;
c.以上判断通过两个mesh的center的点积进行判断的(尚存问题);
一、MaxScript
1.StpModelCovertToFbxTool
global validChar="_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
fn filteringInvalidChar instring =-- beginning of function definition
( local outstring-- declare variables as local
-- create an unique copy of the string referenced by instring,
-- and store reference to unique copy in outstring
-- set variables to literals
result =""
outstring=copy instring
-- increment from 1 to number of character in string
for i=1 to outstring.count do(
-- see if the single character at index i in outstring
-- is present instring lower
-- If so, j equals position in string validChar.
-- If not, j equals undefined
a=findstring validChar outstring[i]
if a!=undefined then
result+=outstring[i]
else result
-- value will be returned as function result
)
result
)
fn getFilesRecursive root pattern =
(
dir_array = GetDirectories (root+"/*")
for d in dir_array do
join dir_array (GetDirectories (d+"/*"))
my_files = #()
for f in dir_array do
join my_files (getFiles (f + pattern))
my_files
)
fn correctGeometryName =(
for obj in geometry do(
splitName=filterString obj.name "|"
if splitName.count>1 then
obj.name=splitName[1]
else(for i=1 to obj.name.count do(
if obj.name[i]!=undefined do(
b=findstring validChar obj.name[i]
if b==undefined do
obj.name=obj.parent.name
)
)
)
)
)
fn correctNodeName =(
i=0
for obj in objects do(
rightname=filteringInvalidChar obj.name as string
if rightname.count>1 then
obj.name=rightname
else (
obj.name="Target"+i as string
i+=1
)
if obj.name[1]=="_" do
obj.name="Object"+obj.name
)
)
fn resetModel=(
for obj in objects do(
CenterPivot obj
ResetScale obj
ResetTransform obj
)
)
#尚存问题
fn deleteRepeatedModel=(
for obj in geometry do(
if obj.parent.children.count>=2 do(
if (dot obj.parent.children[1].center obj.parent.children[2].center<30) do(
try(
if obj.parent.children[1].verts.count <obj.parent.children[2].verts.count then
delete obj.parent.children[1]
else
delete obj.parent.children[2]
)
catch ()
)
)
)
)
stpModelPath="E:\Unity Arts Assets\3ds Max\Schneider Pan Gu"
--stp原始模型路径
dir_array = getFilesRecursive stpModelPath "*stp"
print dir_array.count as string
for i=1 to dir_array.count do(
print dir_array[i]
)
for d in dir_array do(
for f in getfiles d do(
loadmaxfile f
correctGeometryName()
correctNodeName()
resetModel()
#deleteRepeatedModel()
fname=(filterString(pathConfig.stripPathToLeaf d) ".")[1]+".fbx"
exportfile (pathConfig.removePathLeaf d+"\\"+fname) #noprompt selectedonly:false using:fbxexp
)
)
2.WriteAllStpMoldelPathToTxt
fn format_txt filepath filetext =
(
if doesFileExist filepath == true
then
(
fin = openfile filepath mode:"r+"
seek fin #eof
txt = filetext + "\n"
format txt to:fin
close fin
)
else
(
newfile = createFile filepath
close newfile
format_txt filepath filetext
)
)
stpModelPath="E:\3ds Max\Stp Models"
--stp原始模型路径
txtPath="E:\Unity Arts Assets\3ds Max\Schneider Pan Gu\StpList.txt"
dir_array = getFilesRecursive stpModelPath "*.stp"
for i=1 to dir_array.count do(
format_txt txtPath dir_array[i] as string
)
3.findString
<integer>findString<string> <search_string>
Returns the index of search_string in string or undefined if not found.
EXAMPLE
findString "Thanks for all the fish!" "all" -- returns 12
4.The following script shows the use of various literals, constructors, properties, operators, and methods of the String class.
EXAMPLE
-- strings test bed
fn uppercase instring =-- beginning of function definition
( local upper, lower, outstring-- declare variables as local
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"-- set variables to literals
lower="abcdefghijklmnopqrstuvwxyz"
-- create an unique copy of the string referenced by instring,
-- and store reference to unique copy in outstring
outstring=copy instring
-- increment from 1 to number of character in string
for i=1 to outstring.count do
-- see if the single character at index i in outstring
-- is present instring lower
-- If so, j equals position in string lower.
-- If not, j equals undefined
( j=findString lower outstring[i]
-- if character was found in lower,
-- replace with corresponding character in upper:
if (j != undefined) do outstring[i]=upper[j]
)
outstring-- value will be returned as function result
)-- end of fn uppercase
s1="AbCdEfGh"-- set variable to literal
s2=uppercase s1-- call function uppercase, passing s1 as parameter
if s1 == s2 do print "strings s2 and s3 are the same"-- compare strings
if s1 != s2 do print "strings s1 and s2 are different"
theObject="sphere"-- set variable to literal
theRadius= (random 10. 100.) as string-- convert number to string
-- concatenate strings and execute string
myObject=execute (theObject +" radius:"+ theRadius)
OUTPUT:
uppercase()-- result to function definition
"AbCdEfGh"-- result of line 24
"ABCDEFGH"-- result of line 25
undefined-- result of line 26 - stringsnot equal,
-- and no else expression in if expression
"strings s1 and s2 are different"-- output from line 27
"strings s1 and s2 are different"-- result of line 27
"sphere"-- result of line 29
"75.4091"-- result of line 30
$Sphere:Sphere001 @ [0.000000,0.000000,0.000000]-- result of line 32. Execute function
-- created a sphere object
5.getFiles
getFiles <wild_card_filename_string>
Returns an array of file names that match the given wild-card path name.
FOR EXAMPLE,
The following code gets an array of all the .max scene files in c:\foo and then loops over the array, opening each file and printing the objects in each:
files = getFiles "c:\\foo\\*.max"
for f in files do (loadMAXFile f; print objects)
getFiles() can also be used to determine if a file or file pattern exists.
FOR EXAMPLE
the following function will return true if the specified file name or pattern exists:
fn existFile fname = (getfiles fname).count != 0
See also doesFileExist() which checks for a single file only and does not supportwildcardpatterns.
6.getDirectories <wild_card_directory_name_string>
Returns an array of directory paths that match the given wild-card directory path name.
SCRIPT
fn getFilesRecursive root pattern =
(
dir_array = GetDirectories (root+"/*")
for d in dir_array do
join dir_array (GetDirectories (d+"/*"))
my_files = #()
for f in dir_array do
join my_files (getFiles (f + pattern))
my_files
)
--get all .ms files from the folder c:/temp
--and all its subfolders:
getFilesRecursive "c:/temp" "*.ms"
7.filterString
<array of strings>filterString <string> <token_string> [splitEmptyTokens:<boolean>]
Parses string based on token_string and returns an array of strings. The filterString splits the input string into substrings based on the characters given in token_string , and returns each substring as a member of the array. The token_string is simply a list of ‘splitter characters’ (when the string is scanned, any occurrence of any of the tokens is regarded as the start of a substring). This function is useful for file import/export scripts or for any type of manual parsing.
FOR EXAMPLE
filterString "MAX Script, is-dead-funky" ", -"
WOULD RETURN
#("MAX","Script","is","dead","funky")
If splitEmptyTokens is false or not specified, sequential tokens are handled as a single token and tokens at the beginning or end of the string are ignored. If splitEmptyTokens is true , each token found will result in string element in the output, with the string element in the cases ignored above being empty strings
8.pathConfig.removePathLeaf
pathConfig.removePathLeaf <path>
Removes a leaf from the given path.
FOR EXAMPLE,
pathConfig.removePathLeaf "c:\\temp\\test"
"c:\temp"
pathConfig.stripPathToLeaf
9.pathConfig.stripPathToLeaf <path_or_filename>
Returns the last sub-directory name from the given path. If the path is a full file name, returns the file name. Equivalent to filename from path.
EXAMPLES:
pathConfig.stripPathToLeaf "C:\\temp\\test"
"test"
pathConfig.stripPathToLeaf "C:\\temp\\test\\"
""
pathConfig.stripPathToLeaf "C:\\temp\\test\\somefile.tga"
"somefile.tga"
--COMPARE:
filenamefrompath "C:\\temp\\test"
"test"
filenamefrompath "C:\\temp\\test\\"
""
filenamefrompath "C:\\temp\\test\\somefile.tga"
"somefile.tga"
10.CenterPivot
CenterPivot <node>-- mapped method
Same as Hierarchy/Pivot/Affect Pivot Only - Center to Object.
11.ResetScale
ResetScale <node>-- mapped method
Same as Hierarchy/Pivot/Reset Scale.
Vector Dot Product
12.dot
dot <point3> <point3>
Returns the vector dot product.
The geometric interpretation of the dot product is the length of the projection of the first vector onto the unit vector of the second vector. Obviously, when the two vectors are perpendicular, the dot product is 0.0.
The dot product is commutative, which means that dot X Y == dot Y X.
The dot product is associative, which means that dot (rX) Y == r(dot X Y).
The dot product is distributive, which means that dot X (Y+Z) == (dot X Y) + (dot X Z).
Because the dot product of two normal vectors is the cosine of the angle between them, the dot product can be used conveniently to calculate the angle between two vectors:
FOR EXAMPLE
fn GetVectorsAngle v1 v2 =
(
theAngle = acos(dot (normalize v1) (normalize v2))
)
GetVectorsAngle [10,0,0] [10,20,0]
63.435
13.Try Expression
Try Expression