不要信引擎的破碎插件。你做过项目就知道那玩意不好用! raytool制作自定义破碎的绝版教程,如此这般,得到一个光滑的自定破碎组,此教程使用flash绝版制作的破碎用shape的ai文件外,并且还用一个绝妙的方法避免了自相交计算错误!看完记得点赞!
adobe flash cs3,这个版本可以导出ai文件,使用铅笔或者直线描一遍纹理,外面再加一个框png
使用油桶对框内进行填充
每个填充ctrl+g打组,双击进去然后s填充边
选中打组的填充ctrl+x 新建图层ctrl+shift+v原地粘贴到新的图层
打组并且填充后的块复制到新图层后把原来的两个图层删除
再次双击进入新图层
adobe flash cs3,这个版本可以导出ai文件
导出ai文件
max中导入刚才的ai文件
重点来了!!!修改自相交
轴心模式改为各自独立,,右击选择和均匀放大按钮,修改offset,screen为99.99,回车,放大到最大看修正了自相交
放大到最大看修正了自相交
仔细检查,删除跨境或者中间没有loop封闭的线段。
使用图形破碎
顺利计算完成后把切割体和刚才的切割线 shape删除。大刚里把0级的那个完整的破碎前的物体也删除。
其中有个碎片,产生出带框架的破碎,这个框架是没有厚度的,删除这些点,只保留碎片。
显示出所有的碎片。
一个完美的自定义破碎体完成!
使用脚本检查自相交,封闭和清除废点
再搭配cgjoy里我的max破碎绑骨插件便可以完美的导入到unity,ue5里,不要信引擎的破碎插件。你做过项目就知道那玩意不好用!。记住一句话,插件能自动搞好,还要美工干啥?相信ai,母猪能上树。。
脚本代码免费拿!
destroyDialog 破碎线条检测工具
rollout 破碎线条检测工具 "破碎线条检测工具2025.2.13" width:200 height:200
(
button checkIntersectionBtn "检查自相交" width:120 height:30 pos:[30,10]
progressbar CheckIntersectionProgress "CreateProgressBar" color:(color 20 150 240) pos:[30,42]width:120 height:5 align:#center
button CheckClosedBtn "检查是否封闭" width:120 height:30 pos:[30,45]
progressbar CheckClosedProgress "CreateProgressBar" color:(color 20 150 240) pos:[30,76]width:120 height:5 align:#center
button DelIsoVertex "清除废点" width:120 height:30 pos:[30,80]
progressbar DelIsoVertexProgress "CreateProgressBar" color:(color 20 150 240) pos:[30,110]width:120 height:5 align:#center
button showAllBtn "显示所有子线条" width:120 height:30 pos:[30,115]
-- 三维向量叉积的方法
fn ThreeVectorCrossIntersecting p1 p2 p3 p4 = (
-- 计算方向向量
local d1 = p2 - p1
local d2 = p4 - p3
local r = p3 - p1
-- 计算叉积
local crossD1D2 = cross d1 d2
local crossR1D2 = cross r d2
local crossR1D1 = cross r d1
-- 如果叉积的长度接近0,说明线段平行
local crossLength = length crossD1D2
local epsilon = 0.0001
if crossLength < epsilon then return false
-- 计算参数
local t = dot crossR1D2 crossD1D2 / (crossLength * crossLength)
local u = dot crossR1D1 crossD1D2 / (crossLength * crossLength)
-- 检查参数是否在0到1之间
if t >= 0.0 and t <= 1.0 and u >= 0.0 and u <= 1.0 then return true
return false
)
-- 检查两条子样条线是否相交的函数
fn areSubSplinesIntersecting shapeObj splineIndex1 splineIndex2 =
(
-- 获取子样条线的顶点数量
local numKnots1 = numKnots shapeObj splineIndex1
local numKnots2 = numKnots shapeObj splineIndex2
-- 遍历第一条子样条线的所有线段
for i = 1 to (numKnots1 - 1) do
(
local p1 = getKnotPoint shapeObj splineIndex1 i
local p2 = getKnotPoint shapeObj splineIndex1 (i + 1)
-- 遍历第二条子样条线的所有线段
for j = 1 to (numKnots2 - 1) do
(
local p3 = getKnotPoint shapeObj splineIndex2 j
local p4 = getKnotPoint shapeObj splineIndex2 (j + 1)
-- 使用三维线段相交检测函数,检测线段是否相交
if ThreeVectorCrossIntersecting p1 p2 p3 p4 then return true
)
)
return false
)
-- 延迟执行函数
fn delay mytimeNum excudeCMDStr=
(
global delayTimer
global excudeCMDStrGlobal= excudeCMDStr
fn backtop =(
execute excudeCMDStrGlobal
)
if delayTimer == undefined do
(
delayTimer = dotnetobject "Windows.Forms.Timer"
dotnet.AddEventHandler delayTimer "Tick" backtop
)
delayTimer.Interval = mytimeNum
delayTimer.enabled = true
if delayTimer.enabled == true do
(
delayTimer.enabled = false
--print("定时器已经停止")
)
)
-- 检查自相交的函数
fn checkSelfIntersection shapeObj =
(
local TotalSplines = shapeObj.numSplines
local intersectPairs = #()
P=1 --进度条初始化
-- 计算总迭代次数
totalIterations = (TotalSplines * (TotalSplines - 1)) / 2
for i = 1 to TotalSplines do
(
for j = i + 1 to TotalSplines do
(
local isIntersecting = areSubSplinesIntersecting shapeObj i j
if isIntersecting then
(
print "子样条线相交"
append intersectPairs #(i, j)
)
else
(
print "子样条线不相交"
)
-----进度条-----
CheckIntersectionProgress.value = 100.0 * P / totalIterations--CreateProgressBar
if (keyboard.EscPressed==true) then exit
P+=1
-----进度条end-----
)
print("检查完毕")
)
if intersectPairs.count > 0 then
(
format ">检测到 % 对相交的子样条线:\n" intersectPairs.count
for pair in intersectPairs do
(
--format ">>子样条线 % 和子样条线 % 相交。选择了它\n" pair[1] pair[2]
setSplineSelection shapeObj #(pair[1]) keep:1
setSplineSelection shapeObj #(pair[2]) keep:1
)
subobjectLevel = 3
max select invert
splineOps.hide shapeObj
)
cmdString="subobjectLevel = 3" as string
delay 200 cmdString
)
-- 检查是否封闭的函数
fn checkClosed shapeObj =
(
setSplineSelection shapeObj #() keep:0
local NumerSplines = shapeObj.numSplines
p=1 -----进度条初始化
for splineIndex = 1 to NumerSplines do
(
local closed = isClosed shapeObj splineIndex
if closed then
(
format "样条线 % 是封闭的。\n" splineIndex
)
else
(
--format "样条线 % 是开放的。\n" splineIndex
--print("111"+splineIndex as string)
setSplineSelection shapeObj #(splineIndex) keep:1
)
-----进度条-----
CheckClosedProgress.value = 100.0 * P / NumerSplines--CreateProgressBar
if (keyboard.EscPressed==true) then exit
P+=1
-----进度条end-----
)
subobjectLevel = 3
max select invert
splineOps.hide shapeObj
cmdString="subobjectLevel = 3" as string
delay 200 cmdString
)
-- 显示所有子线条的函数
fn showAllSubLines shapeObj =
(
splineOps.unhideAll shapeObj
setSplineSelection shapeObj #() keep:0
local numSplines = shapeObj.numSplines
for i = 1 to numSplines do
(
setSplineSelection shapeObj #(i) keep:1
)
subobjectLevel = 3
cmdString="subobjectLevel = 3" as string
delay 200 cmdString
)
on checkIntersectionBtn pressed do
(
local shapeObj = selection[1]
if isValidNode shapeObj and classof shapeObj == SplineShape then
(
checkSelfIntersection shapeObj
)
else
(
messagebox "请选择一个有效的样条线对象!"
)
)
on checkClosedBtn pressed do
(
local shapeObj = selection[1]
if isValidNode shapeObj and classof shapeObj == SplineShape then
(
checkClosed shapeObj
)
else
(
messagebox "请选择一个有效的样条线对象!"
)
)
on showAllBtn pressed do
(
local shapeObj = selection[1]
if isValidNode shapeObj and classof shapeObj == SplineShape then
(
showAllSubLines shapeObj
setSplineSelection shapeObj #()keep:0
)
else
(
messagebox "请选择一个有效的样条线对象!"
)
)
on DelIsoVertex pressed do
(
selarray=selection as array
if selarray.count==0
then messagebox "请选择物体!" title:"温馨提示"
else
(
P=1 --初始化进度条
for i=1 to selarray.count do
(
wrvarray=#()
x=selarray[i]
-- 检查对象是否为可编辑多边形,如果不是则转换
if classof x != Editable_Poly then
(
convertToPoly x
)
--移除孤立点
x.EditablePoly.deleteIsoVerts ()
--移除同属于两条边并且同属于两个面的废点
for j = 1 to x.GetNumVertices() do
(
x.EditablePoly.SetSelection #Vertex #{j}
vbarray=x.EditablePoly.getSelection #Vertex
varray=vbarray as array
if ((x.GetVertexEdgeCount j)==2 and (x.GetVertexFaceCount j)==2)
then append wrvarray varray[1]
)
x.EditablePoly.SetSelection #Vertex (wrvarray as bitarray)
x.EditablePoly.Remove selLevel:#Vertex
--移除开放边上的废点
wvarray=#()
for k=1 to x.GetNumVertices() do
(
x.EditablePoly.SetSelection #Vertex #{}
if ((x.GetVertexEdgeCount k)==2 and (x.GetVertexFaceCount k)==1) then
(
x.EditablePoly.SetSelection #Vertex #{k}
x.EditablePoly.ConvertSelection #Vertex #Edge
eb=x.EditablePoly.getSelection #Edge
ea=eb as array
es=#()
append es ea[1]
x.EditablePoly.SetSelection #Edge (es as bitarray)
x.EditablePoly.ConvertSelection #Edge #Vertex
vb=x.EditablePoly.getSelection #Vertex
va=vb as array
if va[1]==k
then v1=(x.getvertex va[2])-(x.getvertex k)
else v1=(x.getvertex va[1])-(x.getvertex k)
es=#()
va=#()
append es ea[2]
x.EditablePoly.SetSelection #Edge (es as bitarray)
x.EditablePoly.ConvertSelection #Edge #Vertex
vb=x.EditablePoly.getSelection #Vertex
va=vb as array
if va[1]==k
then v2=(x.getvertex va[2])-(x.getvertex k)
else v2=(x.getvertex va[1])-(x.getvertex k)
)
)
x.EditablePoly.SetSelection #Vertex (wvarray as bitarray)
x.EditablePoly.Remove selLevel:#Vertex
-----进度条-----
DelIsoVertexProgress.value = 100.0 * P / selarray.count--CreateProgressBar
if (keyboard.EscPressed==true) then exit
P+=1
-----进度条end-----
)
)
)
)
-- 显示 UI 对话框
createDialog 破碎线条检测工具