Notifications
Clear all

[Closed] CgTalk Maxscript Challenge 002: "Split it up"

Hey, this is fun! The only thing more fun than maxscripting (and rigging) is poking your eye with a pencil.

Ok, I just recently got into scripting stuff, and just had my “script related” nightmare a few weeks ago. So pease guys, let me pretend to be a Maxscript master, before “Bobo” shows up. LOL.

Well… first, it only works on Teapots heh heh… and not every teapot too. No, It got to be model Teapot01 or it wont work. (I suppose it’s a very serious bug in core code of 3dsmax hehe) Anyway, I don’t know how to assign a unique name to a selected object, like “my beloved teapot01” so, just open a empty clean scene file and run the script. If it won’t work, it’s your foult.:applause:


Teapot radius:20 smooth:on segs:4 body:on handle:on spout:on lid:on mapcoords:on
 
$Teapot01.radius = 20
 
Bomb strength:1 gravity:1 detonation:5f minFragmentSize:1 maxFragmentSize:1 falloff:100 pos:[0,0,0]
 
bindSpaceWarp $Teapot01 $MeshBomb01
 
sliderTime = 7f
 
Mesher radius:10.0 pos:[0,0,0] isSelected:on renderTimeOnly:off
 
$Mesher01.renderTimeOnly = off
 
$Mesher01.radius = 10
 
select $Mesher01
 
$Mesher01.pick = $Teapot01
 
macros.run "Modifier Stack" "Convert_to_Poly"
 
select $Teapot01
 
max delete
 
select $MeshBomb01
 
max[size=2] delete
 
[/size]

Hey Tughan,

I haven’t actually run the script, but I can see what you’re doing. One really quick scripting tip is to assign objects you create to a variable. That way you can use that variable instead of the object’s name when you want to do anything else with it.

So instead of saying:
Teapot radius:20 smooth:on segs:4 body:on handle:on spout:on lid:on mapcoords:on
$Teapot01.radius = 20 (by the way, you already defined the radius in the first line so you don’t need this one)

You could say:
tPot = Teapot radius:20 smooth:on segs:4 body:on handle:on spout:on lid:on mapcoords:on
tPot.radius = 20

Any place you have “$Teapot01”, you would replace with “tPot”. That way it doesn’t matter what the name is and the script will actually run faster. Probably not noticable with one this small, but it’s a good habit to get into.

Hey good work so far! I have started working on a little somn wich I hope to post tomorrow.

j_man – I couldn’t get yours to work. I get the same errors as JHaywood.
CML

Ok here it goes, my version of Split It Up. Mainly it uses Slice modifiers to split up the mesh. Maybe I did a bit too much but I got caught up in it, heh. Maybe it can be useful.
Here is a screenshot of a model and the interface:

The code(formatting will probably suck):

 --Split It Up script by Carl-Mikael Lagnecrantz for CG Talk challenge-- 

global CGSplitchunks

global CGSplitpos

fn CGSplit_interface =

