Notifications
Clear all

[Closed] Custom Geo + Tube

Below in my script I create my own custom plane. When users hit the enable button I want them to be able to create with it a Tube, but rather than me creating the tube from scratch I wanted to just create and instance of the primitive tube and then modifier it from there. How can I integrate the tube to my custom plane and it actually be part of the mesh along with the settings adjusting the size of the tube?


plugin simpleObject IntegratedMesh 
name:"IntegratedMesh"
category:"Standard Primitives"
classID:#(0x512e8ff9, 0x51aefc78)
(

	parameters main rollout:rltParams
	(		
		enableTube type:#boolean default:false ui:uiEnableTube	
		tubeRadius type:#worldUnits default:6 ui:uiTubeRadius
		
		frameWidth type:#worldUnits default:30 ui:uiFrameWidth	
		frameSegs type:#integer default:4 ui:uiFrameSegs	
	)
	
	rollout rltParams "Parameters"
	(
		checkbox uiEnableTube "Enable Tube" offset:[6,4]
		spinner uiTubeRadius "Tube Radius:" range:[.1,1e9,0] type:#worldUnits
		
		spinner uiFrameWidth "Frame Width:" range:[0,1e9,0] type:#worldunits offset:[0,6]
		spinner uiFrameSegs "Segments:" range:[2,1e9,1] type:#integer
	)

	fn genFramePlatform start:[0,0,0] =
	(
		local FrameVerts = #()
		
		/* Create first strip of verts */
		for r = 0 to frameSegs-1 do
		(
			rowSet = (frameWidth/(frameSegs-1))*r
				
			for s = 0 to frameSegs-1 do
			(
				offset = (frameWidth/(frameSegs-1))*s
				vertPos = start + [offset,rowSet,0]
				append FrameVerts vertPos
			)
		)
		return FrameVerts
	)
	
	fn genMesh = 
	(	
		/*Set Vertices*/
		local verticesArr = #()
			
		/* Platform of Verts */
		frameVerts = genFramePlatform start:[0,0,0]
		join verticesArr frameVerts
		
 		/*Set Faces*/
   		local facesArr = #()
		
		local count = frameSegs
		local endCounter = count
		local loops = frameSegs * frameSegs - frameSegs --total number of verts minus last set
		
		for l = 1 to loops do
		(
			if l < endCounter then --less then
			(
				append facesArr [l+1, l, l+count]
 				append facesArr [l+count ,  l+count+1 , l+1 ] 
			)else(
				--only needed if planning on connecting start/end edges like a tube
				endCounter += count --reset strip of verts
			)
		)
		/*Set Mesh*/
		platformMesh = setMesh mesh verts:verticesArr faces:facesArr
		
		/* Tube */
		if enableTube do
		(
			local tub = createinstance Tube pos:[0,0,0] sides:8 heightsegs:20 capsegs:1 height:30 radius1:tubeRadius radius2:(tubeRadius/2) smooth:on
			setMesh mesh tub.mesh
			free tub
		)
		
		update mesh
	)
	
	on buildMesh do (genMesh())
	
	tool create
	(
		on mousePoint click do ()
		on mouseMove click do ()
	)
)
delete objects
clearlistener()
m = IntegratedMesh()
m.vertexticks = true
select m

12 Replies

updated the code above. I got the tube to display but not with the plane i create…?

I saw this practice used in Denis plugin http://forums.cgsociety.org/showthread.php?t=1030472

I tried to see how he went about doing it, but it was not clear to me how it would work in my case where it’s part custom geo and part primitive.

No one has any idea’s on where I’m going wrong with this?

1 Reply
(@bobo)
Joined: 10 months ago

Posts: 0

Replace the line

			setMesh mesh tub.mesh

with

			meshop.attach mesh tub.mesh

Aaaaaa… nice That does the trick
so close.

Now I tried looking up what the term
‘free’ meant in maxscript and there was no description that I could find.

I saw it here on cgtalk in a few posts of geo plugins. Does anyone know what the point of that function is?

