[Closed] scripted plugin – possible?
I noticed a couple of scripted plugin posts in here and it reminded me of an attempt I made a few years back. I wrote a script that makes a soccer ball. It starts with a hedra, converts it to to editable poly, does some poly editing and then it adds some modifiers with specific settings and then collapses the whole thing.
I remember back then, trying to turn it into a scripted plugin to have a soccerball primitive with some spinners for adjusting various settings like initial radius of the ball among other things. But I hit a wall (can’t remember what the problem was) and never finished it.
What I would like to ask, is this possible? I know where to look in the help to learn, but if this isn’t possible to do with this object, I might leave this to learn for another time. But if it is possible, then I’m going to jump right in and do it this time.
Here’s the standalone code (I’ve taken out the collapse at the end so the stack is still intact for inspection):
(
select(hed = hedra radius:10 family:2 scalep:100 scaleq:100 scaler:100 p:0.37 name:"Soccerball")
SetCommandPanelTaskMode #modify
convertTo hed polyMeshObject
hed.faces[#1] = #{1..(polyop.getNumFaces hed)}
hed.edges[#1] = #{1..(polyop.getNumEdges hed)}
hed.verts[#1] = #{1..(polyop.getNumVerts hed)}
subobjectLevel = 1
select hed.verts["1"]
hed.editablePoly.chamferVertices 0.005
subobjectLevel = 2
select hed.edges["1"]
hed.editablePoly.chamferEdges 0.0015
subobjectLevel = 4
for i = 1 to polyop.getNumFaces hed do polyop.setFaceMatID hed i 3
for i = 1 to (hed.faces["1"]).count do polyop.setFaceMatID hed i 1
for i = 1 to (polyop.getNumFaces hed) do
(
if polyop.getFaceMatID hed i == 1 do
(
if (polyop.getfaceVerts hed i).count == 10 do
(
polyop.setFaceMatID hed i 2
)
)
)
faceSel = #()
for i = 1 to (polyop.getNumFaces hed) do
(
if polyop.getFaceMatID hed i == 1 or polyop.getFaceMatID hed i == 2 then append faceSel i
)
hed.selectedFaces = faceSel
hed.extrudeFaces 0.5
hed.EditablePoly.ConvertSelection #Face #Vertex
subobjectLevel = 1
closestVerts = (distance (polyop.getvert hed (hed.selectedVerts[1].index)) (polyop.getVert hed (hed.selectedVerts[2].index)))
vert1 = 1
vert2 = 2
for i = 1 to 6 do
(
for j = i to 6 do
(
if j != i do
(
testDist = (distance (polyop.getvert hed (hed.selectedVerts[i].index)) (polyop.getVert hed (hed.selectedVerts[j].index)))
if testDist < closestVerts do
(
closestVerts = testDist
vert1 = (hed.selectedVerts[i].index)
vert2 = (hed.selectedVerts[j].index)
)
)
)
)
hed.weldThreshold = closestVerts*2
polyop.weldVertsByThreshold hed hed.selectedVerts
ms = meshsmooth iterations:2 sepBySmGroups:off sepByMats:on
addmodifier hed ms
sp = spherify percent:100
addmodifier hed sp
vs = Vol__Select level:2 volume:5 matID:3
addmodifier hed vs
psh = push push_Value:-.125
addmodifier hed psh
ps = Poly_Select()
addmodifier hed ps
psh = push push_Value:0.05
addmodifier hed psh
rel = relax Relax_Value:.5 Keep_Boundary_Pts_Fixed:0 iterations:1
addmodifier hed rel
update hed
theMultiMat = multimaterial name:"SoccerBall" numsubs:3
theMultiMat[1] = standard diffuse:white
theMultiMat[2] = standard diffuse:black
theMultiMat[3] = standard diffuse:black
hed.material = theMultiMat
)
Yes it’s fully possible.
demands some work, but there is examples in the maxscript manual that should get you going.
“scripted geometry” in the help file.
there’s an example that creates geometry and has custom spinners for it’s parameter.
scripted plugin – possible?
We have to talk here about technical and practical possibility. Technically is possible for sure. If anyone (developers of meshsmooth, spherify, push, and relax modifier) could do it, why can you not?
The practical side of this problem is that you have to do all mesh operation on trimesh level. So only the meshop interface can help you.
If the push and relax algorithms are pretty simple, the meshsmooth and spherify are not trivial. The main problem for all these algorithms realization is we don’t really know vertex normals. So you have to calculate them yourself and keep tracking of all changes.
I would estimate the time of developing this plug-in in MXS by myself is about 3-4 day.
So I would stay with the modifier stack solution adding extra modifiers to convert the Hedra to Poly, apply face IDs, extrude faces and weld vertices.
Do I understand correctly Dennis that you’re saying that with a scripted plugin, you have to do everything with tri mesh operations and it would be a long process to replicate the functionality of the modifiers that I’m using so I should skip trying to do it as a custom primitive and just use my script with the modifiers as I already have it now?
I think that your Soccer Ball (how it’s made and looks) is too complicated primitive for your first plug-in. Try to simplify the model a bit. I suggest you this scenario:
#0: start scripted geometry plug-in
#1: use Hedra as base (mesh instance)
#2: tesselate faces
#3: spherify all verts (make all vert distances from the center equal to Radius)
#4: apply right material IDs
that will be a good start
after that we can do some more complicated things
Thanks for that MGernot. This project for me though, is more about the learning than the result. So using someone else’s script kind of defeats the purpose for me in this case. Looks like a cool script though. Pretty sure I’ll use it for other things.
Cheers,
Cg.
OK, I’ve got step 0 and 1. With a radius spinner. Tesselation, I have an idea for a sort of meshsmooth-type tesselation. Spherify I figure I should be able to do with the use of unit vector stuff. I’ll post back when/if I’ve made some progress.
Cheers Dennis.
OK, work’s been a bit busy so I’ve only just had a chance to have a go at a tessellation algorithm. This is my first try at edge to face-center tessellation. To start with, I thought I’d just look at how to tessellate polygons with polyop methods to keep it as simple as possible and then move up from there. I decided to keep the original vert ordering like meshsmooth does (but not turbosmooth)
Very open to comments/crits/discussion
(
obj = convertto (copy selection[1]) polyMeshObject
newObj = convertTo(editable_mesh name:"Tesselated") polyMeshObject
newObj.transform = obj.transform
baseVertCount = polyop.getnumverts obj
baseFaceCount = polyop.getNumFaces obj
baseEdgeCount = polyop.getNumEdges obj
newFaceVerts = #()
newEdgeVerts = #()
-- recreate existing verts on new object so the original verts are retained like meshsmooth, not like turbosmooth where they are reordered.
for i = 1 to baseVertCount do polyop.createVert newObj (polyop.getVert obj i)
-- create new verts on new object at center of all original faces
-- collect an array of new face verts indexed by face numbers
for i = 1 to baseFaceCount do
(
polyop.createVert newObj (polyop.getFaceCenter obj i)
append newFaceVerts (baseVertCount + i)
)
-- create new verts on new object at center of all original edges
-- collect an array of new edge verts indexed by edge numbers
for i = 1 to baseEdgeCount do
(
edgeVerts = polyop.getEdgeVerts obj i
polyop.createVert newObj (((polyop.getVert obj edgeVerts[1])+(polyop.getVert obj edgeVerts[2]))/2)
append newEdgeVerts (baseVertCount + baseFaceCount + i)
)
-- iterate thru all original faces
for i = 1 to baseFaceCount do
(
faceEdges = polyop.getFaceEdges obj i
-- iterate thru all original verts of face
faceVerts = polyop.getFaceVerts obj i
for j = 1 to (faceVerts.count) do
(
-- find the 2 edges that this vert and face share
vertEdges = (polyop.getEdgesUsingVert obj (faceVerts[j]))as array
for k = (vertEdges.count) to 1 by -1 do if findItem faceEdges (vertEdges[k]) == 0 do deleteItem vertEdges k
newPolyVerts = #((newFaceVerts[i]),newEdgeVerts[(vertEdges[2])],(faceVerts[j]),newEdgeVerts[(vertEdges[1])])
polyop.createPolygon newObj newPolyVerts
)
)
delete obj
update newObj
select newObj
)
And this is my first attempt at a meshop spherify algorithm. Was a lot easier than tessellate.
(
obj = convertToMesh (copy selection[1])
undo off
(
vertDistanceTotal = 0
vertCount = meshop.getNumVerts obj
objCenter = obj.center
for i = 1 to vertCount do vertDistanceTotal += (distance objCenter (meshop.getvert obj i))
vertDistAverage = vertDistanceTotal/vertCount
for i = 1 to vertCount do
(
vertVector = (meshop.getVert obj i) - objCenter
meshop.setVert obj i (((vertVector/(length vertVector)) * vertDistAverage) + objCenter)
)
)
selection[1].baseobject = copy obj.baseobject
delete obj
)