CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 06-21-2005, 12:05 AM   #1
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
CgTalk Maxscript Challenge 002: "Split it up"

CgTalk Maxscript Challenge 002: "Split it up"

DESCRIPTION: Create an object splitter that has options to randomly or evenly split an object into seperate polys.
INTERMEDIATE SCRIPTERS: Add dimension to the chunks. Create new polys from the split ones.
ADVANCED SCRIPTERS: Split the object up into more pieces than there are polys in the original object, and add dimension to the pieces. If you have time, throw in an explosion or physics effect.

RULES:

  • Must be code only. No pre-setup scenes.
  • Code from scratch. Try not to use pre-exisitng functions or plugins.
  • Show your script references, if any (eg. Looking at another script to assist you).
  • You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.
  • Post your final script inside [CODE] tags (located on your posting toolbar).
  • Post all code into THIS thread.
NOTES: I believe this type of script has been written before, but I wanted to give beginners a chance to start working with editPoly/Mesh functions. The advanced ones are for people who want more of a challenge.
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 06-21-2005, 06:27 PM   #2
ivanisavich
Some kind of robot
 
ivanisavich's Avatar
Tyson Ibele
Animator
MAKE LLC.
Toronto, Canada
 
Join Date: Nov 2002
Posts: 3,095
I'm not sure if this is what the script is supposed to do...but I wrote this today anyways

Basically...it takes apart a mesh similar to the way the "explode" spacewarp does (ie...detached individual polys, or groups of polys)...only this one can also extrudes faces for chunkiness

