Notifications
Clear all
[Closed] a christmas script present
Dec 24, 2013 11:02 am
something for the holiday season someone might find useful
will generate a mesh along a spline, though you can use the built in mesh and reduce and scale that to produce the same result (which i have done) I’m not overly keen on the way max maintains the cross section. Anyway It’s mxs prototyping for a version of the max line object for generating tree model branches.
fn lerp a b s = (a as float + s * (b - a))
-- create transform from a spline knot, we use an arbitary up axis if pxaxis is unsupplied
fn GetKnotTM shpe splne knt pxaxis: =
(
p = getKnotPoint shpe splne knt;
zaxis = normalize ((p - getInVec shpe splne knt) + (getOutVec shpe splne knt - p));
if pxaxis == unsupplied then
(
xaxis = normalize (cross [0,0,1] zaxis);
yaxis = normalize (cross xaxis zaxis);
)
else
(
yaxis = normalize (cross pxaxis zaxis);
xaxis = normalize (cross zaxis yaxis);
)
matrix3 xaxis yaxis zaxis p;
)
fn CollectSplineTransforms shpe splne nknots =
(
tms = #()
tms.count = nknots;
-- initialize the list so we get a more uniform transform orientation
tms[1] = GetKnotTM shpe splne 1;
-- use the previous xaxis to align all the subsequent transforms
for i = 2 to numKnots shpe splne do tms[i] = GetKnotTM shpe splne i pxaxis:tms[i-1][1];
tms;
)
fn CollectVertCounts start_sides end_sides nknots &nverts &nfaces =
(
vc = #()
vc.count = nknots;
nverts = 0;
nfaces = 0;
for i = 1 to nknots do
(
vc[i] = (lerp start_sides end_sides ((i - 1) as float /(nknots - 1) as float)) as integer;
nverts += vc[i];
if i != 1 then nfaces += (vc[i] + vc[i-1]);
)
vc;
)
-- builds the mesh
fn BuildSplineMesh shpe splne start_radius end_radius start_sides end_sides =
(
if start_sides < end_sides then swap start_sides end_sides;
nknots = numKnots shpe splne;
nverts = 0;
nfaces = 0;
vcs = CollectVertCounts start_sides end_sides nknots &nverts &nfaces;
tms = CollectSplineTransforms shpe splne nknots;
vcoords = getSegLengths shpe splne cum:true byVertex:true;
-- create the base mesh
msh = mesh numverts:nverts numfaces:nfaces;
-- create the geo verts
vi = 1;
for k = 1 to nknots do
(
radius = lerp start_radius end_radius ((k - 1) as float/(nknots - 1) as float);
nsides = vcs[k];
for i = 1 to nsides do
(
u = 360 * (i - 1) as float/nsides as float;
cu = radius * cos u;
su = radius * sin u;
setvert msh vi ([cu, su, 0] * tms[k]);
vi += 1;
)
)
-- create the geo faces
fi = 1;
max_offset = 0
min_offset = vcs[1];
for k = 1 to nknots - 1 do
(
lastj = 0;
max_sides = vcs[k];
min_sides = vcs[k + 1];
mm_ratio = min_sides as float/max_sides as float;
jwrap = (max_offset + max_sides + min_sides);
for i = 1 to max_sides do
(
-- handle the larger vert ring increment
i1 = i + max_offset;
i2 = i1 + 1;
if mod i max_sides == 0 then i2 -= max_sides;
-- handle the smaller vert ring increment
j1 = min_offset + (ceil (i * mm_ratio) as integer);
j2 = j1 + 1;
if mod j1 jwrap == 0 then j2 -= min_sides;
-- create the faces
setEdgeVis msh fi 1 true;
if j1 != lastj and min_sides > 1 then -- do we need to create a quad
(
setEdgeVis msh fi 2 true;
setface msh fi [i2,i1,j1]
fi += 1;
setface msh fi [i2,j1,j2]
setEdgeVis msh fi 2 true;
lastj = j1;
)
else
(
setEdgeVis msh fi 2 true;
setface msh fi [i2,i1,j2];
)
fi += 1;
)
max_offset += max_sides;
min_offset += min_sides;
)
-- allocate mapping
ntverts = nverts + nknots;
meshop.setMapSupport msh 1 true;
meshop.setNumMapVerts msh 1 ntverts;
meshop.setNumMapFaces msh 1 nfaces;
-- mapping verts
vi = 1;
for k = 1 to nknots do
(
nsides = vcs[k];
vc = vcoords[k];
for i = 1 to nsides + 1 do
(
meshop.setmapvert msh 1 vi [(i - 1) as float/nsides as float, vc, 0];
vi += 1;
)
)
-- create the mapping faces
fi = 1;
max_offset = 0
min_offset = vcs[1] + 1;
for k = 1 to nknots - 1 do
(
lastj = 0;
max_sides = vcs[k];
min_sides = vcs[k + 1];
mm_ratio = min_sides as float/max_sides as float;
for i = 1 to max_sides do
(
-- handle the larger vert ring increment, we don't have to worry about wrap around here :)
i1 = i + max_offset;
i2 = i1 + 1;
-- handle the smaller vert ring increment again no wrap around
j1 = min_offset + (ceil (i * mm_ratio) as integer);
j2 = j1 + 1;
-- create the faces
if j1 != lastj and min_sides > 1 then -- do we need to create a quad
(
meshop.setMapFace msh 1 fi [i2,i1,j1]
fi += 1;
meshop.setMapFace msh 1 fi [i2,j1,j2]
lastj = j1;
)
else
meshop.setMapFace msh 1 fi [i2,i1,j2];
fi += 1;
)
max_offset += max_sides + 1;
min_offset += min_sides + 1;
)
update msh;
msh;
)
BuildSplineMesh $ 1 5.0 1.0 11 3
had to change the lerp function as it produced errors
also calculating the number of faces can be reduced to
nfaces = 2 * nverts - start_sides - end_sides;
the algorithm could also be used to create bridging faces between any unequal vert “sets”. You would just need to collect the vert indices in correct sequential order.