Fracture Voronoi

292 votes
Version: 
1.1

This script breaks any mesh while preserving its volume.

Additional Info: 

v1.0: The object is broken in a number of chunks equal to 'Nb Parts' to the power of 'Iterations', using Voronoi cells. The final number appears on the 'Break' button.
The creation process is visible in the viewport.
For a similar result, it is faster to use several iterations with a small number of parts than creating all the parts in one iteration.
Note that the original object is just hidden, not deleted.

v1.1: In this version, the code has been improved and runs much faster. But there is no viewport feedback any more.
Materials:
- the outer faces keep their original material IDs and the new faces are assigned a unique ID. The value that appears by default is the highest ID in use (by the original object) + 1.
- mapping coordinates (if any) are preserved and somehow 'projected' onto the new faces.
- an extra planar mapping is applied to all the pieces at once and set on its own channel, typically for use with 3D procedural maps, so the pattern flows continuously from piece to piece but sticks to them when they are moved apart.
Hierarchy:
- when using several iterations, it is possible to keep the intermediate generations of parts.
- when linked, each part is parented to the one it is derived from.
- generations are set on their own layers, which are hidden except for the last one.

Enjoy :)

AttachmentSize
FractureVoronoi_v1.1.ms10.85 KB
FractureVoronoi_v1.0.ms4.67 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
MaximilianPs's picture

Left button, "save as" or

Left button, "save as" or "save object as"

Bacon's picture

Download

How do I download this? Every time I click on the link I get this: -- * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- * FRACTURE VORONOI - v1.1 - april 2009 - 3ds max 9 *
-- * *
-- * Divides an object in parts (Voronoi cells). *
-- * - several iterations; *
-- * - original UVs are preserved and 'projected' onto *
-- * the new faces; *
-- * - simple planar mapping is applied to a new channel *
-- * and consistent throughout the new parts; *
-- * - new material ID is applied to the new faces; *
-- * - can keep intermediate generations; *
-- * - can build hierarchy. *
-- * *
-- * GARP - 2009 *
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