(

rollout CGSplitroll "Split it"

(



button splitbutt "Split" width: 62 height: 22 align:#center tooltip: "Split up model to chunks."

spinner splitspin "Levels:" range:[1,100,10] type:#integer align:#center fieldwidth:36

checkbox splitcheck "Seperate objects" checked:true

checkbox splitcheck2 "Build inner topology" checked:false

checkbox splitcheck3 "Set Material ID's" checked:true

checkbox splitcheck4 "Mess up inside!" checked:false

radiobuttons splitrad "" labels:#("Type 1","Type 2") default: 1 columns: 2 enabled:false

spinner splitspin3 "Mess amount:" range:[0.0,10000.0,0.0] align:#center fieldwidth:46 enabled:false

group "Check result:"

(

spinner splitspin2 "Move chunks:" range:[0.0,10000.0,0.0] align:#center fieldwidth:46

)



on splitcheck changed state do splitspin2.enabled = state

on splitcheck4 changed state do (splitspin3.enabled = state ; splitrad.enabled = state)

on splitbutt pressed do 

(

if selection.count == 1 and classof $ == Editable_Poly then undo off

(

setWaitcursor()

try(suspendEditing())catch()

numval = splitspin.value

polyop.setFaceSelection $.baseobject #all

distMin = $.min-$.pivot

distMax = $.max-$.pivot

for i = 1 to numval do --split up object with slice mod and cap holes

(

addmodifier $ (SliceModifier slice_type:1)

randomrot = quat (random -1.0 1.0) (random -1.0 1.0) (random -1.0 1.0) (random -1.0 1.0)

$.modifiers[#Slice].Slice_Plane.rotation = randomrot

randpos = [(random distMin.x distMax.x),(random distMin.y distMax.y),(random distMin.z distMax.z)]

$.modifiers[#Slice].Slice_Plane.position = randpos

convertTo $ Editable_Poly

polyOp.capHolesByEdge $.baseobject #all

if keyboard.escpressed == true do exit

)

try(resumeEditing())catch()

disablesceneredraw()

if splitcheck2.state == true do --build inner topology by selecting inside verts and connectiong, then removing created edges on the outside

(

inif = polyop.getFaceSelection $.baseobject

allaf = polyop.getNumFaces $.baseobject

innerf = #{1..allaf} - inif

oute = polyop.getEdgesUsingFace $.baseobject inif

polyop.setVertSelection $.baseobject (polyop.getVertsUsingFace $.baseobject innerf)

$.EditablePoly.ConnectVertices ()

oute2 = polyop.getEdgesUsingFace $.baseobject (polyop.getFaceSelection $.baseobject)

polyop.setEdgeSelection $.baseobject (oute2-oute)

$.remove selLevel:#Edge

)

if splitcheck3.state == true do --set material ID's

(

inif = polyop.getFaceSelection $.baseobject

polyOp.setFaceMatID $.baseobject inif 1

allaf = polyop.getNumFaces $.baseobject

inf = #{1..allaf} - inif

polyOp.setFaceMatID $.baseobject inf 2

)

if splitcheck4.state == true do --mess up inside by tesselating the inside faces and moving the resulting verts randomly

(

$.tesselateBy = splitrad.state - 1

inif = polyop.getFaceSelection $.baseobject

allaf = polyop.getNumFaces $.baseobject

inf = #{1..allaf} - inif

polyop.setFaceSelection $.baseobject inf

polyOp.tessellateByFace $.baseobject inf

polyOp.tessellateByFace $.baseobject (polyop.getFaceSelection $.baseobject)

allef = polyop.getNumFaces $.baseobject

ino = #{1..allef} - (polyop.getFaceSelection $.baseobject)

allav = polyop.getNumVerts $.baseobject

innv = #{1..allav} - (polyop.getVertsUsingFace $.baseobject ino)

for w in innv do

(

randvec = normalize ([(random 0.0 10.0),(random 0.0 10.0),(random 0.0 10.0)] - [(random 0.0 10.0),(random 0.0 10.0),(random 0.0 10.0)])

curp = polyop.getVert $.baseobject w node:$

polyop.setVert $.baseobject w (curp + (randvec * splitspin3.value)) node:$

)

)

if splitcheck.state == true then --explode elements to seperate objects

(

Selobj = $

splitval = 0

max select all

while splitval == 0 do --get a random face and detach the element wich the face is on, then select a new random face and so on until there is no faces left

(

elmf = polyop.getElementsUsingFace Selobj.baseobject 1

polyOp.detachFaces Selobj.baseobject elmf delete:true asNode:true node:Selobj

if (polyop.getNumFaces Selobj.baseobject) == 0 do (splitval = 1 ; delete Selobj)

if keyboard.escpressed == true do (splitval = 1 ; delete Selobj)

)

max select invert

CGSplitchunks = selection as array --put all the chunks into an array for later moving

CGSplitpos = for p in CGSplitchunks collect p.pos --put the positions of all chunks into an array

)

else (CGSplitchunks = #() ; CGSplitpos = #())

enablesceneredraw()

setArrowcursor()

gc()

redrawviews()

)

else messagebox "Yes dude...
It needs to be an Editable polygon object!" title:"Split It Up!"

)

on splitspin2 changed value do undo off

(

if CGSplitchunks.count != 0 do --move all chunks

try(

selnum = 0

allpos = [0,0,0]

for d in CGSplitchunks do (selnum += 1 ; allpos += d.center)

midpos = allpos/selnum

for w = 1 to selnum do

(

levec = normalize (CGSplitchunks[w].center-midpos)

CGSplitchunks[w].pos = CGSplitpos[w] + (levec * value)

)

)catch()

)

)

CGSplitfloat = newrolloutfloater "Split It up!" 156 254 790 130

addrollout CGSplitroll CGSplitfloat

)

CGSplit_interface()


Another screenshot showing where the inside is “messed up”:

Here is the script for download too: http://hem.bredband.net/millman/SplitItUp.zip

cheers,
CML

Great work Rivendale. You almost split the viewport itself. Looking cool.

Hey James, thank you very much for the tip man. That was really a big step for me.

Now, an update for “explode it up good!” script.


foo = $
macros.run "Modifier Stack" "Convert_to_Poly"
Bomb strength:1 gravity:1 detonation:5f minFragmentSize:1 maxFragmentSize:1 falloff:100 pos: foo.pos
bindSpaceWarp foo $MeshBomb01
sliderTime = 7f
Mesher radius:10.0 pos:[0,0,0] isSelected:on renderTimeOnly:off
select $Mesher01
max modify mode
$Mesher01.pick = foo
macros.run "Modifier Stack" "Convert_to_Poly"
select foo
max delete
select $MeshBomb01
max delete

By the way, I check out Maxscript documents and some other sample scripts, and I noticed that usually variable assign names are “foo”. What’s up with foo?

Ah ye swines! I wanted to make one of those but rivendale has gone and done it the way I was going to – Looks great folks, looking forward to browsing the source codes and picking up a few nice hints.

Working on automated rigging at the moment with some tasty hand setups that you guys can crit soon

Hehe sorry bout that joconnell:P
I made a little test in reactor with the split up geometry for fun, check it out:
http://hem.bredband.net/millrider/split2.avi

CML

Good job Rivendale! I like it. Can you explain what’s going on with the “Mess up inside” part, and what the types and spinners do? I tried running it once with that option and it worked fine, then I undid that and ran it again with a lower setting, and got a system exception and Max eventually crashed. I’m guessing it’s some sort of memory error. I guess I could read through the script to figure out what’s going on, but I’m lazy.

JHaywood – Thanks. Yeah it has definetly got to do with undo and memory. Not sure if I can do very much about that. When you have high settings there is a whole lot stored in that one undo and when you run the tool a few times that starts adding up. I have noticed that there is not a problem with undo when you have lower settings like up to 10 on a standard cylinder. If you go with higher settings it’s better to perform the splitting on a new clone instead. Turning off undo will not help either since that will most certainly cause a crash. Might be a good idea to add a button to flush undo memory.

The “mess up” part tesselates the inside faces by tesselate type edge or face(just like in edit poly). The it moves the new vertices randomly by the amount in the spinner.

Also note that you can move the chunks away from each other at the bottom after applying the tool to check how the chunks look. This is also really useful when doing a thing like with Reactor since then you will not want to have the chunks interpenetrating each other.

CML

Page 2 / 5