home *** CD-ROM | disk | FTP | other *** search
/ Maximum 3D 3 / m3d-p3.iso / 3DS_MAX / 3DSMAX.2_0 / SCRIPTS / SUPRSCTR.MS < prev    next >
Text File  |  1997-10-19  |  16KB  |  429 lines

  1. -- ********************************************************************************************
  2. -- *                            "Super Scatter"
  3. -- *                                  v1.0
  4. -- *                  a freeware MAXScript scatter utility
  5. -- *                             by Kyle McKisic
  6. -- *                         75542.363@compuserve.com
  7. -- *
  8. -- *  
  9. -- *     You may distribute this script through any means you see fit,
  10. -- *  as long as you do not remove the credits in the 'About' box.
  11. -- * 
  12. -- *  Please send any bugs or comments to me at the above e-mail
  13. -- *  address or fix them yourself if you want... I don't really care :)
  14. -- * 
  15. -- *  Best viewed when EditorTabWidth = 2 and EditorFont = "Courier"
  16. -- * 
  17. -- *  Known Problems/Bugs:
  18. -- * 
  19. -- *     1. When objects are scattered based on their object centers, rather
  20. -- *        than their pivot points, and their orientations are changed, it's 
  21. -- *     being done based on the object's pivot point, rather than it's 
  22. -- *     geometrical center.
  23. -- * 
  24. -- *  2. When you close the Super Scatter rollout floater window, you have
  25. -- *     to close and re-open the utility to get the window back.  It should
  26. -- *     work a little better than that.
  27. -- *  
  28. -- *     
  29. -- *  Other features I'm planning on implementing:
  30. -- * 
  31. -- *  - Edge Center placement method.
  32. -- *  - Ability to scatter n copies randomly over the distribution object.
  33. -- *  - Scatter over selected verts, selected faces, or selected edges.
  34. -- *  - Scatter based on a loaded bitmap, interpreted through the distribution
  35. -- *    objects UV's.
  36. -- *  - Key random scale (uniform and non-uniform), density, and random rotation
  37. -- *    from bitmaps.
  38. -- *  - Add the ability to have one, single object at the end of scattering.  Note
  39. -- *    that you can do this manually by collapsing all the scatter objects into one
  40. -- *    object through the Collapse Utility.
  41. -- *     - Scatter onto multiple objects at one time.
  42. -- *  - add support for groups, and other wacky MAX objects - some of these may already
  43. -- *    work, I just haven't tested all of them yet.
  44. -- * 
  45. -- ********************************************************************************************
  46. Utility ScatterUtil "Super Scatter v1.0"
  47. (
  48.  
  49. local     DistObj, ScatterObj, ScatterRollout, Nth, CDir, DistObjCenter, InitDir, SourceDistObject,
  50.                 DistObjFaces = #(),
  51.                 DistObjVerts = #(),
  52.                 ScatteredObjects = #(),
  53.                 FaceNormalArray = #(),
  54.                 VertexNormalArray = #(),
  55.                 ScatterNormalArray = #()
  56.  
  57. label title1 "Super Scatter"
  58. label title2 "v1.0"
  59. label title3 "by Kyle McKisic"
  60. label title4 "75542.363@compuserve.com"
  61.  
  62. on ScatterUtil open do
  63.     (
  64.         rof = (NewRolloutFloater "Super Scatter v1.0" 320 470)
  65.         addrollout ScatterRollout rof
  66.     )
  67.  
  68. rollout ScatterRollout "Super Scatter"
  69. (
  70.     button aboutScatter "About" width:35 height:20
  71.     group "Scatter Options"
  72.     (
  73.         label DistLabel "Distribution Object:" align:#left offset:[-5,0]
  74.         pickbutton GetDistObj width:170 align:#right offset:[0,-21]
  75.         
  76.         label scatterLabel "Scatter Object:" align:#left offset:[-5,0]
  77.         pickbutton GetScatterObj width:170 align:#right offset:[0,-21]
  78.     
  79.         radiobuttons placementMethod "Placement method:" labels:#("Object Pivot","Object Center") align:#left columns:1
  80.         spinner PlaceOnEvery range:[1,99999,1] type:#integer fieldwidth:45 offset:[0,-50]
  81.         radiobuttons Placement "Place on every Nth:" labels:#("Vertex","Face center") columns:1 align:#right offset:[-74,-21] fieldwidth:35
  82.         radiobuttons copytype "Clone method:" labels:#("Copy", "Instance","Reference") align:#left columns:1
  83.         button ScatterBtn "Scatter" width:80 height:40 offset:[0,-50]
  84.         button ReInitialize "Reinitialize" offset:[95,-45] width:80 height:40
  85.         label blank0
  86.     )
  87.     
  88.     group "Orientation Options"
  89.         (
  90.             radiobuttons OrientationType labels:#("Initial orientation","Explicit direction","Cylindrical projection","Spherical projection","Normal to surface") align:#left columns:1
  91.             Spinner Xdir "X:" range:[-1,1,0] type:#float fieldwidth:45 offset:[-70,-85] enabled:false
  92.             Spinner YDir "Y:" range:[-1,1,0] type:#float fieldwidth:45 offset:[-70,0] enabled:false
  93.             Spinner ZDir "Z:" range:[-1,1,1] type:#float fieldwidth:45 offset:[-70,0] enabled:false
  94.             pickbutton PickDir "Pick dir" offset:[35,0] enabled:false
  95.             label Presetslabel "Presets:" offset:[110,-93] enabled:false
  96.             button TopPreset "T" offset:[97,-3] width:25 enabled:false
  97.             button BottomPreset "B" offset:[124,-26] width:25 enabled:false
  98.             button LeftPreset "L" offset:[97,-3] width:25 enabled:false
  99.             button RightPreset "R" offset:[124,-26] width:25 enabled:false
  100.             button FrontPreset "F" offset:[97,-3] width:25 enabled:false
  101.             button BackPreset "K" offset:[124,-26] width:25 enabled:false
  102.             label blank2
  103.             checkbox InteractiveUpdate "Interactive Update" checked:true
  104.             button UpdateDir "Manual Update" offset:[35,-23] enabled:false height:32
  105.             label blank3
  106.         )
  107.     
  108.     
  109.     -- about box
  110.     on aboutScatter pressed do
  111.         messagebox "Super Scatter\nv1.0\nby Kyle McKisic\n75542.363@compuserve.com" title:"About Super Scatter..."
  112.     
  113.     on GetDistObj picked obj do
  114.         (
  115.             SourceDistObject = obj
  116.             DistObj = (copy obj)
  117.             convertToMesh DistObj
  118.             DistObj.wireColor = obj.wireColor
  119.             -- get the face and vertex data from the distribution object so we don't have keep
  120.             -- getting it from the mesh anytime we want to do something
  121.             DistObjFaces = for i = 1 to DistObj.numFaces collect (getFace DistObj i)
  122.             DistObjVerts = for i = 1 to DistObj.numVerts collect (getVert DistObj i)
  123.             DistObjCenter = DistObj.center
  124.             FaceNormalArray = for i = 1 to DistObj.numfaces collect (getFaceNormal DistObj i)
  125.             VertexNormalArray = for i = 1 to DistObj.numverts collect (getNormal DistObj i)
  126.             GetDistObj.text = DistObj.name
  127.             -- we've got the data, so get rid of it...
  128.             delete DistObj
  129.         )
  130.     
  131.     on GetScatterObj picked obj do
  132.         (
  133.             ScatterObj = obj
  134.             GetScatterObj.text = ScatterObj.name
  135.         )
  136.     
  137.     on ScatterBtn pressed do
  138.         (
  139.             if ScatterObj != undefined then
  140.                 (
  141.                     undo on
  142.                         (
  143.                             -- here, we collect do a quick compare to make sure
  144.                             -- the user didn't go and modify the mesh after picking it
  145.                             DistObj = copy SourceDistObject
  146.                             convertToMesh DistObj
  147.                             nv = DistObj.numVerts
  148.                             nf = DistObj.numFaces
  149.                             delete DistObj
  150.                             if (nv == DistObjVerts.count) and (nf == DistObjFaces.count) then
  151.                                 (
  152.                                     -- reset these arrays
  153.                                     ScatteredObjects = #()
  154.                                     ScatterNormalArray = #()
  155.                                     -- grab the Initial directional vector from the scatter object
  156.                                     InitDir = ScatterObj.dir
  157.                                     nv = DistObjVerts.count
  158.                                     nf = DistObjFaces.count
  159.                                     Nth = PlaceOnEvery.value
  160.                                     ProgressStart "Generating scattered result...."
  161.                                     if Placement.state == 1 then
  162.                                         (
  163.                                             for i = 1 to nv do
  164.                                                 (
  165.                                                     if (mod i Nth) == 0 do
  166.                                                         (
  167.                                                             CVertPos = DistObjVerts[i]
  168.                                                             if copytype.state == 1 do
  169.                                                                 CScatterTempObj = copy ScatterObj
  170.                                                             if copytype.state == 2 do
  171.                                                                 CScatterTempObj = instance ScatterObj
  172.                                                             if copytype.state == 3 do
  173.                                                                 CScatterTempObj = reference ScatterObj
  174.                                                             append ScatteredObjects CScatterTempObj
  175.                                                             append ScatterNormalArray VertexNormalArray[i]
  176.  
  177.                                                             if PlacementMethod.state == 1 then
  178.                                                                 CScatterTempObj.pos = CVertPos
  179.                                                             else
  180.                                                                 CScatterTempObj.pos = (CVertPos + (ScatterObj.pivot - ScatterObj.center))
  181.                                                             -- update the progress bar
  182.                                                             ProgressUpdate ((i / nv as float) * 100)
  183.                                                         )
  184.                                             )
  185.                                     ) else (
  186.                                         for i = 1 to nf do
  187.                                             (
  188.                                                 if (mod i Nth) == 0 do
  189.                                                     (
  190.                                                         CFace = DistObjFaces[i]
  191.                                                         Vert1 = DistObjVerts[CFace.x]
  192.                                                         Vert2 = DistObjVerts[CFace.y]
  193.                                                         Vert3 = DistObjVerts[CFace.z]
  194.                                                         CPos = ((Vert1 + Vert2 + Vert3) / 3)
  195.  
  196.                                                         if copytype.state == 1 do
  197.                                                             CScatterTempObj = copy ScatterObj
  198.                                                         if copytype.state == 2 do
  199.                                                             CScatterTempObj = instance ScatterObj
  200.                                                         if copytype.state == 3 do
  201.                                                             CScatterTempObj = reference ScatterObj
  202.  
  203.                                                         append ScatteredObjects CScatterTempObj
  204.                                                         append ScatterNormalArray FaceNormalArray[i]
  205.  
  206.                                                         if PlacementMethod.state == 1 then
  207.                                                             (
  208.                                                                 CScatterTempObj.pos = CPos
  209.                                                             ) else (
  210.                                                                 CScatterTempObj.pos = (CPos + (ScatterObj.pivot - ScatterObj.center))
  211.                                                             )
  212.                                                         ProgressUpdate ((i / nf as float) * 100)
  213.                                                     )
  214.                                             )
  215.                                     )
  216.                                 ProgressEnd()
  217.                             ) else (
  218.                                 MessageBox "Distribution object topology has changed.\nPlease re-pick your distribution object."
  219.                             )
  220.                     )
  221.                 ) else (
  222.                     MessageBox "Necessary Scatter objects are not defined yet!"
  223.                 )
  224.         )
  225.  
  226.         -- cleaning the dialog
  227.         on ReInitialize pressed do
  228.             (
  229.                 -- remove the rollout
  230.                 removeRollout ScatterRollout rof
  231.                 -- clean out the variables
  232.                 ScatterObj =                         undefined
  233.                 CDir =                                     undefined
  234.                 DistObjCenter =                 undefined
  235.                 InitDir =                             undefined
  236.                 DistObjFaces =                     #()
  237.                 DistObjVerts =                     #()
  238.                 ScatteredObjects =             #()
  239.                 FaceNormalArray =             #()
  240.                 VertexNormalArray =         #()
  241.                 ScatterNormalArray =         #()
  242.                 -- and add the rollout back again
  243.                 addRollout ScatterRollout rof
  244.             )
  245.         
  246.         on InteractiveUpdate changed state do
  247.             if state == on then 
  248.                 UpdateDir.enabled = false
  249.             else
  250.                 UpdateDir.enabled = true
  251.  
  252.     on UpdateDir pressed do
  253.         (
  254.             if OrientationType.state == 1 do
  255.                 for i = 1 to ScatteredObjects.count do
  256.                     ScatteredObjects[i].dir = InitDir
  257.     
  258.             if OrientationType.state == 2 do
  259.                 (
  260.                     CDir = [Xdir.value, YDir.value, ZDir.value]
  261.                     for i = 1 to ScatteredObjects.count do
  262.                             ScatteredObjects[i].dir = CDir
  263.                 )
  264.     
  265.             if OrientationType.state == 3 do
  266.                 for i = 1 to ScatteredObjects.count do
  267.                     ScatteredObjects[i].dir = normalize (ScatteredObjects[i].pos - [DistObjCenter.x, DistObjCenter.y, ScatteredObjects[i].pos.z])
  268.     
  269.             if OrientationType.state == 4 do
  270.                 for i = 1 to ScatteredObjects.count do
  271.                     ScatteredObjects[i].dir = normalize (ScatteredObjects[i].pos - DistObjCenter)
  272.     
  273.             if OrientationType.state == 5 do
  274.                     for i = 1 to ScatteredObjects.count do
  275.                         ScatteredObjects[i].dir = ScatterNormalArray[i]
  276.         )
  277.  
  278.     on OrientationType changed state do
  279.         (
  280.             if state == 1 do
  281.                 (
  282.                     PickDir.enabled = Xdir.enabled = YDir.enabled = ZDir.enabled = Presetslabel.enabled = TopPreset.enabled = BottomPreset.enabled = LeftPreset.enabled = RightPreset.enabled = FrontPreset.enabled = BackPreset.enabled = false
  283.                     if InteractiveUpdate.checked do
  284.                         for i = 1 to ScatteredObjects.count do
  285.                                 ScatteredObjects[i].dir = InitDir
  286.                 )
  287.     
  288.             if state == 2 do
  289.                 (
  290.                     PickDir.enabled = Xdir.enabled = YDir.enabled = ZDir.enabled = Presetslabel.enabled = TopPreset.enabled = BottomPreset.enabled = LeftPreset.enabled = RightPreset.enabled = FrontPreset.enabled = BackPreset.enabled = true
  291.                     if InteractiveUpdate.checked do
  292.                         (
  293.                             CDir = [Xdir.value, YDir.value, ZDir.value]
  294.                             for i = 1 to ScatteredObjects.count do
  295.                                     ScatteredObjects[i].dir = CDir
  296.                         )
  297.                 )
  298.     
  299.             if state == 3 do
  300.                 (
  301.                     PickDir.enabled = Xdir.enabled = YDir.enabled = ZDir.enabled = Presetslabel.enabled = TopPreset.enabled = BottomPreset.enabled = LeftPreset.enabled = RightPreset.enabled = FrontPreset.enabled = BackPreset.enabled = false
  302.                     if InteractiveUpdate.checked do
  303.                         for i = 1 to ScatteredObjects.count do
  304.                             ScatteredObjects[i].dir = normalize (ScatteredObjects[i].pos - [DistObjCenter.x, DistObjCenter.y, ScatteredObjects[i].pos.z])
  305.                 )
  306.     
  307.             if state == 4 do
  308.                 (
  309.                     PickDir.enabled = Xdir.enabled = YDir.enabled = ZDir.enabled = Presetslabel.enabled = TopPreset.enabled = BottomPreset.enabled = LeftPreset.enabled = RightPreset.enabled = FrontPreset.enabled = BackPreset.enabled = false
  310.                     if InteractiveUpdate.checked do
  311.                         for i = 1 to ScatteredObjects.count do
  312.                                 ScatteredObjects[i].dir = normalize (ScatteredObjects[i].pos - DistObjCenter)
  313.                 )
  314.     
  315.             if state == 5 do
  316.                 (
  317.                     PickDir.enabled = Xdir.enabled = YDir.enabled = ZDir.enabled = Presetslabel.enabled = TopPreset.enabled = BottomPreset.enabled = LeftPreset.enabled = RightPreset.enabled = FrontPreset.enabled = BackPreset.enabled = false
  318.                     if InteractiveUpdate.checked do
  319.                         for i = 1 to ScatteredObjects.count do
  320.                             ScatteredObjects[i].dir = ScatterNormalArray[i]
  321.                 )
  322.         )
  323.     
  324.         on XDir changed state do
  325.             (
  326.                 CDir = [XDir.value, YDir.value, ZDir.value]
  327.                 CDir = normalize CDir
  328.                 YDir.value = CDir.y
  329.                 ZDir.value = CDir.z
  330.                 if InteractiveUpdate.checked do
  331.                     for i = 1 to ScatteredObjects.count do
  332.                         ScatteredObjects[i].dir = CDir
  333.             )
  334.     
  335.         on YDir changed state do
  336.             (
  337.                 CDir = [XDir.value, YDir.value, ZDir.value]
  338.                 CDir = normalize CDir
  339.                 XDir.value = CDir.x
  340.                 ZDir.value = CDir.z
  341.                 if InteractiveUpdate.checked do
  342.                     for i = 1 to ScatteredObjects.count do
  343.                         ScatteredObjects[i].dir = CDir
  344.             )
  345.     
  346.         on ZDir changed state do
  347.             (
  348.                 CDir = [XDir.value, YDir.value, ZDir.value]
  349.                 CDir = normalize CDir
  350.                 YDir.value = CDir.y
  351.                 XDir.value = CDir.x
  352.                 if InteractiveUpdate.checked do
  353.                     for i = 1 to ScatteredObjects.count do
  354.                         ScatteredObjects[i].dir = CDir
  355.             )
  356.  
  357.         on TopPreset pressed do
  358.             (
  359.                 XDir.value = 0
  360.                 YDir.value = 0
  361.                 ZDir.value = 1
  362.                 CDir = [0,0,1]
  363.                 if InteractiveUpdate.checked do
  364.                     for i = 1 to ScatteredObjects.count do
  365.                         ScatteredObjects[i].dir = CDir
  366.             )
  367.         on BottomPreset pressed do
  368.             (
  369.                 XDir.value = 0
  370.                 YDir.value = 0
  371.                 ZDir.value = -1
  372.                 CDir = [0,0,-1]
  373.                 if InteractiveUpdate.checked do
  374.                     for i = 1 to ScatteredObjects.count do
  375.                         ScatteredObjects[i].dir = CDir
  376.             )
  377.         on LeftPreset pressed do
  378.             (
  379.                 XDir.value = -1
  380.                 YDir.value = 0
  381.                 ZDir.value = 0
  382.                 CDir = [-1,0,0]
  383.                 if InteractiveUpdate.checked do
  384.                     for i = 1 to ScatteredObjects.count do
  385.                         ScatteredObjects[i].dir = CDir
  386.             )
  387.         on RightPreset pressed do
  388.             (
  389.                 XDir.value = 1
  390.                 YDir.value = 0
  391.                 ZDir.value = 0
  392.                 CDir = [1,0,0]
  393.                 if InteractiveUpdate.checked do
  394.                     for i = 1 to ScatteredObjects.count do
  395.                         ScatteredObjects[i].dir = CDir
  396.             )
  397.         on FrontPreset pressed do
  398.             (
  399.                 XDir.value = 0
  400.                 YDir.value = -1
  401.                 ZDir.value = 0
  402.                 CDir = [0,-1,0]
  403.                 if InteractiveUpdate.checked do
  404.                     for i = 1 to ScatteredObjects.count do
  405.                         ScatteredObjects[i].dir = CDir
  406.             )
  407.         on BackPreset pressed do
  408.             (
  409.                 XDir.value = 0
  410.                 YDir.value = 1
  411.                 ZDir.value = 0
  412.                 CDir = [0,1,0]
  413.                 if InteractiveUpdate.checked do
  414.                     for i = 1 to ScatteredObjects.count do
  415.                         ScatteredObjects[i].dir = CDir
  416.             )
  417.  
  418.         on PickDir picked obj do
  419.             (
  420.                 CDir = obj.dir
  421.                 XDir.value = CDir.x
  422.                 YDir.value = CDir.y
  423.                 ZDir.value = CDir.z
  424.                 if InteractiveUpdate.checked do
  425.                     for i = 1 to ScatteredObjects.count do
  426.                         ScatteredObjects[i].dir = CDir
  427.             )
  428.     ) -- end rollout
  429. ) -- Utility end.....