一.分離一個特定元素(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崩潰,這我就不研究了,使用前備份一下文件就行。