Still, using your code, maxscript wins hands down:
plugin simpleMeshMod MXSCloneModifier
name:"MXSCloneModifier"
classID:#(0xBAADC0DE, 0xBAADC0DE)
category:"MXS Help"
(
fn _attachMeshes meshes =
(
attach = meshop.attach
n = meshes.count
while (num = n/2) > 0 do for k=1 to num do attach meshes[k] meshes[(n -= 1) + 1]
meshes[1]
)
parameters main rollout:params
(
numClones ui:spnNumClones default:1 type:#integer animatable:true
XOffset ui:spnXOffset default:0 type:#worldUnits animatable:true
YOffset ui:spnYOffset default:0 type:#worldUnits animatable:true
ZOffset ui:spnZOffset default:0 type:#worldUnits animatable:true
)
rollout params "Parameters"
(
spinner spnNumClones "# Clones:" range:[1, 1e3, 1] type:#integer
spinner spnXOffset "X Offset:" range:[-1e3, 1e3, 0] type:#worldUnits
spinner spnYOffset "Y Offset:" range:[-1e3, 1e3, 0] type:#worldUnits
spinner spnZOffset "Z Offset:" range:[-1e3, 1e3, 0] type:#worldUnits
)
on modifyMesh do
(
local meshes = #(mesh)
for k = 1 to (numClones-1) do
(
_m = copy mesh
meshop.moveVert _m #all ([XOffset, YOffset, ZOffset] * k)
append meshes _m
)
_attachMeshes meshes
)
)
Teapot segs:8 numClones:64
MCG time: 803 ms
MAXScript time: 114 ms
Teapot segs:8 numClones:256
MCG time: 3408 ms
MAXScript time: 505 ms
Teapot segs:8 numClones:1000
MCG time: 14385 ms
MAXScript time: 2443 ms
Teapot segs:10 numClones:907
MCG time: 21154 ms
MAXScript time: 3501 ms
change meshop.moveVert to
local moveVert = meshop.moveVert
for ... do (moveVert ...)
it saves some time too (and memory for sure)
unfortunately i expect the same lagging for many plugins produced by MCG. the code is fast because it’s compiled, but it’s not optimized well and made without really best knowledge how max sdk works.
make a compiler for mxs… and we will get much faster functions and tools written on pure mxs. no doubts.
I guess you don’t need to wait since you can do with c++ whatever you want.
But, I can wait a little.
Not a noticeable difference in time, unless the count is really high. With 10000 clones it saves less than 100 ms (with less than 1000 nodes it’s not a bigger difference than that of successive runs of the same code).
absolutely correct… but it might be a case where very small mesh cloned many times… for example: the grass (7 faces per blade and >300,000 blades)
MCG code probably will kill the max in this case
BTW, I’m still waiting for “CloneOnVerts” modifier maxscript version.
I also want to see proper benchmark between MCG and MXS,
I want to see performance on animated object, because that’s where performance matters more.
i don’t have simpleMeshMod available… it’s a feature of max 2016…
but i can try to write it blind and anyone who has it can correct me:
plugin simpleMeshMod TpMeshScatter
name:"TpMeshScatter"
classID:#(0x193aa23b, 0x193cc2db)
category:"How to with denisT"
(
fn _attachMeshes meshes =
(
attach = meshop.attach
n = meshes.count
while (num = n/2) > 0 do for k=1 to num do attach meshes[k] meshes[(n -= 1) + 1]
meshes[1]
)
fn _meshTransform mesh tm =
(
for v=1 to mesh.numverts do setvert mesh v ((getvert mesh v) * tm)
mesh
)
fn _getVertexTransform mesh v =
(
translate (arbaxis (getnormal mesh v)) (getvert mesh v)
)
on modifyMesh do
(
_m = copy mesh
local meshes = #(mesh)
local _t = (createinstance teapot).mesh
for v=1 to _m.numverts do append meshes \
(
_meshTransform (copy _t) (_getVertexTransform _m v)
)
_attachMeshes meshes
)
)
Well, denis posted a working sample, for your convenience here it is with a pickbutton added:
plugin simpleMeshMod TpMeshScatter
name:"TpMeshScatter"
classID:#(0x193aa23b, 0x193cc2db)
category:"How to with denisT"
(
fn _attachMeshes meshes =
(
attach = meshop.attach
n = meshes.count
while (num = n/2) > 0 do for k=1 to num do attach meshes[k] meshes[(n -= 1) + 1]
meshes[1]
)
fn _meshTransform mesh tm =
(
for v=1 to mesh.numverts do setvert mesh v ((getvert mesh v) * tm)
mesh
)
fn _getVertexTransform mesh v =
(
translate (arbaxis (getnormal mesh v)) (getvert mesh v)
)
parameters main rollout:params
(
source ui:pbSourceNode type:#node
)
rollout params "Parameters"
(
pickButton pbSourceNode "source" autoDisplay:true
)
on modifyMesh do if isValidNode source do
(
local meshes = #(mesh)
local _t = source.mesh
for v=1 to mesh.numverts do append meshes \
(
_meshTransform (copy _t) (_getVertexTransform mesh v)
)
_attachMeshes meshes
)
)
In the attachement I’ve included my take on the mcg version of the same (screenshot of the graph and the mcg package).
Feel free to test with whatever setup you consider appropriate. I didn’t really benchmark it thoroughly but in a few quick tests the unoptimized maxscript version was about 3-4 times faster. There might be a clever way to setup the graph in a different way, too.
OK… you guys win for now.
It seems you are already ready for MCG.
I’ll look forward some good graphs from you!
but the right way to make this plugin is to cache last mesh of cloned objects (teapots), hash target mesh (torus) topology(numverts), and geometry(vert positions and normals)…
if topology changed:
if greater than was -> attach new
if less than was -> delete
if only geometry changed:
transform previously cloned
Seeing all the skilled artists here… We once had this great sticky MaxScript challenge thread, which is basically dead for a few years now. What about a new incarnation of it, this time as a thread to post ideas/challenges done in MCG?
Or a section for MCG only? It’s been only a few days and there’s already some cool stuff floating around, it would really be great to have a dedicated section for all the upcoming ideas and questions.