MAX Script Export/Import

本文分享了使用3ds Max Script开发Export/Import插件的经验,包括对3ds Max概念的理解、脚本编写技巧以及常见问题解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FW: http://www.cnblogs.com/sssa2000/archive/2007/05/18/751800.html

2个工作日
写了一套简单的Export/Import插件
一直对MAX的 Script感到很好奇
说说使用的感受吧。

首先,如果要使用这套Script那么 首先会陷入到庞大的MAX的概念的汪洋大海之中
MAX中很多概念不同于平常熟知的 RealTime里面的思想
例如,MAX中的纹理坐标,每个顶点都有一对UV 这个很正常
但是同时 MAX对每个Face也保存了UV,这是因为MAX中的 每个Face都有可能是不同的贴图
等等

第二,如果熟悉了MAX中的哪些类能够干什么 那么Script也就是很水道渠成的事情了。为了写这2个插件,MAX Script 的help翻了无数次,几乎每写一句就要去翻一次。

第三,MAX中的数组起位置是1,但是MAX中有的概念 使用数组表示的时候起始位置为0 ,例如纹理的Channel,起始就是为0,并且Channel0  很危险,写入错误直接让MAX挂掉

第四,脚本编写很考验打字的准确度,由于变量没有类型,不需要声明就可以试用,打错一个字母的话那就查吧,运气不好的话,会让你疯掉的,同时MAX的脚本编辑器 超级难用。

第五,编写导入插件的时候,发现Script 中读入数据异常痛苦,我在Script的帮助中没有发现任何类似c语言中的fprintf(%...)的东西,只有通过脚本提供的skiptostring来做。

第六 Max Script的函数 没有明确的返回值的概念,不习惯

第七 那个调试器 太难用了,我打了无数个messagebox

总 结:对于导入导出插件来说其实用SDK和Script 编写其实差别不大,因为都只是涉及到数据的读取和写入,并不涉及到复杂的逻辑。如果编写渲染类型或者是动画控制类型的插件 我觉得还是用script好一些,因为可以直接在MAX中看到结果,同时还能够一句一句的执行,很方便。

我只是初学,希望有经验的人给点经验,最后附上简单的插件代码,
导出插件只能到处一个几何体,点击ExportGeo按钮,然后点选几何体,即可输出
导入插件没什么特别的操作,导入插件结尾有些仓促

以下是导入插件:其实导入插件没什么必要写,反正是在MAX中建模,直接保存为MAX文件就可以了,这里
纯属练手