Thanks again bobo for your help!

1 Reply
(@bobo)
Joined: 10 months ago

Posts: 0

See here:
http://docs.autodesk.com/3DSMAX/16/ENU/MAXScript-Help//files/GUID-31E273C4-9248-49A0-B357-4B8F8023385D.htm

Free() Method

The free() method has been implemented since 3ds Max 9 but has remained undocumented. This method frees the memory used by the value without waiting for a garbage collection to occur. It is implemented for the following classes: String Value, StringStream Value, FileStream Value, BitMap Value, Array Value, BitArray Value, Mesh Value

Nicely done. I tried searching for it online in the docs but they were taking forever and turning up results that didn’t help.

On a side note.

Now in the script below, I use a for-loop which allows me to copy the mesh multiple times and I store it in variable called meshes=#().
From there I then attach all those to the main mesh by using the meshop.attach mesh m.

Is there an easy way to offset each one of those elements by a random value for example
how would I apply this offset to each mesh before or after it gets attached?
offset = [random 0 50,0,0]
Unless the only way to do it is by going vert by vert for each mesh, that works to I suppose.



plugin simpleObject IntegratedMesh 
name:"IntegratedMesh"
category:"Standard Primitives"
classID:#(0x512e8ff9, 0x51aefc78)
(

	parameters main rollout:rltParams
	(		
		enableTube type:#boolean default:false ui:uiEnableTube	
		tubeRadius type:#worldUnits default:6 ui:uiTubeRadius
		
		frameWidth type:#worldUnits default:30 ui:uiFrameWidth	
		frameSegs type:#integer default:4 ui:uiFrameSegs	
	)
	
	rollout rltParams "Parameters"
	(
		checkbox uiEnableTube "Enable Tube" offset:[6,4]
		spinner uiTubeRadius "Tube Radius:" range:[.1,1e9,0] type:#worldUnits
		
		spinner uiFrameWidth "Frame Width:" range:[0,1e9,0] type:#worldunits offset:[0,6]
		spinner uiFrameSegs "Segments:" range:[2,1e9,1] type:#integer
	)

	fn genFramePlatform start:[0,0,0] =
	(
		local FrameVerts = #()
		
		/* Create first strip of verts */
		for r = 0 to frameSegs-1 do
		(
			rowSet = (frameWidth/(frameSegs-1))*r
				
			for s = 0 to frameSegs-1 do
			(
				offset = (frameWidth/(frameSegs-1))*s
				vertPos = start + [offset,rowSet,0]
				append FrameVerts vertPos
			)
		)
		return FrameVerts
	)
	
	fn genMesh = 
	(	
		/*Set Vertices*/
		local verticesArr = #()
			
		/* Platform of Verts */
		frameVerts = genFramePlatform start:[0,0,0]
		join verticesArr frameVerts
		
 		/*Set Faces*/
   		local facesArr = #()
		
		local count = frameSegs
		local endCounter = count
		local loops = frameSegs * frameSegs - frameSegs --total number of verts minus last set
		
		for l = 1 to loops do
		(
			if l < endCounter then --less then
			(
				append facesArr [l+1, l, l+count]
 				append facesArr [l+count ,  l+count+1 , l+1 ] 
			)else(
				--only needed if planning on connecting start/end edges like a tube
				endCounter += count --reset strip of verts
			)
		)
		/*Set Mesh*/
		platformMesh = setMesh mesh verts:verticesArr faces:facesArr
		
		/*Dupe Meshes*/
		local meshes = #()
		for i = 1 to 5 do 
		(
			append meshes (copy mesh)
		)
		
		for m in meshes do 	
		(
			meshop.attach mesh m
		)
			
		/* Tube */
		if enableTube do
		(
			local tub = createinstance Tube pos:[0,0,0] sides:8 heightsegs:20 capsegs:1 height:30 radius1:tubeRadius radius2:(tubeRadius/2) smooth:on
			meshop.attach mesh tub.mesh
			free tub
		)
		
		update mesh
	)
	
	on buildMesh do (genMesh())
	
	tool create
	(
		on mousePoint click do ()
		on mouseMove click do ()
	)
)
delete objects
clearlistener()
m = IntegratedMesh()
m.vertexticks = true
select m

