[Closed] Sample Simple Object Plug-in
following this discussion http://forums.cgsociety.org/showthread.php?f=98&t=1030079 i’ve made the plugin that might be helpful as a sample:
/* denisT script collection (2012)*/
plugin simpleObject BrickChimney
name:"Chimney"
classID:#(0x10001967,0xA0000001)
category:"Scripted Primitives"
(
local attach = meshop.attach
parameters params rollout:params
(
height type:#worldunits default:5 ui:ui_height
radius type:#worldunits default:5 ui:ui_radius
shift type:#float default:0.5 ui:ui_shift
brickLength type:#worldunits default:2.5 ui:ui_brickLength
brickWidth type:#worldunits default:1.6 ui:ui_brickWidth
brickHeight type:#worldunits default:1 ui:ui_brickHeight
brickFillet type:#worldunits default:0.15 ui:ui_brickFillet
brickFilletSegs type:#integer default:2 ui:ui_brickFilletSegs
brickSmooth type:#integer default:1 ui:ui_brickSmooth
brickMapCoords type:#integer default:1 ui:ui_brickMapCoords
brickRealWorldMapSize type:#boolean default:off ui:ui_brickRealWorldMapSize
)
rollout params "Parameters"
(
group "Chimney:"
(
spinner ui_height "Height: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_radius "Radius: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_shift "Shift: " type:#float range:[0,1,0] fieldwidth:56
)
group "Brick:"
(
spinner ui_brickLength "Length: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickWidth "Width: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickHeight "Height: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickFillet "Fillet: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickFilletSegs "Fillet Segs: " type:#integer range:[0,5,0] fieldwidth:56
checkbox ui_brickSmooth "Smooth" offset:[0,4]
checkbox ui_brickMapCoords "Apply UV Mapping"
checkbox ui_brickRealWorldMapSize "Real-World Map Size"
)
)
fn numberRows =
(
(if (height*brickHeight) == 0 then 0 else (height/brickHeight) as integer) + 1
)
fn numberBricksInRow =
(
--brickLength = 2*radius*sin(pi/n)
if (radius*brickLength) == 0 then 0 else
(
n = 180./(asin(brickLength/(2*radius)))
if (bit.isNAN n) then 0 else (n as integer)
)
)
fn transformMesh mesh verts offset: angle: =
(
for v in verts do
(
tm = transmatrix ((getVert mesh v) + offset)
tm = rotateZ tm angle
setVert mesh v tm.pos
)
mesh
)
on buildMesh do
(
setMesh mesh numverts:0 numfaces:0
if (n = numberBricksInRow()) > 0 do
(
local b = if brickFilletSegs > 0 then
(
createinstance ChamferBox Length_Segments:1 Width_Segments:1 Height_Segments:1 Fillet_Segments:brickFilletSegs \
length:brickLength width:brickWidth height:brickHeight Fillet:brickFillet \
smooth:brickSmooth mapcoords:brickMapCoords realWorldMapSize:brickRealWorldMapSize
)
else
(
createinstance Box lengthsegs:1 widthsegs:1 heightsegs:1 \
length:brickLength width:brickWidth height:brickHeight \
mapcoords:(brickMapCoords > 0) realWorldMapSize:brickRealWorldMapSize
)
local verts = #{1..b.mesh.numverts}
local angle = 360.0/n
local offset = [radius-brickWidth/2,0,0]
for z=0 to numberRows()-1 do
(
offset.z = brickHeight*z
s = shift*angle*z
for k=0 to n-1 do
(
brick = copy b.mesh
transformMesh brick verts offset:offset angle:(k*angle + s)
attach mesh brick
)
)
free b
)
)
tool create
(
on mousePoint click do case click of
(
1:
(
nodeTM.translation = gridPoint
height = 0
radius = 0
)
3: #stop
)
on mouseMove click do case click of
(
2:
(
radius = sqrt (gridDist.x^2 + gridDist.y^2)
)
3: height = gridDist.z
)
)
)
as i have time i will add new features. any questions, suggestions are welcome.
that features could be added:
#1 Tape/Bend the bricks
#2 Random Size a little
#3 Random Material ID
#4 Support Square/Rectangular Chimney
#5 …
any enthusiast is free to extend the plug-in…
Cool! Although its extremely slow for me in Max 2010 64bit. Takes seconds to update anything/create it.
i know. i’m thinking about a way of optimization. vertex transformation kills the performance. maybe attaching too.
Maybe do a sort of Proxy while editing/creating that is lower poly, then on end, create the higher poly mesh?
I wasn’t either on my Edge Twist issue I had in my other thread, but i spent too many hours trying to get it to work, and now I just have to user do it, and then is all good. Having more control is always good too.
Maybe do it like this method I saw from soulburn,
local snapObjs = #()
for obj in selection where (superclassof obj == GeometryClass) do
(
append snapObjs (snapshot obj)
)
local count = 1
local currentIteration = 0
local numOfItems = snapObjs.count
select snapObjs
--Thank you to SoulBurn Scripts for this algorithm/method
if snapObjs.count > 1 do
(
while (selection.count > 1) do
(
for i = selection.count to 2 by -2 do
(
currentIteration += 1
m = ((currentIteration as float)/(numOfItems as float))*100
attachTo = snapObjs[i]
convertToPoly attachTo
attachTo.EditablePoly.attach snapObjs[i-1] attachTo
deleteItem snapObjs (i-1)
)
)
convertToMesh selection[1]
i updated the plug-in… now it’s ~10 times faster:
/* denisT script collection (2012)*/
plugin simpleObject BrickChimney
name:"Chimney"
classID:#(0x10001967,0xA0000001)
category:"Scripted Primitives"
(
local attach = meshop.attach
local numBricks = 0, numBrickVerts = 0, numBrickFaces = 0
parameters params rollout:params
(
--useClone type:#boolean default:on ui:ui_useClone
height type:#worldunits default:5 ui:ui_height
radius type:#worldunits default:5 ui:ui_radius
shift type:#float default:0.5 ui:ui_shift
brickLength type:#worldunits default:2.5 ui:ui_brickLength
brickWidth type:#worldunits default:1.6 ui:ui_brickWidth
brickHeight type:#worldunits default:1 ui:ui_brickHeight
brickFillet type:#worldunits default:0.15 ui:ui_brickFillet
brickFilletSegs type:#integer default:2 ui:ui_brickFilletSegs
brickSmooth type:#integer default:1 ui:ui_brickSmooth
brickMapCoords type:#integer default:1 ui:ui_brickMapCoords
brickRealWorldMapSize type:#boolean default:off ui:ui_brickRealWorldMapSize
)
rollout params "Parameters"
(
--checkbox ui_useClone "Use Cluster Method" offset:[0,0]
group "Chimney:"
(
spinner ui_height "Height: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_radius "Radius: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_shift "Shift: " type:#float range:[0,1,0] fieldwidth:56
)
group "Brick:"
(
spinner ui_brickLength "Length: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickWidth "Width: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickHeight "Height: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickFillet "Fillet: " type:#worldunits range:[0,1e9,0] fieldwidth:56
spinner ui_brickFilletSegs "Fillet Segs: " type:#integer range:[0,5,0] fieldwidth:56
checkbox ui_brickSmooth "Smooth" offset:[0,4]
checkbox ui_brickMapCoords "Apply UV Mapping"
checkbox ui_brickRealWorldMapSize "Real-World Map Size"
)
)
fn numberRows =
(
(if (height*brickHeight) == 0 then 0 else (height/brickHeight) as integer) + 1
)
fn numberBricksInRow =
(
--brickLength = 2*radius*sin(pi/n)
if (radius*brickLength) == 0 then 0 else
(
n = 180./(asin(brickLength/(2*radius)))
if (bit.isNAN n) then 0 else (n as integer)
)
)
fn transformMesh mesh verts offset: angle: =
(
for v=1 to verts.count do
(
tm = transmatrix (verts[v] + offset)
tm = rotateZ tm angle
setvert mesh v tm.pos
)
mesh
)
on buildMesh do
(
t1 = timestamp()
setMesh mesh numverts:0 numfaces:0
numBricks = 0
if (n = numberBricksInRow()) > 0 do
(
local b = if brickFilletSegs > 0 then
(
createinstance ChamferBox Length_Segments:1 Width_Segments:1 Height_Segments:1 Fillet_Segments:brickFilletSegs \
length:brickLength width:brickWidth height:brickHeight Fillet:brickFillet \
smooth:brickSmooth mapcoords:brickMapCoords realWorldMapSize:brickRealWorldMapSize
)
else
(
createinstance Box lengthsegs:1 widthsegs:1 heightsegs:1 \
length:brickLength width:brickWidth height:brickHeight \
mapcoords:(brickMapCoords > 0) realWorldMapSize:brickRealWorldMapSize
)
brick = b.mesh
numBrickVerts = brick.numverts
numBrickFaces = brick.numfaces
local verts = #{1..numBrickVerts}
local vert_array = for v in verts collect (getvert brick v)
local angle = 360.0/n
local offset = [radius-brickWidth/2,0,0]
local meshes = #()
for z=0 to numberRows()-1 do
(
offset.z = brickHeight*z
s = shift*angle*z
for k=0 to n-1 do
(
brick = transformMesh b.mesh vert_array offset:offset angle:(k*angle + s)
append meshes brick
)
)
n = numBricks = meshes.count
while (num = n/2) > 0 do for k=1 to num do
(
attach meshes[k] meshes[n]
n -= 1
)
setmesh mesh meshes[1]
free b
free meshes
--format "time:% bricks:%
" (timestamp()-t1) numBricks
)
)
tool create
(
on mousePoint click do case click of
(
1:
(
nodeTM.translation = gridPoint
height = 0
radius = 0
)
3: #stop
)
on mouseMove click do case click of
(
2:
(
radius = sqrt (gridDist.x^2 + gridDist.y^2)
)
3: height = gridDist.z
)
)
)