Home Technical Talk

[Maxscript] Help applying auto smoothing to a group of objects.

polycounter lvl 7
Offline / Send Message
Steven_Oconnell polycounter lvl 7
I’ve been working away at this script for some time now, but I’m still very much in the process of trying to learn MaxScript so trying to build a rather complex script at the same time is just a tad challenging.  :P

That being said completing this script will undoubtedly save me weeks or even months depending on the project.

The problem I’m currently having is trying to get the script to Auto Smooth editable poly objects to 45°

Here’s the code. (E-Meshes are properly auto smoothing to 45° it's just E-Poly's that aren't working)

(I’ve also provided the entire script to give some better context as to what I’m working with)
&nbsp;&nbsp;&nbsp; -- This will apply the default 45° auto smooth to all selected objects<br>&nbsp;&nbsp;&nbsp; fn autosmooth45 tresh: = if selection.count == 0 then (messageBox "Select Some Objects!" title:"Warning" beep:off) else<br>&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; local poAS = polyop.autoSmooth<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; local moAS = meshop.autosmooth<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for o in selection where isKindOf o GeometryClass and not isKindOf o Targetobject do<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if o.modifiers.count != 0 then (messageBox "Please collapse modifier stack!" title:"Warning" beep:off) else<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case classof o of <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (Editable_Poly):<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; o.autoSmoothThreshold = tresh<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; o.EditablePoly.autosmooth ()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; update o<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (Editable_Mesh): (moAS o o.faces tresh ; update o)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; )
And here's the code for the button, although i doubt there's anything wrong with that. :P

&nbsp;&nbsp;&nbsp; on btn_smooth45 pressed do<br>&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; autosmooth45 tresh:45<br>&nbsp;&nbsp;&nbsp; )

For those of you who are curious I’m going to be using this script for creating content for a game called Killing Floor 2, more specifically porting maps from the first game (UE2) to the second game (UE3).

Currently I’m having to sort through thousands of objects and it’s taking me months to get the geometry into an acceptable state to be pushed into the KF2 SDK, so having this script will be a massive time saver. XD





