Notifications
Clear all

[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	
 )
10 Replies

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.

Cheers for that, I have a mission ahead.

Cg.

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?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

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
 )