macroScript ImportGeo category: "HowTo2"
(
    
--从文件中读入某个分割符 后面 的数据
    
--FileStream:文件句柄
    
--needload :储存读取后的值的变量 (string or value)
    
--spliter:分隔符(string)
    
--bReadLine: 是否读取分隔符后所有的数据  1表示读取后面所有
    fn LoadData FileStream spliter bReadLine
=
    (
        temp
=skiptostring FileStream spliter
        
if bReadLine==1 then
            needload
=readline FileStream
        
else
            needload
=readvalue FileStream
    
    )
    
--***************************************************
    
--******************************************************
    
--****************************************************
    vert_array 
= #()
    face_array 
= #()
    sgroup_array 
= #()
    matid_array 
= #()
    edge_array 
= #()
    
    tm_row1
=#()
    tm_row2
=#()
    tm_row3
=#()
    tm_row4
=#()
    nodename
=""
    
--以下均为material变量
    _Material_Name
    _Material_Type
    _Material_Ambient
    _Material_Diffuse
    _Material_Specular
    _Material_Specular_Lv
    _Material_Glossiness
    _Material_SelfillumColor
    _Material_SelfillumAmount
    _Material_DiffTexPath
    BitmapPath
    
    channel_num
    UVW_Ver_Num
    UVW_Face_Num
    Vert_UV
=#()          --所有的顶点的uv都放在这里
    Face_UV
=#()          --所有的面的uv都放在这里
    Vert_UV_Size
=#()  --用于记录每个channel的顶点的uv总数
    Face_UV_Size
=#()  --用语及了每个channel的面uv总数

    in_name
=getopenfilename()
    
if in_name!=undefined then
    (
        in_file
=openfile in_name
        
if in_file!=undefined then
        (
            
--node name
            temp
= readline in_file 
            token
=filterString temp    " "    
            nodename
=(token[token.count] as string)
            
--**************************************************
            
--material info
                
            _Material_Name
=LoadData in_file  "->" 1
            _Material_Type
=LoadData in_file  "->" 1
            _Material_Ambient
=LoadData in_file  "->" 0
            _Material_Diffuse
=LoadData in_file  "->" 0
            _Material_Specular
=LoadData in_file  "->" 0
            _Material_Specular_Lv
=LoadData in_file  "->" 0
            _Material_Glossiness
=LoadData in_file  "->" 0
            _Material_SelfillumColor
=LoadData in_file  "->" 0
            _Material_SelfillumAmount
=LoadData in_file  "->" 0
            _Material_DiffTexPath
=LoadData in_file  "->" 1
             
--**************************************************

            
--node matrix
            
--temp= readline in_file
            
            tt
=readDelimitedString in_file ":"
            temp
=readvalue in_file
            append tm_row1(temp)
            
            tt
=readDelimitedString in_file ":"
            temp
=readvalue in_file
            append tm_row2(temp)
            
            tt
=readDelimitedString in_file ":"
            temp
=readvalue in_file
            append tm_row3(temp)
        
            tt
=readDelimitedString in_file ":"
            temp
=readvalue in_file
            append tm_row4(temp)
            
            
--************************************************
            
--vertex info
            temp
= readline in_file 
            token
=filterString temp    " "    
            num_vert
=token[token.count] as integer
            
for i=1 to num_vert do
            (
                tt
=readDelimitedString in_file ":"
                temp
=readvalue in_file
                append vert_array (temp)
            )
            
--************************************************************
            
--face info
            temp
=readline in_file
            token
=filterstring temp " "
            num_face
=(token[token.count] as integer)
            
for j=1 to num_face do
            (
                append face_array (readValue in_file)
                append sgroup_array (readValue in_file)
                append matid_array (readValue in_file)
                edge1 
= readValue in_file
                edge2 
= readValue in_file
                edge3 
= readValue in_file
                append edge_array (#(edge1, edge2, edge3))
                
            )
             
--************************************************************
            
--uv info
            
-- in max channel begin with 0
            
--the channel 0 stores the vertex color info,no uv info
            
            channel_num
=LoadData in_file  ":" 0
            
for b=1 to (channel_num-1do
            (
                
--读出Channel id
                channel_id
=LoadData in_file  ":" 0
                
                
--texture map path
                BitmapPath
=LoadData in_file  "->" 1
                
                
--读出uv Vertex 的数量
                temp_size
=LoadData in_file ":" 0
                append Vert_UV_Size temp_size
                
                
--uv的数据
                
for i=1 to temp_size do
                (
                    append Vert_UV (readValue in_file)
                )
                
                
--uv face的 数量
                temp_size
==LoadData in_file  ":" 0
                append Face_UV_Size temp_size
                
                
for i=1 to temp_size do
                (
                    append Face_uv (readValue in_file)
                )
                
            )
        )
        close in_file
        
    )
    meditmaterials[
1].ambient=_Material_Ambient
    meditmaterials[
1].diffuse=_Material_Diffuse
    meditmaterials[
1].shaderbyname=_Material_type
    meditmaterials[
1].specular=_material_specular
    meditmaterials[
1].specularlevel=_material_specular_lv
    meditmaterials[
1].glossiness=_material_glossiness
    meditmaterials[
1].selfillumcolor=_Material_SelfillumColor
    meditmaterials[
1].selfillumamount=_Material_SelfillumAmount
    meditmaterials[
1].diffuseMapEnable=true
    bmp 
=bitmaptexture filename: _Material_DiffTexPath
    meditmaterials[
1].diffusemap=bmp

    new_mesh 
= mesh vertices:vert_array faces:face_array --materialIDs:#(0,1) tverts:vert_uv
    
for f = 1 to num_face do
    (
        setFaceSmoothGroup new_mesh f sgroup_array[f]
        setFaceMatID new_mesh f matid_array[f]
        setEdgeVis new_mesh f 
1 edge_array[f][1
        setEdgeVis new_mesh f 
2 edge_array[f][2
        setEdgeVis new_mesh f 
3 edge_array[f][3
    )
    myTransform 
= new_mesh.transform
    new_mesh.transform.row1 
= tm_row1[1]
    new_mesh.transform.row2 
= tm_row2[1]
    new_mesh.transform.row3 
= tm_row3[1]
    new_mesh.transform.row4 
= tm_row4[1]

    new_mesh.name
=(nodename as string)
    
    new_mesh.material
=meditmaterials[1]
        
    meshop.setMapSupport new_mesh 
0 true
    meshop.setMapSupport new_mesh 
1 true
    
    
--set vertex uv for every vertex
    meshop.setNumMapVerts new_mesh 
1 Vert_UV_Size[1] keep:false
    
for i=1 to Vert_UV_Size[1do
    (
        meshop.setMapVert new_mesh 
1 i Vert_UV[i]
    )
    
    
--set face uv for every face
    meshop.setnummapfaces new_mesh 
1 Face_UV_Size[1] keep:false
    
for i=1 to Face_UV_Size[1do
    (
        meshop.setMapFace new_mesh 
1 i Face_UV[i]
    )

    update new_mesh
    
)


以下是导出插件:
到处插件很容易写,导入插件花了2倍于导出的时间


-- export by sssa2000
macroScript ExportGeo category:
"HowTo2"
(
    fn GetGeometry o 
= 
    (
    
    Superclassof o 
== Geometryclass and classof o != TargetObject 
    )

    fn DumpMaterial m file
=
    (
    
--只对Standard类型的材质处理
    
--获得diffuse and diffuse map
        ismat
=iskindof m material 
        
if ismat then
        (
            
            name
=m.name
            format 
"Material Name-> %/n" name to: file
            
            class_of_mat
=classof m
            
--messagebox class_of_mat
            
if (class_of_mat )==Standardmaterial then
            (
                
                type
=m.shaderByName 
                format 
"Material Type->%/n" type to: file
                
                _ambient
=m.ambient
                format 
"Ambient Value->%/n" _ambient to:file
                
                diffuse_value
=m.diffuse
                format 
"Diffuse Value->%/n" diffuse_value to:file
                
                _specular
=m.specular 
                format 
"Specular Value->%/n" _specular to:file
                
                _specularLevel 
=m.specularLevel 
                format 
"SpecularLevel Value->%/n" _specularLevel to:file
                
                
                _Glossiness
=m.Glossiness 
                format 
"Glossiness Value->%/n" _Glossiness to:file
                
                _selfIllumColor 
=m.selfIllumColor 
                format 
"SelfIllumColor Value->%/n" _selfIllumColor to:file
                
                _selfIllumAmount 
=m.selfIllumAmount 
                format 
"SelfIllumAmount Value->%/n" _selfIllumAmount to:file
                
                
                diffuse_map_path
=m.diffusemap.filename
                format 
"Diffuse Map Path->%/n" diffuse_map_path to:file
            )
        )
        format 
"/n" to: file
    )
    
--/////////////////////////////////////////////////////////////////////////////////////////
    obj 
= pickobject filter:GetGeometry
    
    
if isValidNode obj then
    (
        nodename
=obj.name
        
--First export the matrix
        row1
=obj.transform.row1
        row2
=obj.transform.row2
        row3
=obj.transform.row3
        row4
=obj.transform.row4
        
        tmesh 
= snapshotAsMesh obj 
        out_name 
= GetSaveFileName()
        
if out_name != undefined then
        (
            out_file 
= createfile out_name

            format 
"Node Name: %/n" nodename to: out_file
            format 
"/n" to: out_file
            
--******************************************************
            
-- material info
            node_material
=obj.material
            num_sub_material
=getNumSubMtls obj.material
            DumpMaterial obj.material out_file
            
for y=1 to num_sub_material do
            (
                sub_mat
=getSubMtl obj.material y
                DumpMaterial sub_mat
= out_file
            )
            
--******************************************************

            format 
"Node TM Row1: %/n" row1 to: out_file
            format 
"Node TM Row2: %/n" row2 to: out_file
            format 
"Node TM Row3: %/n" row3 to: out_file
            format 
"Node TM Row4: %/n" row4 to: out_file
            
--******************************************************
            
-- vertex info
            num_verts 
= tmesh.numverts 
            num_faces 
= tmesh.numfaces
            format 
"Number of Ver: %/n" num_verts to:out_file
            
for v = 1 to num_verts do
                format 
"Ver%: %/n" v (getVert tmesh v) to:out_file
            format 
"/n" to:out_file
            
--***********************************************
            
--face info
            format 
"Number of Face: %/n" num_faces to:out_file
            
for f = 1 to num_faces do
            (
                face 
= getFace tmesh f
                sgroup 
= getFaceSmoothGroup tmesh f
                matid 
= getFaceMatId tmesh f
                edge1 
= getEdgeVis tmesh f 1
                edge2 
= getEdgeVis tmesh f 2
                edge3 
= getEdgeVis tmesh f 3
                format 
"%,%,%,%,%,%/n" face sgroup matid edge1 edge2 edge3 to:out_file
            )
            
--******************************************************
            
--uv info
            channel
=meshop.getnummaps tmesh --number of texture
            format 
"/n" to: out_file
            format 
"Channel Number:%/n" channel to:out_file
            
for i=1 to (channel-1do
            (
                
                
-- channel的计数从0开始
                
--channel 0 is vertex color so do not export it
                IsSupport
=meshop.getMapSupport tmesh i
                
if IsSupport==true then
                (
                    format 
"Channel ID:%/n" i to:out_file
                    
if classof obj.material.maps[i+1]==Bitmaptexture then
                        format 
"Map File Path->%/n" obj.material.maps[i+1].filename to: out_file
                    
else
                        format 
"Map File Path->Null/n" to: out_file
                    num_uv_ver
=meshop.getNumMapVerts tmesh i
                    num_uv_face
=meshop.getNumMapFaces tmesh i
                    format 
"UVW Vertex Number:%/n" num_uv_ver to:out_file
                    
for j=1 to num_uv_ver do
                    (
                        vert_uvw
=meshop.getMapVert tmesh i j 
                        
--messagebox (vert_uvw as string)
                        format 
"% /n" vert_uvw to: out_file
                    )
                    format 
"UVW Face Number:%/n" num_uv_face to:out_file
                    
for o=1 to num_uv_face do
                    (
                        uvw_face
=meshop.getMapFace tmesh i o
                        format 
"% /n" uvw_face to: out_file
                    )
                )
                
else
                (
                    
--format "Do Not Support Channel %/n" i to:out_file
                )
            )
        close out_file
        edit out_name
        )
    
    )

)
在vue2的main.js中代码是 import Vue from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; import ElementUI from "element-ui"; import "@/permissions.js"; // 路由权限 import "element-ui/lib/theme-chalk/index.css"; import "element-ui/lib/theme-chalk/display.css"; import "@/styles/theme/index.css"; //换肤样式 import "@/styles/index.scss"; //全局公共样式 import Fragment from "vue-fragment"; // 可产生虚拟根节点 import ElTableEdit from "el-table-edit"; import "@/filters/index"; // 全局过滤器 import "@/directive/index"; // 注册全局指令 import MyElement from "@/components/my-element"; // ElementUI 组件覆盖 import ImageViewer from "@/components/ImageViewer/index"; // 图片预览组件 import "./console.js"; import mavonEditor from 'mavon-editor'; import 'mavon-editor/dist/css/index.css'; Vue.config.productionTip = false; Vue.use(ElementUI); Vue.use(Fragment.Plugin); Vue.use(ElTableEdit); Vue.use(MyElement); Vue.use(mavonEditor); Vue.prototype.$ELEMENT = { size: "medium", zIndex: 3000 }; Vue.prototype.$imageViewer = ImageViewer; ElementUI.Input.props.clearable = { type: Boolean, default: true }; ElementUI.Select.props.clearable = { type: Boolean, default: true }; ElementUI.Pagination.props.background = { type: Boolean, default: true }; ElementUI.Pagination.props.layout = { type: String, default: "total,prev,pager,next", }; new Vue({ router, store, render: function(h) { return h(App); }, beforeCreate(){ Vue.prototype.$bus=this } }).$mount("#app"); router下index.js中的代码是 import Vue from "vue"; import VueRouter from "vue-router"; import Layout from "@/layout"; import view from "./module/view"; import Pages from "./module/pages"; Vue.use(VueRouter); /* 对VueRouter原型链上的push、replace方法进行重写 为了解决某些情况下控制台报 ‘Uncaught (in promise) undefined’的问题 参考地址:https://github.com/vuejs/vue-router/issues/2881 / const originalPush = VueRouter.prototype.push; VueRouter.prototype.push = function push(location, onResolve, onReject) { if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject); return originalPush.call(this, location).catch((err) => err); }; /* 所有页面都应该是一级页面,或者说必须直接渲染到layout上,否则没有缓存 name 必须与组件name一致,用于路由缓存功能 permission 为布尔时表示需要权限,默认值应该为 false,待后端返回相应的地址后会自动改为 true / const routes = [ // { // path: "/login", // hidden: true, // component: () => // import(/ webpackChunkName: "login" */ "@/views/Login.vue"), // }, { path: "/", component: Layout, redirect: "/icon", meta: { keepAlive: true }, // 标记需要缓存的路由 children: [...view, ...Pages], }, { path: "/icon", component: () => import("@/views/Icon.vue"), meta: { keepAlive: true }, // 标记需要缓存的路由 }, { path: "/from", component: () => import("@/pages/form.vue"), meta: { keepAlive: true }, // 标记需要缓存的路由 }, ]; const router = new VueRouter({ mode: "history", // base: process.env.BASE_URL, routes, }); export default router; 引入的layout代码是 <template> <keep-alive> <Lock v-if="isLock" /> <el-container v-else class="container"> <Aside /> <div v-show="!isCollapse" class="drawer-bg" @click="setCollapse(!isCollapse)" ></div> <el-container> <!-- <el-header class="el-header" height="auto"> <Header /> <Tabs /> </el-header> --> <el-main class="main"> <WaterMark :height="36" :width="100" image=""> <keep-alive :include="include"> <router-view /> </keep-alive> </WaterMark> </el-main> <!-- <el-backtop target=".main"></el-backtop> --> </el-container> </el-container> </keep-alive> </template> <script> import Aside from "./Aside"; // import Header from "./Header"; // import Tabs from "./Tabs"; import Lock from "./Lock"; import WaterMark from "@/components/WaterMark"; export default { components: { Aside, Lock, WaterMark }, computed: { //控制侧边栏展开收起状态 isCollapse() { return this.$store.state.layout.isCollapse; }, include() { return this.$store.getters.include; }, isLock() { return this.$store.state.lock.isLock; }, }, methods: { // 控制侧边栏导航 setCollapse(collapse) { this.$store.commit("setCollapse", collapse); }, }, }; </script> <style scoped lang="scss"> .container { position: relative; .el-header { padding: 0 !important; } .el-main{ padding: 0px; } .drawer-bg { display: none; } @media screen and (max-width: 1200px) { .drawer-bg { display: block; width: 100%; height: 100vh; position: absolute; top: 0; background: #000; opacity: 0.3; z-index: 1999; } } } .dark-theme .container .main { background-color: $dark-layout-main; } </style> 如何在路由中加入 缓存
最新发布
07-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值