ScriptSpot

Forum topic · Scripts Wanted

select and detach vertices using maxscript

By zwrtron · 2019-02-09

Description

Hello, is there a way to select certain vertices and detach them to new object using maxscript?

I have following geometry merged together (called boxes) and I would like to detach one of them to new object.

I would like to select all vertices of this geometry, where X-axis is possitive (right box) or negative (left box) and detach them to new object.
How can I do that?

Thanks!

 

Comments (10)

.

miauu · 2019-02-16


(
	global rol_detachByXpos
	try(destroyDialog rol_detachByXpos)catch()
	rollout rol_detachByXpos "Detach by X pos"
	(
		local poDetachVerts = polyop.detachVerts
		local poGetVert = polyop.getVert
		
		button btn_detachPosX "Detach positive X" width:140
		button btn_detachNegX "Detach negative X" width:140
		
		function DetachVertsByXpos xSide: =
		(
			if selection.count != 0 do
			(
				selObjsArr = selection as array
				for o in selObjsArr where classOf o == Editable_Poly do
				(
					vertsCnt = o.numverts
					posXBA = #{}
					negXBA = #{}
					for v = 1 to vertsCnt do
					(
						vPos = poGetVert o v
						if vPos.x > 0 do posXBA[v] = true
						if vPos.x < 0 do negXBA[v] = true
					)
					case xSide of
					(
						#positive:
						(
							if not posXBA.isEmpty do
							(
								poDetachVerts o posXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
							)
						)
						
						#negative:
						(
							if not negXBA.isEmpty do
							(
								poDetachVerts o negXBA delete:true asNode:true name:(o.name + "_detachedNegativeX") node:o
							)
						)
					)
				)
			)
		)
		
		on btn_detachposX pressed do
		(
			DetachVertsByXpos xSide:#positive
		)
		on btn_detachNegX pressed do
		(
			DetachVertsByXpos xSide:#negative
		)
	)
	createdialog rol_detachByXpos 
	
)

Thank you

zwrtron · 2019-02-16

Working like a charm exactly like I except.
But any chance to make it work on plane for example? Like it cuts plane in half which has edge in the middle (pos 0)
Figure:
https://i.imgur.com/9QKVTXl.png
Thank you so much!

.

miauu · 2019-02-16

Try this using Detach by Face:




(
	global rol_detachByXpos
	try(destroyDialog rol_detachByXpos)catch()
	rollout rol_detachByXpos "Detach by X pos"
	(
		local poDetachVerts = polyop.detachVerts
		local poDetachFaces = polyop.detachFaces
		local poGetVert = polyop.getVert
		local poGetFacesUsingVert = polyop.getFacesUsingVert
 
		radiobuttons rb_detachBy "Detach:" labels:#("verts", "faces") default:1 columns:1
		
		button btn_detachPosX "Detach positive X" width:140
		button btn_detachNegX "Detach negative X" width:140
 
		function DetachVertsByXpos xSide: =
		(
			if selection.count != 0 do
			(
				selObjsArr = selection as array
				for o in selObjsArr where classOf o == Editable_Poly do
				(
					vertsCnt = o.numverts
					posXBA = #{}
					negXBA = #{}
					for v = 1 to vertsCnt do
					(
						vPos = poGetVert o v
						if vPos.x > 0 do posXBA[v] = true
						if vPos.x < 0 do negXBA[v] = true
					)
					case xSide of
					(
						#positive:
						(
							if not posXBA.isEmpty do
							(
								if rb_detachBy.state == 1 then
									poDetachVerts o posXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
								else
								(
									poDetachFaces o (poGetFacesUsingVert o posXBA) delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
								)
							)
						)
 
						#negative:
						(
							if not negXBA.isEmpty do
							(
								if rb_detachBy.state == 1 then
									poDetachVerts o negXBA delete:true asNode:true name:(o.name + "_detachedNegativeX") node:o
								else
								(
									poDetachFaces o (poGetFacesUsingVert o negXBA) delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
								)
							)
						)
					)
				)
			)
		)
 
		on btn_detachposX pressed do
		(
			DetachVertsByXpos xSide:#positive
		)
		on btn_detachNegX pressed do
		(
			DetachVertsByXpos xSide:#negative
		)
	)
	createdialog rol_detachByXpos 
 
)

or if it not works as expected:




(
	global rol_detachByXpos
	try(destroyDialog rol_detachByXpos)catch()
	rollout rol_detachByXpos "Detach by X pos"
	(
		local poDetachFaces = polyop.detachFaces
		local poGetFaceCenter = polyop.getFaceCenter
 		
		button btn_detachPosX "Detach positive X" width:140
		button btn_detachNegX "Detach negative X" width:140
 
		function DetachVertsByXpos xSide: =
		(
			if selection.count != 0 do
			(
				selObjsArr = selection as array
				for o in selObjsArr where classOf o == Editable_Poly do
				(
					facesCnt = o.numfaces
					posXBA = #{}
					negXBA = #{}
					for v = 1 to facesCnt do
					(
						fPos = poGetFaceCenter o v
						if fPos.x > 0 do posXBA[v] = true
						if fPos.x < 0 do negXBA[v] = true
					)
					case xSide of
					(
						#positive:
						(
							if not posXBA.isEmpty do
							(
								poDetachFaces o posXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
							)
						)
 
						#negative:
						(
							if not negXBA.isEmpty do
							(
								poDetachFaces o negXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
							)
						)
					)
				)
			)
		)
 
		on btn_detachposX pressed do
		(
			DetachVertsByXpos xSide:#positive
		)
		on btn_detachNegX pressed do
		(
			DetachVertsByXpos xSide:#negative
		)
	)
	createdialog rol_detachByXpos 
 
)

zwrtron · 2019-02-17

Unfortunately, both don't. :(

.

jahman · 2019-02-17

you can simply create a copy of your object and apply slice modifier with remove bottom to original and remove top to copy

GIF click if it refuses to play

zwrtron · 2019-02-18

@jahman - Thank for contribution, that's the way I've been doing it manually until now.
However, do you think that this approach is more effective than @miauu script? Because using slice works on both editable geometry and primitives where the script only on editable poly.

.

jahman · 2019-02-18

I personally like slice approach since it isn't destructive.
The only problem to solve here is to align slice plane to world axis properly.


ref = copy $
addModifier $ (SliceModifier Slice_Type:2)
$.modifiers[1].slicePlane.transform = inverse ($.objectTransform * RotateYMatrix 90)

addModifier ref (SliceModifier Slice_Type:2)
ref.modifiers[1].slicePlane.transform = inverse (ref.objectTransform * RotateYMatrix 270)

zwrtron · 2019-02-20

I'll use this method seems to work on all examples I've tried.
Thank you very much.

.

miauu · 2019-02-17


(
	global rol_sliceOnXaxis
	try(destroyDialog rol_sliceOnXaxis)catch()
	rollout rol_sliceOnXaxis "Slice on X axis"
	(
		local poDetachFaces = polyop.detachFaces
		local poGetFaceCenter = polyop.getFaceCenter
		local poSlice = polyop.slice
 
		button btn_detachPosX "Detach positive X" width:140
		button btn_detachNegX "Detach negative X" width:140
 			
		function SliceAndDetach xSide: = with undo "Slice and Detach" on
		(
			if selection.count != 0 do
			(
				selObjsArr = selection as array
				dir = normalize ([100,0,0] - [-100,0,0])
				for o in selObjsArr do
				(
					o.split = on
					poSlice o #all (ray [0,0,0] dir)
					update o
					facesCnt = o.numfaces
					posXBA = #{}
					negXBA = #{}
					for v = 1 to facesCnt do
					(
						fPos = poGetFaceCenter o v
						if fPos.x > 0 do posXBA[v] = true
						if fPos.x < 0 do negXBA[v] = true
					)
					case xSide of
					(
						#positive:
						(
							if not posXBA.isEmpty do
							(
								poDetachFaces o posXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
							)
						)

						#negative:
						(
							if not negXBA.isEmpty do
							(
								poDetachFaces o negXBA delete:true asNode:true name:(o.name + "_detachedPositiveX") node:o
							)
						)
					)	
				)
			)
		)
 
		on btn_detachposX pressed do
		(
			SliceAndDetach xSide:#positive
		)
		on btn_detachNegX pressed do
		(
			SliceAndDetach xSide:#negative
		)
	)
	createdialog rol_sliceOnXaxis 
 
)

zwrtron · 2019-02-18

@miauu - Thank you very much, exactly what I've been looking for.