Replies

  • Swordslayer
    Options
    Offline / Send Message
    Swordslayer interpolator
    I'd try something along the lines of

    <div>polyop.setFaceSelection o #all</div><br><div>poAS o</div><br><div>update o</div>


    Btw. you should be able to use #all instead of o.faces in the meshop method as well.
  • monster
    Options
    Offline / Send Message
    monster polycounter
    Why not apply a Smooth modifier and adjust the setting, and not worry about class difference shenanigans?
  • Steven_Oconnell
    Options
    Offline / Send Message
    Steven_Oconnell polycounter lvl 7

    Wow thanks guys that worked!

    Here’s what I got so far:

    &nbsp;&nbsp;&nbsp;&nbsp; -- This will apply the default 45° auto smooth to all selected objects<br>&nbsp;&nbsp; &nbsp;fn autosmooth45 tresh: = if selection.count == 0 then (messageBox "Select Some Objects!" title:"Warning" beep:off) else<br>&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local poAS = polyop.autoSmooth<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;local moAS = meshop.autosmooth<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for o in selection do<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if o.modifiers.count != 0 then (messageBox "Please collapse modifier stack!" title:"Warning" beep:off) else<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case classof o of <br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(Editable_Poly):<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;polyop.setFaceSelection o #all<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;poAS o<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;polyop.setFaceSelection o #none<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;update o<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;)<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(Editable_Mesh): (moAS o #all tresh ; update o)<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;)<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;)<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;)<br>&nbsp;&nbsp; &nbsp;)

    So another quick question, how would I go about making the “autoSmoothThreshold” adjustable with a spinner.

    The Max documentation says that the threshold angle is a property of the “polyop.autoSmooth” method so I assumed that I could just get away with this:

    polyop.autoSmooth (autoSmoothThreshold spn_angle.value)
    ("spn_angle" being the spinner in question)
    However that doesn’t seem to work.


  • monster
    Options
    Offline / Send Message
    monster polycounter
    The doc says autoSmoothThreshold is a property of the Editable Poly object, not the polyop.autoSmooth function. So keep this line in there: o.autoSmoothThreshold = tresh

    But I'm telling you, just use a Smooth modifier. So much less code.

    From this:
    -- This will apply the default 45° auto smooth to all selected objects fn autosmooth45 tresh: = if selection.count == 0 then (messageBox "Select Some Objects!" title:"Warning" beep:off) else ( local poAS = polyop.autoSmooth local moAS = meshop.autosmooth for o in selection where isKindOf o GeometryClass and not isKindOf o Targetobject do ( if o.modifiers.count != 0 then (messageBox "Please collapse modifier stack!" title:"Warning" beep:off) else ( case classof o of ( (Editable_Poly): ( polyop.setFaceSelection o #all poAS o update o ) (Editable_Mesh): (moAS o o.faces tresh ; update o) ) ) ) ) -- This will auto smooth with a custom value (Not working either) fn autosmoothcus tresh:spn_angle.value = if selection.count == 0 then (messageBox "Select Some Objects!" title:"Warning" beep:off) else ( local poAS = polyop.setFaceSmoothGroup local moAS = meshop.autosmooth for o in selection where isKindOf o GeometryClass and not isKindOf o Targetobject do ( if o.modifiers.count != 0 then addModifier o (messageBox "Please collapse modifier stack!" title:"Warning" beep:off) else ( case classof o of ( (Editable_Poly): (poAS o o.faces tresh add:false) (Editable_Mesh): (moAS o o.faces tresh ; update o) ) ) ) ) --This will remove all smoothing groups from all selected objects fn smoothclear = ( local numFaces = polyop.getNumfaces $ local faces = (for i in 1 to numFaces collect i) as bitarray polyOp.setFaceSmoothGroup $ faces 1 ) ... ... on btn_smooth45 pressed do ( autosmooth45 tresh:45 ) on btn_autosmooth pressed do ( autosmoothcus tresh:spn_angle.value ) on btn_clear pressed do ( smoothclear() )
    To this:
    	fn doSmooth clear:false =
    	(
    		sMod = Smooth()
    		sMod.autoSmooth = not clear
    		sMod.threshold = spn_angle.value
    		addModifier selection sMod
    		collapseStack selection
    	)
    ...
    ...
    	on btn_smooth45 pressed do
    	(
    		spn_angle.value = 45
    		doSmooth()
    	)
    	
    	on btn_autosmooth pressed do
    	(
    		doSmooth()
    	)
    	
    	on btn_clear pressed do
    	(
    		doSmooth clear:true
    	)

  • Steven_Oconnell
    Options
    Offline / Send Message
    Steven_Oconnell polycounter lvl 7

    Holly crap, shorter is an understatement.

    I wish I would have known about that when I first started this.

    Thanks a bunch.




  • Steven_Oconnell
    Options
    Offline / Send Message
    Steven_Oconnell polycounter lvl 7

    So I have another, quick question.

    I’ve been trying to get a simple attach script to work.

    As far as I know this is the correct way to do it:

    &nbsp;&nbsp;&nbsp;&nbsp; -- This will attach all selected objects, and merge individual materials into multi/sub-object material. (whon't bring up the "Attach Options" dialogue)<br>&nbsp;&nbsp; &nbsp;function attachobj =<br>&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for o in (selection as array) do<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;converttopoly o<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;polyop.attach o o<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;)<br>&nbsp;&nbsp; &nbsp;)

    However whenever I execute it nothing happens. (the conversion to an editable poly works, but nothing gets attached)





  • Swordslayer
    Options
    Offline / Send Message
    Swordslayer interpolator
    You are trying to attach each object to itself. Keep the first one and iterate the rest attaching them to the first object. For more performant version, look up cluster attach on cgtalk.
  • Steven_Oconnell
    Options
    Offline / Send Message
    Steven_Oconnell polycounter lvl 7

    My goal is to basically replicate the default functionality of Max's attach feature found in the modify panel.

    When the objects with different materials get attached I would like the materials in question to be put into a Multi/Sub Object material. (The first option in the “Attach Options” dialogue that appears when you try to attach objects with different material assignments)

    (Hopefully I explained that decently enough  XD)

     

    I have seen this thread here:

    http://forums.cgsociety.org/archive/index.php?t-922140.html

    Which I’m assuming is the one you’re referring to, however I can’t for the life of me get those functions to work. (Lack of knowledge on my end is pretty apparent so it’s no surprise)




  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    swordslayer is correct  your problem is logic.  

    The one linked off CG society looks like it probably comes into it's own when you're dealing with hundreds of objects

    I decided I'd probably find this handy so I wrote it up for myself : the multi-sub material is automatically created by default - simply use the eyedropper to pick the material off the combined object.  I'd advise against doing any scripting of the material editor if you can avoid it  - it's a horrible place to visit. 

    	function attachobj =
        (
    		-- copy selection into a proper array
    		objs = #()
    		for o in selection do
    		(
    			append objs o
    		)
    
    		--grab first object from array and store
    		fobj = objs[1]
    		-- pop  first object out of array
    		deleteitem objs 1
    		converttopoly fobj
    
    		--attach to fobj
    		for o in objs do
            (
    			polyop.attach fobj o
            )
    
        )
    	
    	
    	attachobj()
    	
    	

  • Steven_Oconnell
    Options
    Offline / Send Message
    Steven_Oconnell polycounter lvl 7
    poopipe said:
    I'd advise against doing any scripting of the material editor if you can avoid it  - it's a horrible place to visit.

    I will most definitely heed your warning, the only reason I brought it up was because I’ve seen a few scripts that do not use the default material merging method when attaching objects so I thought I’d be as clear as possible. XD

     

    I really appreciate the help. I learn best by going through other peoples code, however it seems that most scripts available online are generally quite a bit more complex than what I’m trying to achieve and the documentation doesn’t provide particle examples for everything so that can be hit and miss at times as well.

    I’m really thankful that people are willing to show me the basic methods of doing simple tasks, it gives me a good starting point.

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter
    I'm a big fan of noodly little scripts like this - they save me clicks and they're great practice for when you want to make bigger tools. 

    the polyop stuff is unusually consistent and well organised for maxscript so you'll probably find you can build yourself a bunch of useful mesh manipulating buttons quite quickly

  • monster
    Options
    Offline / Send Message
    monster polycounter
    My object combining script is similar to poopipe's. There is a command for converting a selection into an array.

    --//Replace this...
    
            objs = #()
            for o in selection do
            (
                append objs o
            )
    
    --//With this...
    
            objs = getCurrentSelection()

Sign In or Register to comment.