[Closed] plexus WIP
This is the start of a plexus maxscript. It’s a work in progress, rather rough draft right now. Check it out. Open to suggestions and feature requests.
clearlistener()
delete objects
numCtrls = 20
numBranches = 5
ctrls = for c = 1 to numCtrls collect (point cross:true box:false pos:[random -50 50, random -50 50, random 0 50] wirecolor:yellow size:5)
plexusData = #()
fn getRandomNode nodes:#() excluded:#() =
(
useableNodes = for node in nodes where (findItem excluded node) == 0 collect node
count = random 1 useableNodes.count
return useableNodes[count]
)
sp = splineshape pos:[0,0,0] wirecolor:blue name:(uniqueName "Plexus_")
for ctrl in ctrls do
(
for b = 1 to numBranches do
(
addNewSpline sp
spIndex = numSplines sp
addKnot sp spIndex #corner #line ctrl.pos
randomCtrl = getRandomNode nodes:ctrls excluded:#(ctrl)
addKnot sp spIndex #corner #line randomCtrl.pos
append plexusData #(ctrl,randomCtrl)
)
)
updateShape sp
fn wireKnotToCtrl knot: index: target: =
(
if knot != unsupplied do
(
scriptCtrl = point3_script ()
sp[4][8][knot].controller = scriptCtrl
scriptCtrl.addTarget "control" plexusData[index][target][3]
scriptCtrl.setExpression "control.pos"
scriptCtrl.getTarget "control" --Get the Target Track as SubAnim value
scriptCtrl.getTarget "control" asObject:true --Get as Object
)
)
/* Controlable Knots */
animateVertex sp #all
knotA = 2; knotB = 5
for k = 1 to plexusData.count do
(
/* Knot A */
wireKnotToCtrl knot:knotA index:k target:1
wireKnotToCtrl knot:knotB index:k target:2
/* Increment for each knot controller */
knotA += 6; knotB += 6
)
/* Animation Ctrls */
sp.showFrozenInGray = false
sp.isfrozen = true
animationRange = interval 0f 144f
for t = animationrange.start to animationrange.end by 12 do
(
with animate on at time t
(
for ctrl in ctrls do ctrl.pos = [random -50 50, random -50 50, random 0 50]
)
)
Nice,
you could make the movement more organic by adding a slight wobble to the keyframes
for t = animationrange.start to animationrange.end by 12 do
(
for ctrl in ctrls do
(
local theTime = random (t-6) (t+6)
with animate on at time theTime (ctrl.pos = [random -50 50, random -50 50, random 0 50])
)
)
Hey John,
Why don’t you use splineIKs instead?
Have you tested it with more control objects? i tried with 200 and the viewport performance drops dramatically.
Suggestions:
- Loading a point cloud to create the plexus object
- Selecting a geometry as point cloud with ability to skip nth Vertex
- setting number of knots per branch (currently it’s 2 – one at the start, one at the end)
- Adding Position Noise controllers on the control objects
- A master controller for the points to set the weight of the noise controller
- adding a flex modifier on the plexus object.
This solution will eat a lot of memory. Probably bast way for plexus-like behavior is usage of cebas TP. Also Flex modifier have huge problem when “start animaton range” have value below 0.
Yeah I had created one once already using the spline ik. It still had performance issues and I wanted to see how this method proved to work. Seemingly there is no real solid method out there, especially if there are a lot of objects.
Thanks dude, this is awesome! It definitely gets the idea machine working. I will try to post some follow up ideas.
Hi, very nice script! Like the others…
It would be cool if the position of the points could “loop” at the and of time.
Hope to see updates
You don’t need script controllers, you can just instance the position controllers of the nulls to the knots. As long as plexus is on world zero and nulls also have world as parent. I’ll bet performance will be better as well.
-Johan
I thought about giving thickness to those splines basing on distance between control points, but it needs each line to be separate shape. This is my approach, but it’s pretty slow unfortunately.
numK = 20
for i = 1 to numK do geosphere pos:[random -20.0 20.0, random -20.0 20.0, random -20.0 20.0] wirecolor:(Color (random 155 155) (random 0 55) (random 0 55)) segs:5 radius:(random 1.0 2.0) name:("ctrl"+i as string)
ctrls = for i = 1 to numK collect (getnodebyname ("ctrl"+i as string))
for t = animationrange.start+30 to animationrange.end+30 by 30 do
(
for ctrl in ctrls do
(
local theTime = random (t-10) (t+10)
with animate on at time theTime (ctrl.pos = [random -50 50, random -50 50, random 0 50])
)
)
distmax = 35.0
thickmax = 2.5
for i = 1 to ctrls.count do
(
for j = i+1 to ctrls.count do
(
sp = splineShape pos:[0,0,0] render_renderable:true render_displayRenderMesh:true wirecolor:(Color (random 150 255) (random 150 255) (random 150 255))
scr = float_script()
str = stringstream ""
format ("dist = distance $"+ctrls[i].name+".pos $"+ctrls[j].name+".pos") to:str
format ("
if dist>"+distmax as string+" then return 0.0 else return ((1.0-(dist/"+distmax as string+"))*"+thickmax as string+")") to:str
str = str as string
scr.setExpression str
sp.render_thickness.controller = scr
addNewSpline sp
addKnot sp 1 #corner #line ctrls[i].pos
addKnot sp 1 #corner #line ctrls[j].pos
updateShape sp
animateVertex sp #all
local lista = #()
append lista (ctrls[i])
append lista (ctrls[j])
spm = Spline_IK_Control linkTypes:2 helper_list:lista
addModifier sp spm
ep = Edit_Poly()
addModifier sp ep
)
)