( -- start script

global rltFractureVoronoi
try destroyDialog rltFractureVoronoi catch()

rollout rltFractureVoronoi "F.R.A.C.T.U.R.E"
(
groupBox boxSetUp "" pos:[5,0] width:116 height:83
fn geometryFilter obj = superClassOf obj == GeometryClass
pickButton pbObject "Pick Object" pos:[10,11] width:106 height:25 filter:geometryFilter tooltip:"object to fracture"
spinner spnNbParts "Nb Parts: " pos:[09,41] width:106 height:16 range:[2,1000,10] type:#integer enabled:false
spinner spnNbIter "Iterations: " pos:[28,61] width:87 height:16 range:[1,10,1] type:#integer enabled:false

groupBox boxMat "" pos:[5,81] width:116 height:89
spinner spnNewID "New Mat ID:" pos:[24,93] width:91 height:16 range:[1,100,1] indeterminate:true type:#integer enabled:false
checkBox cbKeepMat "Keep Material" pos:[12,110] checked:true enabled:false
spinner spnNewCh "New Map Ch:" pos:[32,133] width:83 height:16 range:[1,10,3] type:#integer enabled:false
checkBox cbRWMS "R-W Map Size" pos:[12,150] checked:true enabled:false

groupBox boxHierarchy "" pos:[5,168] width:116 height:48
checkBox cbKeepGen "Keep Iterations" pos:[12,179] checked:false enabled:false
checkBox cbLinkGen "Build Hierarchy" pos:[12,196] checked:false enabled:false

groupBox boxCreate "" pos:[5,214] width:116 height:109
button btnCreate "Break in 10" pos:[10,225] width:106 height:25 tooltip:"pick object first" enabled:false
radiobuttons rdoColor "" pos:[12,253] width:72 height:32 labels:#("Multi Color","Uniform") default:1 columns:1 enabled:false
colorPicker cpParts "" pos:[70,270] fieldWidth:20 height:12 visible:false
radiobuttons rdoCenter "" pos:[12,288] width:72 height:32 labels:#("B.Boxes Centers","Vo.Cells Centers") default:1 columns:1 enabled:false

groupBox boxProgress "" pos:[5,321] width:116 height:49
progressBar pbProgress "" pos:[10,335] width:106 height:15 value:0 color:[0,96,0]
label lblProStatus "" pos:[10,351] width:100 height:17

local theObject -- holds the original object

on pbObject picked obj do
(
pbObject.text = obj.name
theObject = obj
spnNbParts.enabled = true
spnNbIter.enabled = true
spnNewID.enabled = true
cbKeepMat.enabled = true
spnNewCh.enabled = true
cbRWMS.enabled = true
cbLinkGen.enabled = true
btnCreate.enabled = true
btnCreate.tooltip = "start creating parts"
rdoColor.enabled = true
rdoCenter.enabled = true
cpParts.color = obj.wireColor
cpParts.visible = true

when obj deleted do
(
btnCreate.enabled = false
btnCreate.tooltip = pbObject.text + " has been deleted!"
pbObject.text = "Pick Object"
)

undo off
( -- gets new mat ID for new faces
m = edit_mesh()
addModifier obj m
spnNewID.value = amax(for i = 1 to obj.numfaces collect getFaceMatID obj i) + 1
deleteModifier obj m
)

) -- end on btnMesh picked theMesh

on btnCreate pressed do
(
undo off
(
disableSceneRedraw()
clearSelection()
start = timeStamp()

local nbParts = spnNbParts.value
local nbIter = spnNbIter.value
local keepGen = cbKeepGen.checked
local linkGen = cbLinkGen.checked
local aPartsStart = #()
local aPartsEnd = #()
local aAllParts = #()
local aAllCoords = #()
local thePlane = plane width:1 length:1 widthSegs:1 lengthSegs:1 -- plane helper for slice plane
local theMesh = editable_mesh()
local abortBreaking = false

lblProStatus.caption = " Breaking..."

-- BREAKING UP
---------------

-- clean copy (no custom attributes, keyframes, weird transforms, etc
theCopy = copy theObject
theCopy.name = "toto"
resetXForm theCopy
convertToMesh theCopy
theMesh.mesh = theCopy.mesh
theMesh.transform = theCopy.transform
theMesh.pivot = [0,0,0]
resetXForm theMesh
convertToMesh theMesh
delete theCopy

-- material and UVs
if cbKeepMat.checked do theMesh.material = theObject.material
addModifier theMesh (uvwMap mapChannel:spnNewCh.value realWorldMapSize:cbRWMS.checked)
convertToMesh theMesh
setFaceSelection theMesh #{}

-- parts creation
aPartsEnd = #(theMesh)
for iter = 1 to nbIter while not abortBreaking do
(
aPartsStart = aPartsEnd
aPartsEnd = #()

for obj in aPartsStart while not abortBreaking do
(
aPartsTemp = for i = 1 to nbParts collect copy obj
pSys = pcloud emitter:obj formation:3 total_number:nbParts quantityMethod:1 viewPercent:100 seed:(random 0 100)
aCoords = for i = 1 to nbParts collect particlePos pSys i -- fill with random coordinates
delete pSys
for i = 1 to nbParts - 1 do for j = i + 1 to nbParts while not abortBreaking do -- for each pair of coords
(
thePlane.pos = (aCoords[i] + aCoords[j]) / 2
thePlane.dir = aCoords[j] - aCoords[i]

addModifier aPartsTemp[i] (sliceModifier slice_type:2)
addModifier aPartsTemp[j] (sliceModifier slice_type:3)
aPartsTemp[i].slice.slice_plane.transform = thePlane.transform
aPartsTemp[j].slice.slice_plane.transform = thePlane.transform
addModifier aPartsTemp[i] (cap_holes())
addModifier aPartsTemp[j] (cap_holes())
convertToMesh aPartsTemp[i]
convertToMesh aPartsTemp[j]

if keyboard.escPressed do abortBreaking = queryBox "Do you want to abort and delete already created parts?"
) -- end i loop
aPartsEnd += aPartsTemp
aAllParts += aPartsTemp
aAllCoords += aCoords

total = nbParts * ((nbParts^nbIter - 1) / (nbParts - 1))
prog = 100 * aAllParts.count / total
pbProgress.value = prog
pbProgress.color = [200 - prog * 2,prog * 2,0]
) -- end obj loop
) -- end iter loop

if not abortBreaking then
(
lblProStatus.caption = " Finalizing..."

-- TIDYING UP
--------------

delete theMesh
delete thePlane
hide theObject

-- intermediate generations
if not keepGen and nbIter != 1 do
(
ind = 0
for i = 1 to nbIter - 1 do for j = 1 to nbParts^i do
(
ind += 1
delete aAllParts[ind]
aAllCoords[ind] = undefined
)
aAllParts = for obj in aAllParts where not isDeleted obj collect obj
aAllCoords = for c in aAllCoords where c != undefined collect c
)

-- coordinates
if rdoCenter.state == 1 then centerPivot aAllParts
else for i = 1 to aAllParts.count do aAllParts[i].pivot = aAllCoords[i]
resetXForm aAllParts
convertToMesh aAllParts

-- new faces ID
newID = spnNewID.value
for obj in aAllParts do
(
for f in getFaceSelection obj do setFaceMatID obj f newID
setFaceSelection obj #{}
)

-- names
if not keepGen or nbIter == 1 then
for i = 1 to aAllParts.count do aAllParts[i].name = theObject.name + "_Part_" + i as string
else
(
for i = 1 to nbParts do aAllParts[i].name = theObject.name + "_Part_" + i as string
indP = 0
indC = nbParts
for i = 1 to nbIter - 1 do for j = 1 to nbParts^i do
(
indP += 1
for k = 1 to nbParts do
(
indC += 1
aAllParts[indC].name = aAllParts[indP].name + "_" + k as string
) -- end k loop
) -- end j loop
) -- end else

-- layers
-- (comment out this block if you don't want any layer, intermediate generations will not be hidden)
-- (FROM HERE...)
if not keepGen or nbIter == 1 then
(
if layerManager.getLayerFromName (theObject.name + "_Parts") == undefined then
theLayer = layerManager.newLayerFromName (theObject.name + "_Parts")
else theLayer = layerManager.getLayerFromName (theObject.name + "_Parts")
for obj in aAllParts do theLayer.addNode obj
) -- end if
else
(
aTheLayers = for i = 1 to nbIter collect
(
if layerManager.getLayerFromName (theObject.name + "_Gen_" + i as string) == undefined then
layerManager.newLayerFromName (theObject.name + "_Gen_" + i as string)
else layerManager.getLayerFromName (theObject.name + "_Gen_" + i as string)
)
for i = 1 to nbIter - 1 do aTheLayers[i].isHidden = true
ind = 0
for i = 1 to nbIter do for j = 1 to nbParts^i do
(
ind += 1
aTheLayers[i].addNode aAllParts[ind]
) -- end i loop
) -- end else
-- (...TO HERE)

-- hierarchy
if linkGen do
(
if not KeepGen or nbIter == 1 then for obj in aAllParts do attachObjects theObject obj move:false
else
(
for i = 1 to nbParts do attachObjects theObject aAllParts[i] move:false
indP = 0
indC = nbParts
for i = 1 to nbIter - 1 do for j = 1 to nbParts^i do
(
indP += 1
for k = 1 to nbParts do
(
indC += 1
attachObjects aAllParts[indP] aAllParts[indC] move:false
) -- end k loop
) -- end j loop
) -- end else
) -- end if linkGen

-- colors
if rdoColor.state == 1 then for obj in aAllParts do obj.wireColor = random black white
else aAllParts.wireColor = cpParts.color

lblProStatus.caption = " Done in " + (formattedPrint ((timeStamp() - start) / 1000.0) format:".1f") + "sec."

enableSceneRedraw()
completeRedraw()
)
else
(
delete thePlane
delete theMesh
delete aAllParts
pbProgress.value = 0
lblProStatus.caption = " Stopped"
enableSceneRedraw()
) -- end test abortBreaking

) -- end undo off

) -- end btnCreate pressed

on spnNbParts changed val do
(
btnCreate.caption = "Break in " + ((val ^ spnNbIter.value) as string)
)

on spnNbIter changed val do
(
btnCreate.caption = "Break in " + ((spnNbParts.value ^ val) as string)
cbKeepGen.enabled = val != 1
)

on rltFractureVoronoi close do
(
enableSceneRedraw()
CompleteRedraw()
callbacks.removeScripts id:#FVcbID01
)

) -- end rollout rltFractureVor

createDialog rltFractureVoronoi 126 375 60 130

) -- end script

robobear510's picture

vorks fine on 2015 - now this

works fine on 2015 - now this is what I realised so far, there are at least 5 more great free scripts or plugins that I constantly add to every version of max - like this one - max doesn't offer anything similar to this one - and it offers voronoi geometry generation

- it's like, why don't they just pay you 0.01% of their revenue and buy you plugin and pay the support off of you guys, you would be much happier, and max customers would be even more happier not needing to update - or for newbies, even more fetures

- I guess the corporations are really really slow, and this is how it works - after 20 or so versions max finally got out an outliner that c4d, modo and almost any other package has.. and it's one of the most expensive softwares out there - and still you cannot open more than one file inside of it - like in any other software package - and not to mention the start up times - the longest of any software package, ever - and bugs that go back to version 4

- and the fact they mentioned that "look see we have new features, we're not gonna shut it down" looks just like they want to shut it down in a few more versions - and who is going to decide that - a manager that just needs to keep percentages up year after year, not the same earnings, more earnings, he gets payed just for that, if he doesn't do it, someone else will

- if more money comes out of Maya - they will switch to just Maya - there is no logical reason for them to keep a software that earns less, like with softimage, doesn't matter what the community thinks or feels, any corporation does this - it turns into a headless monster, their products are not for humans, the products are for reproducing more moneyz

.. anyway, here's one rant

- and a great intuitive plugin you have there just keep it updatin :)

Midge_S's picture
dbrooksie7's picture

Thank you!

Thank you!

Garp's picture

Hey mariss.

Use VoroFrag instead. It's way better and faster.

mariss274's picture

Flat Objects

I have been using 3D max in school and I am currently using Fracture Voronoi and massfx in a project. My project is a blender that blends up different types of fruit when they are dropped in. Everything has gone well so far except Voronoi will only break up my blueberries which are spheres. When I apply it to my apples, strawberries and raspberries, it gives me a bit of trouble. The apples, strawberries and raspberries are organic shapes because I had to move vertices to create the look. Voronoi causes the apples to go flat and the other to berries to shrink.

Would anyone be able to help me fix this?

Thank you,
Marissa

svet_lana_kouz's picture

How to install the script in 3ds max

I couldn't find either any information about installation of the fracture voronoi script. I installed it as follows: opened my 3ds max, chose MAXScrip Menu and New Scrip there. I copies and pasted all the script text there and saved it in \Programm Files\Autodesk\3ds max**\Scripts as facture_voronoi_v1.1.ms. Closed "New Script" window. To run the script I chose MAXScript menu, clicked "Run Script" and chose the saved file. Hope, my experience can be of any use to somebody. Good luck!

Evandro_ebs's picture

how do I download the file?

how do I download the file?
This page appearing when I click on this file.

http://www.scriptspot.com/files/FractureVoronoi_v1.1.ms

fadly lilik's picture

why I can not take Voronoi

why I can not take Voronoi Fracture. . . whether due to my ignorance. . . Can you help

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.