Got it working
Now I can just throw a weld in there and its a wrap. This by no means is a complete tool, but more so just an R&D setup



plugin simpleObject IntegratedMesh 
name:"IntegratedMesh"
category:"Standard Primitives"
classID:#(0x512e8ff9, 0x51aefc78)
(

	parameters main rollout:rltParams
	(		
		enableTube type:#boolean default:false ui:uiEnableTube	
		tubeRadius type:#worldUnits default:6 ui:uiTubeRadius
		
		frameWidth type:#worldUnits default:30 ui:uiFrameWidth	
		frameSegs type:#integer default:4 ui:uiFrameSegs	
	)
	
	rollout rltParams "Parameters"
	(
		checkbox uiEnableTube "Enable Tube" offset:[6,4]
		spinner uiTubeRadius "Tube Radius:" range:[.1,1e9,0] type:#worldUnits
		
		spinner uiFrameWidth "Frame Width:" range:[0,1e9,0] type:#worldunits offset:[0,6]
		spinner uiFrameSegs "Segments:" range:[2,1e9,1] type:#integer
	)

	fn genFramePlatform start:[0,0,0] =
	(
		local FrameVerts = #()
		
		/* Create first strip of verts */
		for r = 0 to frameSegs-1 do
		(
			rowSet = (frameWidth/(frameSegs-1))*r
				
			for s = 0 to frameSegs-1 do
			(
				offset = (frameWidth/(frameSegs-1))*s
				vertPos = start + [offset,rowSet,0]
				append FrameVerts vertPos
			)
		)
		return FrameVerts
	)
		
	fn genMesh = 
	(	
		/*Set Vertices*/
		local verticesArr = #()
			
		/* Platform of Verts */
		frameVerts = genFramePlatform start:[0,0,0]
		join verticesArr frameVerts
		
 		/*Set Faces*/
   		local facesArr = #()
		
		local count = frameSegs
		local endCounter = count
		local loops = frameSegs * frameSegs - frameSegs --total number of verts minus last set
		
		for l = 1 to loops do
		(
			if l < endCounter then --less then
			(
				append facesArr [l+1, l, l+count]
 				append facesArr [l+count ,  l+count+1 , l+1 ] 
			)else(
				--only needed if planning on connecting start/end edges like a tube
				endCounter += count --reset strip of verts
			)
		)
		/*Set Mesh*/
		platformMesh = setMesh mesh verts:verticesArr faces:facesArr
		
		/*Dupe Meshes*/
		local meshes = #()
		for i = 1 to 5 do 
		(
			tmpMesh = copy mesh
			offsetVerts = for v in tmpMesh.vertices collect (v.pos+[frameWidth*i,0,0])
			setmesh tmpMesh vertices:offsetVerts
			
			append meshes tmpMesh
		)
		
		for m in meshes do 	
		(
			meshop.attach mesh m
		)
			
		/* Tube */
		if enableTube do
		(
			local tub = createinstance Tube pos:[0,0,0] sides:8 heightsegs:20 capsegs:1 height:30 radius1:tubeRadius radius2:(tubeRadius/2) smooth:on
			meshop.attach mesh tub.mesh
			free tub
		)
		
		update mesh
	)
	
	on buildMesh do (genMesh())
	
	tool create
	(
		on mousePoint click do ()
		on mouseMove click do ()
	)
)
delete objects
clearlistener()
m = IntegratedMesh()
m.vertexticks = true
select m

