A script that welds verts but keep groups...?


#1

Hi all.
Is there a script that will weld identical verts (or a threshold) but will keep the grouping intact? So the polys are still grouped seperately but the mesh is all welded.

Thanks!


#2

when you say ‘group’, do you mean the Elements? I.e. being able to select them separately by going into element sub-object mode?

If so - 'fraid not. Elements are determined by connectivity.

However, you should be able to store the original elements as named selection sets so that you can still select them separately once the vertices are welded.

Collect each unique element using <meshop|polyop>.getElementsUsingFace, assign each element to a named selection set using <object>.faces[“Name”] = <element face list>, then weld.


#3

ZeBoxx2,

That would work as the modeling would be completely done at that point, so it would be a welded single object but I could select the old poly elements…right?
How would these elements be selected then?

I wouldn’t impose on you to write a script just for me I was hoping that there might be something out there that would do this or that there would be a way inside of Max for this to be done???

I am complete idiot at scripting and can barely run a script! lol.


#4

You would select them from the Named Selection Set drop-down, which is typically in the top toolbar in 3ds Max (no idea where it’s at in 2010) and also accessible through Edit > Manage Selection Sets.

Not much code, really… the code to get the elements is the biggie… I’ll paste ofer_z’s here as mine’s all comment-less:
( source: http://forums.cgsociety.org/showpost.php?p=5260271&postcount=18 )


	fn getElements obj faces:#All =
	(
		-- Check the obj class
		local objClass = classOf obj
		-- Create a temp function (func) that given the object and a face ID returns
		-- the element face IDs.
		-- Depending on the class of obj, use the right method to get the element faces.
		local func
		case objClass of (
			Editable_Poly: fn func obj face = polyOp.getElementsUsingFace obj face
			PolyMeshObject: fn func obj face = polyOp.getElementsUsingFace obj face
			Editable_Mesh: fn func obj face = meshOp.getElementsUsingFace obj face
			Edit_Poly: fn func obj face = (local elem = #{}; obj.getElementsUsingFace elem #{face} #{}; elem)
			default: undefined
		)
		
		-- Initialize some variables
		local elements = #() 	-- The array of the elements
		local usedFaces = #{} 	-- A bitArray to hold all the face IDs that were either checked or were part of elements of other checked faces.
		
		-- Get the number of faces in obj (use the right method based on the class of obj).
		local numFaces = case objClass of (
			Editable_Poly: obj.numFaces
			Editable_Mesh: obj.numFaces
			PolyMeshObject: obj.numFaces 
			Edit_Poly: obj.getNumFaces()
			default: 0
		)
		-- If faces is not a bitArray, make it into a bitArray with all the faces in obj.
		if faces == #All then
			faces = #{1..numFaces}
		
		-- Loop through all the faces in the faces variable.
		-- If the current face ID is already in usedFaces, skip it.
		for f in faces where not usedFaces[f] do (
			-- Using the temp function func, get the face IDs of the 
			-- element the current face is in.
			local elem = func obj f
			-- Append the element's face IDs to the elements array.
			append elements elem
			-- Add the face IDs in the element to the usedFaces bitArray.
			usedFaces += elem
		)
		-- Return the elements array.
		elements
	)

After that is evaluated, that function can be called to get the elements as face sets, which in turn can be saved to named selection sets on the object, and the vertices welded:


fn elementsToSelectionSetsAndWeld obj = (
	if (not (isValidNode obj)) then (
		displayTempPrompt "Please select a single object" 5000
	)
	else (
		allowedClasses = #(Editable_Poly,PolyMeshObject,Editable_Mesh)
		objClass = classOf obj
		if (findItem allowedClasses objClass == 0) then (
			displayTempPrompt "Selected object is not an Editable Poly / Editable Mesh" 5000
		)
		else (
			myElements = getElements obj
			for i = 1 to myElements.count do (
				obj.faces["Element #" + i as string] = myElements[i]
			)
			obj.selectedVerts = $.vertices
			SetCommandPanelTaskMode #modify
			subObjectLevel = 1

			case objClass of (
				Editable_Poly: (polyOps.weld obj)
				PolyMeshObject: (polyOps.weld obj)
				Editable_Mesh: (meshOps.weld obj)
			)
		)
	)
)
elementsToSelectionSetsAndWeld $

If you take both pieces of code together, select all the code, and drag&drop that selected text to a toolbar, it should create a button for you that you can then use. Note that it’s limited to Editable Mesh and Editable Poly objects, but Edit Poly modifier should be supportable as well.


#5

Thank you kind soul! :beer:


#6

Hi!

I have a similar problem: I have some MAX files here that have about 800 separate 3D objects each. Each of them with its own texture (UVW). I don’t need to keep any groups, I’m just looking for a script or some other way to weld all vertices of each single object at a radius of 0.01.
I’m not very much into scripting and just tried to get the second script part of the above post working for a test scene with two boxes that have vertices at the same positions, but I get a message saying “Call needs function or class, got: undefined”.

It would be great if someone could tell me where to get a script that can weld more than one object in one MAX file (without groups) or how to get the above working.
In case there isn’t a script: I already got a script that selects the objects one after another, I just need to know what to fill in after the selection part to do the welding.

Bests,
Sasa


#7

Not sure what happens to mapping when welding, but I suppose it should be fine.

Try the following… note that it doesn’t bother with any of the threshold settings… for editable poly that -could- be done, for editable mesh I’m not seeing a variable for it… would have to much with more UI code.

Oh, right. There’s a bit of UI code - if you have editable meshes and try to weld vertices on those with no vertices within the weld threshold, it will pop up a dialog telling you as much. So that needs to be automatically closed. So if you’ve got editable meshes, you might hear some beeping when it hits such an object. Annoying :slight_smile:


fn weldVertsOnObjs_dmo = (
	local hwnd = dialogMonitorOps.getWindowHandle()
	local dialogTitle = uiAccessor.getWindowText hwnd
	if (hwnd != 0) AND (dialogTitle == "Weld") do (
		UIAccessor.pressButtonByName hwnd "OK"
	)
	false
)
fn weldVertsOnObjs = (
	objs = getCurrentSelection()
	if (objs.count == 0) then (
		format "No objects selected
"
	)
	else (
		format "Welding vertices on selected objects...
"
		SetCommandPanelTaskMode #modify
		dialogMonitorOps.registernotification weldVertsOnObjs_dmo id:#weldVertsOnObjs_dmo
		dialogMonitorOps.enabled = true
		for obj in objs do (
			allowedClasses = #(Editable_Poly,PolyMeshObject,Editable_Mesh)
			objClass = classOf obj
			if (findItem allowedClasses objClass == 0) then (
				format "Object '%' is not an Editable Mesh or Editable Poly type.  Cannot process.
" obj.name
			)
			else (
				select obj
				format "Processing object '%'...
" obj.name
				obj.selectedVerts = $.vertices
				subObjectLevel = 1

				case objClass of (
					Editable_Poly: (polyOps.weld obj)
					PolyMeshObject: (polyOps.weld obj)
					Editable_Mesh: (meshOps.weld obj)
				)
				format "	Done
"
			)
		)
		dialogMonitorOps.enabled = false
		dialogMonitorOps.unregisternotification id:#weldVertsOnObjs_dmo
		format "Done
"
		deselect $*
	)
)
weldVertsOnObjs()


#8

Maybe I misunderstand your problem but have you tried the vertex weld modifier?


#9

d’oh! :banghead:


#10

Well… doesn’t make much sense so select several thousand objects and weld their vertices by hand…
Richard’s Script helped me a lot - THANK YOU! :bowdown:
Is there an option to get a bigger welding radius? I couldn’t find anything in your script telling me what radius is used. Anyway: Your script reduced the polycount of my working file from 334000 to 302000 and vertex count from 503000 to 170000!

Bests,
Sasa


#11

I think he meant for you to select -all- the objects, and then apply the Vertex Weld modifier; it will then be applied to all the objects (instanced), and each will use the weld threshold setting you specify there.

If an object needs a larger/smaller one, right-click on the modifier and choose ‘make unique’(I think), then dial in the larger/smaller threshold.


#12

Hmm… didn’t know that modifier neither. Interesting that the result somehow is still differend because using your script I can still convert everything into MS Flight Simulator format, while using the weld modifier this doesn’t work. So your script still helped me a lot. Thanks a million!!!

Bests,
Sasa


#13

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.