一.分离一个特定元素(Detach Element)
要对一组相同的物体(Editable_Poly)进行分离物体里面某一个部分的功能。
本来以为Editable_Poly里面会有相关的Element的API,结果全是点(Vert)线(Edge)面(Face),只有一个getElementsUsingFace
而它的参数是 faceList,问题是在polyop里我还找不到getFace的函数....
也就是说这个界面上的基本操作实际上是封装了一层的,api层至多到Face层级,没有更高的层级了。
搜索了一番,找到了两个有用的函数
fn getElements obj=
(
try
(
f=obj.numfaces
eles=#()
done=#()
for i=1 to f do
(
if (finditem done i)==0 then
(
case (classof obj) of
(
editable_mesh:(faces=(meshop.getElementsUsingFace obj #(i)) as array)
editable_poly:(faces=(polyop.getElementsUsingFace obj #(i)) as array)
)
append eles faces
join done faces
)
)
)
catch(
eles=undefined
)
return eles
)
参考:https://www.maxforums.org/forum/thread/maxscript_mesh_elements/1
function detachElements nin_Object =
(
naOut = #()
if classof nin_Object == Editable_Poly do
(
suspendediting()
try
(
undo off
(
with redraw off
(
while polyOp.getNumFaces nin_Object != 0 do
(
elementSel = (polyOp.getElementsUsingFace nin_Object #{1})
baseName = nin_Object.name
newName = (uniqueName baseName)
polyOp.detachFaces nin_Object elementSel asNode:true name:newName
detachedObj = (getNodeByName newName)
append naOut detachedObj
)
for o in naOut do
(
baseName = (substring o.name 1 (o.name.count-3))
uniquePart = (substring o.name (o.name.count-2) o.name.count)
finalName = (baseName + "_" + uniquePart)
o.name = finalName
centerPivot o
)
)
)
)
catch(messageBox "error: detach objects")
resumeediting()
delete nin_Object
)
naOut as array
)
参考:http://www.scriptspot.com/forums/3ds-max/general-scripting/edit-poly-modifier-quick-detach
接下来又是二次开发的工作了,我要把Element相关的操作封装到一个ElementOp里面
-------------------------------------------------------------------------------------------------
二、按材质分离元素
本来以为是分离就好了,结果还要合并相同材质的物体
结果1:将窗户的玻璃和外框分离,并放在一个组里,每个窗户变成一个组,里面有两个子物体
结果2:在上面的基础上,将全部的玻璃合并在一个物体里,外框合并在一个物体里
整个过程学到了Element操作,材质操作,分离合并,从门外汉入门了一些。
把整个ms贴出来吧,使用的是最下面的函数。
print "-------------------------- ElementOp.ms ---------------------------------"
struct ElementOpClass
(
fn GetElements obj=
(
print ("->ElementOp.GetElements():"+(obj as string))
try
(
f=obj.numfaces
eles=#()
done=#()
for i=1 to f do
(
if (finditem done i)==0 then
(
case (classof obj) of
(
editable_mesh:(faces=(meshop.GetElementsUsingFace obj #(i)) as array)
editable_poly:(faces=(polyop.GetElementsUsingFace obj #(i)) as array)
)
append eles faces
join done faces
)
)
)
catch(
eles=undefined
)
return eles
),
fn DetachElement obj ele=
(
newName = (uniqueName obj.name)
polyOp.detachFaces obj ele asNode:true name:newName
detachedObj = (getNodeByName newName)
centerPivot detachedObj --没有这句话的话,新的物体的轴心还是在原来的物体的轴心的位置
return detachedObj
),
fn RenameElement o = --
(
baseName = (substring o.name 1 (o.name.count-3))
uniquePart = (substring o.name (o.name.count-2) o.name.count)
finalName = (baseName + "_" + uniquePart)
o.name = finalName
),
fn RenameElements objs = --
(
if objs == undefined do (
print "RenameElements objs == undefined"
return undefined
)
for o in objs do
(
RenameElement o
)
),
--ElementOp.DetachAllElements $
fn DetachAllElements obj =
(
print ("->ElementOp.DetachAllElements():"+(obj as string))
naOut = #()
if classof obj != Editable_Poly do convertToPoly obj
if classof obj == Editable_Poly do
(
-- suspendediting()
-- try
-- (
-- undo off
(
with redraw off
(
while polyOp.getNumFaces obj != 0 do
(
elementSel = (polyOp.GetElementsUsingFace obj #{1})
detachedObj=DetachElement obj elementSel
append naOut detachedObj
)
for o in naOut do
(
RenameElement o
)
)
)
-- )
-- catch(messageBox "error: detach objects")
-- resumeediting()
delete obj
)
naOut as array
),
fn DetachElements_Inner obj indexes isCombine:true isGroup:true=(
print ("->Elements.DetachElements():"+(obj as string))
if classof obj != Editable_Poly do (
convertToPoly obj
)
local eleList=GetElements obj
print eleList
local newObjs=#(obj)
if isCombine then
(
local newEle=#()
if indexes!= undefined do
(
for i in indexes do
(
ele=eleList[i]
print (ele as string)
join newEle ele
)
local detachedObj=DetachElement obj newEle
append newObjs detachedObj
)
)
else
(
if indexes!= undefined do
(
for i in indexes do
(
local detachedObj=DetachElement obj eleList[i]
append newObjs detachedObj
)
)
)
local oriName=obj.name
obj.name=obj.name+"000" --保持命名一致
for o in newObjs do
(
RenameElement o
)
if isGroup then
(
g1=group newObjs name:oriName
setGroupOpen g1 true
return g1
)
return newObjs
),
--ElementOp.DetachElements $ #(1,2,3)
--ElementOp.DetachElements $ #(1,2,3) isCombine:false
--ElementOp.DetachElements $ #(1,2,3) isGroup:false
--ElementOp.DetachElements $ #(1,2,3) isGroup:false isAttachAll:true
fn DetachElements objList indexes isCombine:true isGroup:true isAttachAll:false=
(
if objList == undefined do (
print "DetachElements objList == undefined"
return undefined
)
newObjList=#()
for obj in objList do
(
print ("->Elements.DetachElements():"+(obj as string))
newObj=DetachElements_Inner obj indexes isCombine:isCombine isGroup:isGroup
append newObjList newObj
--exit
)
if newObjList.count > 1 and isCombine == true and isGroup==false and isAttachAll == true do
(
print "attachAll"
)
print (newObjList as string)
),
--ElementOp.DetachByMaterial $
fn DetachByMaterial_Inner obj isGroup:true=
(
if obj == undefined do (return undefined)
if classof obj != Editable_Poly do (
convertToPoly obj
)
oldName=obj.name
m=obj.material
if classof m == MultiMaterial do
(
newObjs=#()
for i=1 to m.numsubs do
(
mId=m.MaterialIDList[i]
obj.selectByMaterial mId
m_faces = getFaceSelection obj
detachedObj=DetachElement obj m_faces
subM=m.MaterialList[i]
detachedObj.material=subM
print ("detachedObj Material"+(subM as string ))
append newObjs detachedObj
)
RenameElements newObjs
delete obj
if isGroup do
(
g=group newObjs name:oldName
setGroupOpen g true
return g
)
return newObjs
)
return undefined
),
fn FindObjectsByMaterial objList m =
(
items=#()
for obj in objList do
(
if isDeleted obj do continue
if obj.material == m do append items obj
)
return items
),
--ElementOp.AttachObjects $
fn AttachObjects objList =
(
print objList
if objList == undefined do (
print "AttachObjects objList == undefined"
return undefined
)
if classof objList != Array and classof objList !=ObjectSet do (
format "skip classof:%\n" (classof objList)
return objList
)
if objList.count < 2 do return objList
objList=objList as Array --记得要转换 不然会出错
first = objList[1]
format "first:%\n" first
format "objList1:%\n" objList.count
-- deleteItem objList first
-- while objList.count > 0
for i =2 to objList.count do
(
obj = objList[i]
format "obj:%\n" obj
if obj == undefined do continue
polyop.attach first obj --ObjectSet的情况下,会自动把删除的模型去掉
i-=1
format "count:%\n" objList.count
)
format "objList:%\n" objList
CenterPivot first
),
fn CollectMaterials objList=
(
mList=#()
for obj in objList do
(
m=obj.material
i = findItem mList m
if i == 0 do append mList m
)
format "materialList:%\n" mList
return mList
),
--ElementOp.AttachByMaterial $
fn AttachByMaterial objList=
(
if objList == undefined do (
print "AttachByMaterial objList == undefined"
return undefined
)
newObjList=#()
mList=CollectMaterials objList
for m in mList do
(
subList=FindObjectsByMaterial objList m
format "subList:%\n" subList
newObj=AttachObjects subList
-- append newObjList newObj
)
return newObjList
),
--ElementOp.DetachByMaterial $
--ElementOp.DetachByMaterial $ isGroup:false
--ElementOp.DetachByMaterial $ isCombineByMat:true
fn DetachByMaterial objList isGroup:true isCombineByMat:false=
(
if objList == undefined do (
print "DetachElements objList == undefined"
return undefined
)
if isCombineByMat do isGroup=false
newObjList=#()
objList=objList as Array --记得要转换 不然会出错
for obj in objList do
(
print ("->Elements.DetachElements():"+(obj as string))
newObj=DetachByMaterial_Inner obj isGroup:isGroup
join newObjList newObj
--exit
)
print (newObjList as string)
if newObjList.count > 1 and isCombineByMat ==true and isGroup == false do
(
print "attachAll"
newObjList=AttachByMaterial newObjList
print (newObjList as string)
)
)
)
ElementOp=ElementOpClass()
大小写上,我自己的约定是 struct和function是大写开头的,虽然写着写着有时候自己也写成了小写,后面会再替换一下,javascript和java的函数名都是小写开头的,c#的是大写开头的,但是这些语言有()作为函数的调用,这里没有,还是区分一些 不然两个并列的字符串 感觉像是两个变量一样。
命名上函数名都是动词+名词,变量名都是名称。
实际使用环境中,这些窗户是分别在不同楼层中的,要按楼层分别处理。
然后还有楼梯、栏杆的分离合并操作。
另外就是一般的代码操作都能回退,这些操作完后如果回退,可能会导致3dmax崩溃,这我就不研究了,使用前备份一下文件就行。