Problems (I'm still new to the scripting game so there are a few)

-extruded faces extude outwards (not inwards) due to issues with the face normals I was having
-there's no option to split the mesh apart "evenly" or "randomly" as in the challenge guidelines...it simply breaks it apart into groups of faces (the number of faces in each group can be specified in a spinner in the UI)
-I couldn't figure out a way to create backfacing for the detached polys...so I just used the "capholes" function to ensure everything is 2-sided/capped....therefore if your chunks are set to be really thick...the backface mesh can look weird (not necessarily a bad thing though, just very unprecise)

As reference, I used the maxscript helpfiles that come with max.

Code:
utility splitter "Object Splitter" ( rollout splitroll "Object Splitter" width:162 height:52 ( local amount1 = bezier_float() global chunk1 = bezier_float() button split "Split Selected Object" pos:[12,10] width:140 height:26 spinner amount "Extrude amount: " range: [.01,100,1] controller:amount1 spinner chunk "Chunk size: " type:#integer range: [1,100,1] controller:chunk1 on split pressed do ( sel = selection[1] if sel != undefined then ( namecount = 0 obj1 = sel convertto obj1 editable_poly faces = polyop.getnumfaces obj1 print ((faces as string) + " faces in " + (sel as string)) print chunk1.value for t in 1 to faces by (chunk1.value as integer) do ( namecount += 1 name1 = ("explode_obj" + (namecount as string)) if t+(chunk1.value-1) >= faces then ( face_array = #{t..faces} ) else ( face_array = #{t..(t+(chunk1.value-1))} ) polyop.detachfaces obj1 face_array delete:false asnode:true name:name1 node:[0,0,0] name2 = $*explode_obj*[namecount] print name2 polyop.extrudefaces name2 #all amount1.value polyop.capholesbyface name2 #all name2.pivot = name2.center ) delete obj1 ) else print "No selection" ) ) on splitter open do ( addrollout splitroll chunk1.value = 1 amount1.value = 1 ) )


Go easy on it ....it's only the 3rd script I've written. Btw...Thanks for these challenges erilaz...they're great practice!
__________________
http://www.tysonibele.com

Last edited by ivanisavich : 06-21-2005 at 06:30 PM.
 
Old 06-22-2005, 05:44 PM   #3
j-man
in 3D!
 
j-man's Avatar
portfolio
Joshua Newman
Director
MESHROOM
London, United Kingdom
 
Join Date: Apr 2005
Posts: 1,345
Send a message via MSN to j-man
Hello,

I've taken different interpretation, and split the object into evenly divided chunks based on number of division in the x, y, z, axis (I know this has been done before). It's good Eploy practice for me.
The code could be optimize a lot, removing repeated code using functions, and also limiting the capping to search though faces that actually need capping. It could also be turned into a macroscript, but I didn't really see the point.
I've included features like predicting the number of objects and faces that will be created, and a progress bar sine the process is quite slow.
Haven't really had much time to spend on this one, and probably spent to much anyway, about 3hrs plus a bt of messing around the other night when I was thinking about how I would do it (i was thinking more about explode then).

Nice work ivanisavich, and thanks again to erilaz.

One question: how can I post my code so I don't lose the formatting (in this case the tabs), if I paste from MXS I get double spacing.

oh, and I've also attached a function I use regulary (since footools left us) to explode polys into elements, works on an EMesh

J.

**********************
It looks like I've had problems with uploading one line of code to the webboard, so I've changed some variable names and uploaded the code again.
**********************

Code:
-------------------------------------------------------------------------------- -- CGTalk Challenge 2 - Divide Object -- version 1.0 -- max version 6, 7 -- written by Joshua Newman -- www.joshuanewman.net -- written 22/06/05 -- last updated 22/06/05 -- copyright 2005 -------------------------------------------------------------------------------- -- -- divides an editable poly into any (ok up to 100 each axis) objects global obj, pgttl rollout CGTalk_divider "Parameters" ( -- Functions fn objfilter obj=classof obj==Editable_Poly -- Rollout items pickbutton pobj "Pick Editable Poly!" width:240 filter:objfilter group "Segments" ( spinner xd "X objects:" type:#integer range:[1,100,2] spinner yd "Y objects:" type:#integer range:[1,100,2] spinner zd "Z objects:" type:#integer range:[1,100,2] label objnum "objects:8" align:#right label fcenum "faces:0" align:#right ) checkbox obox "original to boxmode" checked:false across:2 checkbox ohde "hide original" checked:true offset:[28,0] button go "Divide" width:240 height:50 enabled:false progressbar prgrss "" color:red label l1 "\xa9 2005 Joshua Newman" across:2 offset:[-8,0] hyperlink hl "www.joshuanewman.net" address:"www.joshuanewman.net" offset:[4,0] -- rollout functions fn updatedisplay c= ( pgttl=(zd.value*yd.value*xd.value) objnum.text=("Objects:"+pgttl as string) if obj!=undefined then ( fcenum.text=("faces:"+(obj.numfaces*pgttl) as string) ) ) -- rollout events on xd changed c do updatedisplay c on yd changed c do updatedisplay c on zd changed c do updatedisplay c on pobj picked o do ( obj=o pobj.text=obj.name go.enabled=true ) on CGTalk_divider open do ( -- this routine scans the current selection to look for a likely source object, and if it finds one, it places it in the settings for s in selection do ( if classof s==Editable_Poly then ( pobj.text=s.name obj=s print s go.enabled=true fcenum.text=("faces:"+(obj.numfaces*8) as string) exit ) ) ) -- the start of the prcess on go pressed do ( -- get the parameter values into variables xdiv=xd.value ydiv=yd.value zdiv=zd.value -- the objects vital statistics size=obj.max-obj.min zval=size.z*1./zdiv yval=size.y*1./ydiv xval=size.x*1./xdiv -- check the hide and boxmode settings and act as appropriate if obox.state then obj.boxmode=true -- make the origianl object display in boxmode if ohde.state then hide obj -- hide the original object -- some variables zobj=#() yobj=#() xobj=#() -- progressbar pgvlu=0 -- Z slice! for i=1 to zdiv do ( local tmp=copy obj polyop.slice tmp tmp.faces (ray [obj.pos.x,obj.pos.y,obj.min.z+zval*(i-1)] [0,0,1]) -- slice bottom segment polyop.slice tmp tmp.faces (ray [obj.pos.x,obj.pos.y,obj.min.z+zval*i] [0,0,1]) -- slice top segment fces=for i in tmp.faces collect i.index -- collect the faces into an array dlfcs=#() for f in fces do if (polyop.getfacecenter tmp f).z<(obj.min.z+(zval*(i-1))) then append dlfcs f -- collect the faces below the slice for f in fces do if (polyop.getfacecenter tmp f).z>(obj.min.z+(zval*i)) then append dlfcs f -- collect the faces above the slice if dlfcs.count>0 then polyop.deletefaces tmp (dlfcs as bitarray) delisoverts:true -- if the list isn't emply, delete the faces polyop.capholesbyface tmp (tmp.faces as bitarray) -- cap holes! - this is using all faces! could be costly on large polys append zobj tmp pgvlu+=1 -- increase the progress prgrss.value=100./pgttl*pgvlu -- update the progressbar ) -- Y slice for z in zobj do ( for i=1 to ydiv do ( local tmp=copy z polyop.slice tmp tmp.faces (ray [obj.pos.x,obj.min.y+yval*(i-1),obj.pos.z] [0,1,0]) -- slice bottom segment polyop.slice tmp tmp.faces (ray [obj.pos.x,obj.min.y+yval*i,obj.pos.z] [0,1,0]) -- slice top segment fces=for i in tmp.faces collect i.index -- collect the faces into an array dlfcs=#() for f in fces do if (polyop.getfacecenter tmp f).y<(obj.min.y+(yval*(i-1))) then append dlfcs f -- collect the faces below the slice for f in fces do if (polyop.getfacecenter tmp f).y>(obj.min.y+(yval*i)) then append dlfcs f -- collect the faces above the slice if dlfcs.count>0 then polyop.deletefaces tmp (dlfcs as bitarray) delisoverts:true -- if the list isn't emply, delete the faces polyop.capholesbyface tmp (tmp.faces as bitarray) -- cap holes! - this is using all faces! could be costly on large polys append yobj tmp pgvlu+=1 -- increase the progress prgrss.value=100./pgttl*pgvlu -- update the progressbar ) ) -- X slice for y in yobj do ( for i=1 to xdiv do ( local tmp=copy y polyop.slice tmp tmp.faces (ray [obj.min.x+xval*(i-1),obj.pos.y,obj.pos.z] [1,0,0]) -- slice bottom segment polyop.slice tmp tmp.faces (ray [obj.min.x+xval*i,obj.pos.y,obj.pos.z] [1,0,0]) -- slice top segment fces=for i in tmp.faces collect i.index -- collect the faces into an array dlfcs=#() for f in fces do if (polyop.getfacecenter tmp f).x<(obj.min.x+(xval*(i-1))) then append dlfcs f -- collect the faces below the slice for f in fces do if (polyop.getfacecenter tmp f).x>(obj.min.x+(xval*i)) then append dlfcs f -- collect the faces above the slice if dlfcs.count>0 then polyop.deletefaces tmp (dlfcs as bitarray) delisoverts:true -- if the list isn't emply, delete the faces polyop.capholesbyface tmp (tmp.faces as bitarray) -- cap holes! - this is using all faces! could be costly on large polys append xobj tmp pgvlu+=1 -- increase the progress prgrss.value=100./pgttl*pgvlu -- update the progressbar ) ) -- remove the temporary slices delete zobj delete yobj prgrss.value=0 -- reset progress bar select xobj -- select new objects ) ) newroll=newrolloutfloater "CGTalk - Challenge 2 - Divider." 260 302 750 80 addrollout CGTalk_divider newroll
__________________
www.joshuanewman.net

Last edited by j-man : 06-30-2005 at 12:58 PM.
 
Old 06-22-2005, 05:46 PM   #4
j-man
in 3D!
 
j-man's Avatar
portfolio
Joshua Newman
Director
MESHROOM
London, United Kingdom
 
Join Date: Apr 2005
Posts: 1,345
Send a message via MSN to j-man
sorry, attachment:

J.
__________________
www.joshuanewman.net
 
Old 06-22-2005, 09:31 PM   #5
ivanisavich
Some kind of robot
 
ivanisavich's Avatar
Tyson Ibele
Animator
MAKE LLC.
Toronto, Canada
 
Join Date: Nov 2002
Posts: 3,095
Wow...Fantastic work j_man! Your script worked great! A couple of minor errors popped up...but no big deal it still did what it needed to do.

As for mine....I updated it a bit....still no where near the quality of yours ....but now it's a bit more intuitive...and the faces extrude inward instead of outward.

http://www.theonlyt.com/Main/Scripts/splitter.ms
__________________
http://www.tysonibele.com
 
Old 06-23-2005, 12:19 AM   #6
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
Guys, fantastic work so far! I'm still nutting out a decent method myself!

Can you please keep to the rule of posting your code in [code] tags, rather than an attachment? It makes it easier for people to see the code at face value, and then copy/paste it if they want to run it.
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 06-23-2005, 02:56 AM   #7
ivanisavich
Some kind of robot
 
ivanisavich's Avatar
Tyson Ibele
Animator
MAKE LLC.
Toronto, Canada
 
Join Date: Nov 2002
Posts: 3,095
Sorry Erilaz....I figured wasting more forum space with my updated code would be pointless since not too many things were changed.
__________________
http://www.tysonibele.com
 
Old 06-23-2005, 03:00 AM   #8
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
Quote:
Originally Posted by ivanisavich
Sorry Erilaz....I figured wasting more forum space with my updated code would be pointless since not too many things were changed.


Not a problem. In fact, it would be preferable for you to repost your code and highlight what you've changed. The changes are the important part. The challenges are here to encourage thinking about new ways of using maxscript, and since this is all text you can fill the thread as much as you like (within reason, of course!)
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 06-23-2005, 03:12 AM   #9
ivanisavich
Some kind of robot
 
ivanisavich's Avatar
Tyson Ibele
Animator
MAKE LLC.
Toronto, Canada
 
Join Date: Nov 2002
Posts: 3,095
K cool

Code:
global amount1 = bezier_float() --threw these 2 initializations up here to avoid errors global chunk1 = bezier_float() rollout splitroll "Object Splitter" width:162 height:52 ( button split "Split Selected Object" pos:[25,10] width:140 height:26 spinner amount "Extrude amount: " range: [.01,100,1] controller:amount1 spinner chunk "Chunk size: " type:#integer range: [1,100,1] controller:chunk1 button del "Delete ALL chunks" --new button was added for housecleaning :) on split pressed do ( sel = selection[1] if sel != undefined then ( namecount = 0 obj1 = sel convertto obj1 editable_poly faces = polyop.getnumfaces obj1 print ((faces as string) + " faces in " + (sel as string)) if chunk1.value >= faces then chunk1.value = (faces-1) for t in 1 to faces by (chunk1.value as integer) do ( namecount += 1 name1 = ("temp_obj" + (namecount as string)) --to avoid duplication problems later on, chunks that are being split in this loop are given a temporary name while the loop is in progress if t+(chunk1.value) > faces then ( face_array = #{t..faces} ) else ( face_array = #{t..(t+(chunk1.value-1))} ) polyop.detachfaces obj1 face_array delete:false asnode:true name:name1 node:[0,0,0] name2 = $*temp_obj*[namecount] count = polyop.getnumfaces name2 for i in 1 to count do ( verts_array = polyop.getfaceverts name2 i --different method of capping holes in this update...still some issues when chunks are made from a group of 3 faces or more...but whatever :P polyop.capholesbyvert name2 verts_array ) count2 = polyop.getnumfaces name2 polyop.extrudefaces name2 #{(count+1)..count2} (amount1.value) --faces are now extruded properly name2.pivot = name2.center ) select $*temp_obj* namecount = 0 for j in selection do ( namecount += 1 j.name = "explode_obj" + (namecount as string) --this loop renames the temp objects to their proper names ) deselect $ delete obj1 ) else print "No selection" ) on del pressed do ( try ( delete $explode_obj* --deletes all chunks (if they are present) ) catch () ) on splitroll open do ( amount1.value = 1 chunk1.value = 1 ) ) splitter=newrolloutfloater "Object Splitter" 200 143 650 300 --splitter script is now a floater instead of utility. Thanks for the idea on that one j_man! addrollout splitroll splitter
__________________
http://www.tysonibele.com
 
Old 06-23-2005, 07:37 PM   #10
JHaywood
Know-it-All
 
JHaywood's Avatar
portfolio
James Haywood
Senior Technical Artist
Bungie Studios
Seattle, USA
 
Join Date: Jun 2005
Posts: 395
Hey Josh,

I get this error when trying to change the X spinner:
-- Error occurred in updateDisplay()
-- Frame:
-- xdivision: undefined
-- S: undefined
-- c: 3
-- called in xdivisions.changed()
-- Frame:
-- c: 3
>> MAXScript Rollout Handler Exception: -- Type error: Call needs function or class, got: undefined <<

And this one if I don't touch the defaults and just hit "Divide":
-- Error occurred in i loop
-- Frame:
-- tmp: $Editable_Poly:Plane02 @ [1523.483398,-0.000044,1002.226563]
-- i: 1
-- dlfcs: #(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
-- fces: #(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...)
-- called in go.pressed()
-- Frame:
-- xdiv: 2
-- yobj: #()
-- yval: 7.35278e-006
-- pgvlu: 1
-- zval: 168.212
-- zobj: #($Editable_Poly:Plane02 @ [1523.483398,-0.000044,1002.226563])
-- zdiv: 2
-- xobj: #()
-- size: [1160.66,1.47056e-005,336.424]
-- ydiv: 2
-- xval: 580.331
>> MAXScript Rollout Handler Exception: -- Incompatible types: 100.0, and undefined <<

It looks very well organized though.
__________________
Website
Blog
 
Old 06-23-2005, 10:44 PM   #11
JHaywood
Know-it-All
 
JHaywood's Avatar
portfolio
James Haywood
Senior Technical Artist
Bungie Studios
Seattle, USA
 
Join Date: Jun 2005
Posts: 395
Okay, I'm jumping in to this one. The script is fairly simple right now, but I plan on beefing it up as I find the time. This could be very handy for effects work.

How to work it:
- Run the script.
- Select an editable poly object with lots of polys.
- Crank up the "Crack Factor", the higher the number, the bigger the chunks. Beware that if your object has tons of polys and the crack factor is kept too low, it could take a while to process.
- Set the "Thickness" value to something other than 0 to add an edge to the chunks.
- Hit "Do It!" to crack up the object.

I'll be adding more options and trying to optimize it later, but this is a good first pass.

Code:
fn growSelectionByRandomEdge obj faceNum numTimes = ( local faceArr = #(faceNum) for t = 1 to numTimes do ( local edgeArr = (polyOp.getEdgesUsingFace obj faceArr) as array n = edgeArr.count / 2 for j = n to 1 by -1 do ( ranNum = random 1 n deleteItem edgeArr ranNum ) tempArr = (polyOp.getFacesUsingEdge obj edgeArr) as array for j = 1 to tempArr.count do (append faceArr tempArr[j]) ) return faceArr as array ) rollout crackMeUpRlt "Crack Me Up" ( button doItBtn "DO IT!" width:125 height:30 spinner crackFactorSpnr "Crack Factor:" range:[1,1000000,10] type:#integer offset:[0,10] width:110 align:#right spinner thicknessSpner "Thickness:" range:[0,1000000,10] width:100 align:#right on doItBtn pressed do ( obj = selection[1] if obj != undefined and classof obj == Editable_Poly then ( crackFactor = crackFactorSpnr.value crackObjArr = #() numFacesStart = getNumFaces obj setWaitCursor() with undo "CrackMeUp" on ( for i = numFacesStart to 1 by -1 do ( numFaces = getNumFaces obj if numFaces == 0 then exit detachArr = growSelectionByRandomEdge obj numFaces crackFactor polyOp.detachFaces obj detachArr asNode:true name:(uniqueName obj.name) objArr = objects as array append crackObjArr objArr[objArr.count] ) delete obj for i in crackObjArr do ( i.wirecolor = [(random 0 255),(random 0 255),(random 0 255)] i.pivot = i.center if thicknessSpner.value != 0 then ( pushMod = Shell() addModifier i pushMod pushMod.innerAmount = thicknessSpner.value ) collapseStack i ) ) -- end undo setArrowCursor() ) else ( -- end if classof obj messagebox "Selected object needs to be a collapsed Editable Poly." ) ) -- end doItBtn pressed ) -- end rollout createDialog crackMeUpRlt width:150 pos:[40,80]
__________________
Website
Blog

Last edited by JHaywood : 06-24-2005 at 12:35 AM.
 
Old 06-24-2005, 07:44 PM   #12
Tughan
Brigadier General
 
Tughan's Avatar
portfolio
Tughan Arslan
Character Animator
Bodrum, Turkey
 
Join Date: Jan 2003
Posts: 455
Send a message via MSN to Tughan
Cool Behold! here comes the Maxscript master!

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.

Code:
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 delete
__________________
www.tughan.com
|-Character Animator-|
_____________________________
WIP: Mouse Short <--*NEW*
AJ - Private Detective ShortFilm
 
Old 06-24-2005, 10:00 PM   #13
JHaywood
Know-it-All
 
JHaywood's Avatar
portfolio
James Haywood
Senior Technical Artist
Bungie Studios
Seattle, USA
 
Join Date: Jun 2005
Posts: 395
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.
__________________
Website
Blog
 
Old 06-25-2005, 02:20 AM   #14
Rivendale
Right here
 
Rivendale's Avatar
portfolio
Carl-Mikael Lagnecrantz
CG artist
Stockholm, Sweden
 
Join Date: Apr 2002
Posts: 1,338

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
__________________
PolyBoost Tools for 3ds max
 
Old 06-25-2005, 11:02 AM   #15
Rivendale
Right here
 
Rivendale's Avatar
portfolio
Carl-Mikael Lagnecrantz
CG artist
Stockholm, Sweden
 
Join Date: Apr 2002
Posts: 1,338

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):
Code:
--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...\nIt 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
__________________
PolyBoost Tools for 3ds max

Last edited by Rivendale : 10-02-2005 at 06:43 PM.
 
Thread Closed share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 04:26 AM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.