plugin simpleObject IntegratedMesh 
name:"IntegratedMesh"
category:"Standard Primitives"
classID:#(0x512e8ff9, 0x51aefc78)
(

	parameters main rollout:rltParams
	(		
		enableTube type:#boolean default:false ui:uiEnableTube	
		tubeRadius type:#worldUnits default:6 ui:uiTubeRadius
		
		frameWidth type:#worldUnits default:30 ui:uiFrameWidth	
		frameSegs type:#integer default:4 ui:uiFrameSegs	
		
		numDupes type:#integer default:5 ui:uiNumDupes
		DupeDist type:#float default:10 ui:uiDupeDist
	)
	
	rollout rltParams "Parameters"
	(
		checkbox uiEnableTube "Enable Tube" offset:[6,4]
		spinner uiTubeRadius "Tube Radius:" range:[.1,1e9,0] type:#worldUnits
		
		spinner uiFrameWidth "Frame Width:" range:[0,1e9,0] type:#worldunits offset:[0,6]
		spinner uiFrameSegs "Segments:" range:[2,1e9,1] type:#integer
		
		spinner uiNumDupes "Duplicates:" range:[0,100,5] type:#integer offset:[0,3]
		spinner uiDupeDist "Distance:" range:[0,100000,10] type:#worldunits offset:[0,3]
		
	)

	fn genFramePlatform start:[0,0,0] =
	(
		local FrameVerts = #()
		
		/* Create first strip of verts */
		for r = 0 to frameSegs-1 do
		(
			rowSet = (frameWidth/(frameSegs-1))*r
				
			for s = 0 to frameSegs-1 do
			(
				offset = (frameWidth/(frameSegs-1))*s
				vertPos = start + [offset,rowSet,0]
				append FrameVerts vertPos
			)
		)
		return FrameVerts
	)
	
	fn genMesh = 
	(	
		/*Set Vertices*/
		local verticesArr = #()
			
		/* Platform of Verts */
		frameVerts = genFramePlatform start:[0,0,0]
		join verticesArr frameVerts
		
 		/*Set Faces*/
   		local facesArr = #()
		
		local count = frameSegs
		local endCounter = count
		local loops = frameSegs * frameSegs - frameSegs --total number of verts minus last set
		
		for l = 1 to loops do
		(
			if l < endCounter then --less then
			(
				append facesArr [l+1, l, l+count]
 				append facesArr [l+count ,  l+count+1 , l+1 ] 
			)else(
				--only needed if planning on connecting start/end edges like a tube
				endCounter += count --reset strip of verts
			)
		)
		/*Set Mesh*/
		platformMesh = setMesh mesh verts:verticesArr faces:facesArr
		
		/*Dupe Meshes*/
		local meshes = #()
		for i = 1 to numDupes do 
		(
			local newMesh = copy mesh
			meshop.moveVert newMesh #{1..(newMesh.numverts)} [0,0,i*DupeDist] 
			append meshes newMesh
		)
		
		for m in meshes do 	
		(
			meshop.attach mesh m
			free m
		)		
		
		free meshes
			
		/* Tube */
		if enableTube do
		(
			local tub = createinstance Tube pos:[0,0,0] sides:8 heightsegs:20 capsegs:1 height:30 radius1:tubeRadius radius2:(tubeRadius/2) smooth:on
			meshop.attach mesh tub.mesh
			free tub
		)
		
		update mesh
	)
	
	on buildMesh do (genMesh())
	
	tool create
	(
		on mousePoint click do ()
		on mouseMove click do ()
	)
)
delete objects
clearlistener()
m = IntegratedMesh()
m.vertexticks = true
select m
1 Reply
(@jokermartini)
Joined: 10 months ago

Posts: 0

Now in this case say that I attached the meshes and I want to further adjust the placement of the verts within the entire main mesh. How can I go about adjusting those verts?
Would I place something like this right above the ‘update mesh’?


meshop.moveVert mesh #{1..(mesh.numverts)} [0,0,i*50]

Nicely done Bobo.
This will sure make for some interesting custom geo ideas I have. Thank you for your help on all of this.

Can you add a modifier to a mesh in the custom geo? for example a shell modifier?