-- test plugin simpleObject vscylinder name:"vscyl" classID:#(0x1f226f41, 0x18e231e1) category:"Scripted" ( parameters main rollout:params ( height type:#WorldUnits default:25.0 ui:ui_height; start_radii type:#WorldUnits default:25.0 ui:ui_start_radii; end_radii type:#WorldUnits default:25.0 ui:ui_end_radii; start_sides type:#integer default:16 ui:ui_start_sides; end_sides type:#integer default:16 ui:ui_end_sides; segments type:#integer default:5 ui:ui_segments; on start_sides set val do ( if end_sides > val then end_sides = val; ) on end_sides set val do ( if val > start_sides then end_sides = start_sides; ) ) rollout params "Params" ( spinner ui_height "Height:" range:[0, 1e9, 0] fieldwidth:64 type:#WorldUnits align:#right; spinner ui_start_radii "Start Radius:" range:[0, 1e9, 0] fieldwidth:64 type:#WorldUnits align:#right; spinner ui_end_radii "End Radius:" range:[0, 1e9, 0] fieldwidth:64 type:#WorldUnits align:#right; spinner ui_start_sides "Start Sides:" range:[3, 128, 5] fieldwidth:64 type:#integer align:#right; spinner ui_end_sides "End Sides:" range:[3, 128, 5] fieldwidth:64 type:#integer align:#right; spinner ui_segments "Segments:" range:[1, 128, 5] fieldwidth:64 type:#integer align:#right; ) tool create ( on mousePoint click do case click of ( 1: ( nodeTM.translation = gridPoint; height = start_radii = end_radii = 0.0; ) 3: #stop ) on mouseMove click do case click of ( 2: start_radii = end_radii = amax (abs gridDist.y) (abs gridDist.x); 3: height = gridDist.z ) ) fn lerp a b s = (a + s * (b - a)) fn collect_side_counts start end segs &nv = ( sides = #() sides.count = segs + 1; nv = 0; denom = 1.0/segs; for i = 0 to segs do ( sides[i + 1] = ceil(lerp start end (i * denom)) as integer; nv += sides[i + 1]; ) sides; ) -- build a cylindrical mesh fn build_mesh = ( local nverts = 0; -- compute the number of sides verts and faces local sides = collect_side_counts start_sides end_sides segments &nverts; local nfaces = 2 * nverts - start_sides - end_sides; -- create the geometry mesh.NumVerts = nverts; mesh.NumFaces = nfaces; local vi = 1, fi = 1, side_seg_size = height/segments; -- generate the verts for seg = 0 to segments do ( nsides = sides[seg+1]; z = side_seg_size * seg; radius = lerp start_radii end_radii (seg as float/segments as float); for i = 1 to nsides do ( u = 360 * (i - 1) as float/nsides as float; setvert mesh vi [radius * cos u, radius * sin u, z]; vi += 1; ) ) -- create the faces local i_offset = 0; -- index offset to the first vert of the start vert ring local j_offset = sides[1]; -- index offset to the first vert of the end vert ring for seg = 1 to segments do ( local lastc = 0, i_sides = sides[seg], j_sides = sides[seg + 1]; local inc_ratio = j_sides as float/i_sides as float, jwrap = i_offset + i_sides + j_sides; for i = 1 to i_sides do ( j = ceil (i * inc_ratio) as integer; -- top row counter -- handle the larger vert ring increment local a = i + i_offset, b = a + 1; if i == i_sides then b = i_offset + 1; -- handle the smaller vert ring increment local c = j_offset + j, d = c + 1; if j == j_sides then d = j_offset + 1; if c == j_offset + j_sides + 1 then d = j_offset + 1; setEdgeVis mesh fi 1 true; if c != lastc and c != j_offset + j_sides + 1 and j_sides > 1 then -- do we need to create a quad ( setEdgeVis mesh fi 2 true; setface mesh fi [c,a,b]; fi += 1; setface mesh fi [d,c,b]; setEdgeVis mesh fi 3 true; setEdgeVis mesh fi 1 true; lastc = c; ) else ( setEdgeVis mesh fi 2 true; setEdgeVis mesh fi 3 true; setface mesh fi [d,a,b]; ) fi += 1; ) i_offset += i_sides; j_offset += j_sides; ) update mesh; ) on update do build_mesh(); on buildmesh do build_mesh(); )