Notifications
Clear all

[Closed] scripted geometry plugin test

Ok, I created this roof light scripted object, and I think it’s quite cool.
There is some issue though, with cetrain steps of the width sements, the sine wave function is behaving faulty. I suspect there is some rounding error, but I’m not sure what it is.
This is my first try with this kind of stuff, I’d appreciate some C&C.
Maybe there are more elegant ways to do things?


plugin simpleObject rp_rooflight
name:"Roof Light"
classID:#(0xc139ae3, 0x4c925cf6)
category:"Scripted Primitives"
version:1.0
( 
	local box1
	local box0
	local plane1

	parameters creation rollout:creation
	(
		creation_method type:#integer ui:creation_method default:2
	)
	parameters params rollout:params
	(
		length type:#worldUnits ui:length default:0
		width type:#worldUnits ui:width default:0
		height type:#worldUnits ui:height default:1E-3
		lenghtsegments type:#integer ui:lenghtsegments default:10
		widthsegments type:#integer ui:widthsegments default:10
		smooth type:#boolean ui:smooth default:true
		frame_enabled type:#boolean ui:frame_enabled default:true
		frame_width type:#float ui:frame_width default:1E-3
		frame_height type:#float ui:frame_height default:1E-3
		mapcoords type:#boolean ui:mapcoords default:true animatable:false
		realWorldMapSize type:#boolean ui:rwMapSize default:false animatable:false
	)
parameters advanced rollout:advanced
	(
		autoedge type:#boolean ui:autoedge default:off
		autoedge_threshold type:#float ui:autoedge_threshold default:24
		remove_sides type:#boolean ui:remove_sides default:false
	)
rollout creation "Creation Method"
(
	radiobuttons creation_method labels:#("Cube	 ","Box	")
)
rollout params "Parameters"
(
	spinner length "Length:" type:#worldUnits range:[1E-3,1E9,0]
	spinner width "Width:" type:#worldUnits range:[1E-3,1E9,0]
	spinner height "Height:" type:#worldUnits range:[-1E9,1E9,0]
	spinner lenghtsegments "Lenght Segs:" type:#integer range:[1,1000,10] offset:[0,8]
	spinner widthsegments "Width Segs:" type:#integer range:[1,1000,10]
	checkbox smooth "Smooth" align:#right
	
	group "Frame"
	(
		checkbox frame_enabled "Enabled"
		spinner frame_width "Width: " type:#worldUnits range:[1E-3,1E9,0]
		spinner frame_height "Height: " type:#worldUnits range:[-1E9,1E9,0]
	)
	checkbox mapcoords "Generate Mapping Coords."
	checkbox rwMapSize "Real-World Map Size"
)
rollout advanced "Advanced"
(
	group "Auto Edge"
	(
		checkbutton autoedge "Auto Edge" across:2 offset:[-2,0]
		spinner autoedge_threshold type:#float range:[1E-3,1E9,24] align:#right width:65 offset:[0,2]
	)
	checkbox remove_sides "Remove Sides"
)
on Load do 
(
)		
on buildMesh do
(
	fn transformMesh theTriMesh theMatrix =
	(
		for v = 1 to theTriMesh.numverts do
		setVert theTriMesh v ((getVert theTriMesh v)*theMatrix)
		theTriMesh
	)

	if box0 == undefined then
	(
		box1 = createInstance box
		box0 = createInstance box
		plane1 = createInstance plane lengthsegs:lenghtsegments widthsegs:widthsegments
	)

		--avoid negative hole size
	size=amin #(width,length)
	if frame_width>(size/2) then frame_width=size/2
	
	local inner_width=width
	local inner_length=length
	if frame_enabled then 
	(
		inner_width=width-frame_width*2
		inner_length=length-frame_width*2
	)
	
	box1.height = frame_height
	box1.width = width
	box1.length = length
	box0.height = frame_height
	
	box0.width = inner_width
	box0.length = inner_length
	
	plane1.width = inner_width
	plane1.length = inner_length

	box1.mapcoords = mapcoords
	box1.realWorldMapSize = realWorldMapSize
	box0.mapcoords = mapcoords
	box0.realWorldMapSize = realWorldMapSize
	plane1.mapcoords = mapcoords
	plane1.realWorldMapSize = realWorldMapSize

	------------------------------------------------------
	-- WAVE DEFORM PLANE START
	------------------------------------------------------
	tempwave=TriMesh()
	tempwave = plane1.mesh
	local tempwave_verts=tempwave.verts
	local currentvert=1
	local width_segments_distance=1.0/widthsegments
	local length_segments_distance=1.0/lenghtsegments
	for l=0.0 to 1 by length_segments_distance do
	(
		y=l*Pi*(180.0/Pi)
		for w=0.0 to 1 by width_segments_distance do
		(
			x=w*Pi*(180.0/Pi)
			z=sin (x)*sin(y)*height
			tempwave_verts[currentvert].pos+= [0,0,z]
			currentvert+=1
		)
	)
	------------------------------------------------------
	-- WAVE DEFORM PLANE END
	------------------------------------------------------
	
	tempmesh=TriMesh()
	if frame_enabled then 
	(
		tempmesh.mesh=box1.mesh
		for i = 5 to 12 do setFaceMatID tempmesh i 1000 --assign mat id to side faces, to find them again after boolean
			--boolean create frame
		if frame_enabled then tempmesh-=box0.mesh
	)
		
	------------------------------------------------------
	-- REMOVE SIDES START
	------------------------------------------------------
	if (remove_sides and frame_enabled) then
	(
		local sidefaces=#{} --init bitarray
		for i = 1 to tempmesh.numfaces do 
		(
			if (getFaceMatID tempmesh i)==1000 then append sidefaces i  --collect all faces with previously stored mat ID
		)
		meshop.deleteFaces tempmesh sidefaces  --delete side faces
	)
	
		--all tempmesh edges as bitarray
	local tempmesh_edges=tempmesh.edges as bitarray
	------------------------------------------------------
	-- REMOVE SIDES END
	------------------------------------------------------
	
	local tempwave_faces=tempwave.mesh.faces as bitarray
	if not smooth then meshop.autoSmooth tempwave tempwave_faces 0
		
	meshop.attach tempmesh tempwave

	------------------------------------------------------
	-- AUTO EDGE START
	------------------------------------------------------
		--do auto edge
	if autoedge then meshop.autoEdge tempmesh tempmesh_edges autoedge_threshold
	------------------------------------------------------
	-- AUTO EDGE END
	------------------------------------------------------
	------------------------------------------------------
	-- EDGE SELECTION START
	------------------------------------------------------
		--function by denisT
	fn isEdgeVisible emesh edge_index = if (iskindof emesh Editable_Mesh or iskindof emesh TriMesh) do
	(
		edge_index -= 1
		if (face_index = edge_index/3 + 1) <= emesh.numFaces do
		(
			edge_index_in_face = (mod edge_index 3) + 1
			getEdgeVis emesh face_index edge_index_in_face
		)
	)
		--set  edge selection to visible edges
	local edgeSelSet=#{}
	for i in tempmesh_edges do
	(
			if (isEdgeVisible tempmesh i) do append edgeSelSet i --collect the edge

	)
	setEdgeSelection tempmesh edgeSelSet --keep:false-- Select all visible edges
	------------------------------------------------------
	-- EDGE SELECTION END
	------------------------------------------------------

	
	--meshop.applyUVWMap tempmesh #box --tm:m3NodeTM --utile:2 vtile:2 wtile:2

	
	mesh = TriMesh()
	mesh=tempmesh.mesh

		--clean up temp meshes
	delete tempmesh
	delete tempwave
)
tool create
(
	on mousePoint click do
		case click of
		(
			1: nodeTM.translation = gridPoint
			3:
			(
				if (not frame_enabled) then #stop
			)
			4:
			(
				if frame_enabled then #stop
			)
		)
	on mouseMove click do
		case click of
		(
			2: (
						--cube creation mode
					if (creation_method==1) then 
					(
						width = length = abs gridDist.x
					)
						--box creation mode
					else 
					(
						width = abs gridDist.x
						length = abs gridDist.y
						nodeTM.translation = gridPoint - [gridDist.x/2,gridDist.y/2,0]
					)
				
				)
			3: (
					if frame_enabled then
					(
						frame_width = abs gridDist.x
						frame_height = frame_width
					)
					else height = gridDist.z
				)
			4:
				(
				if frame_enabled then height = gridDist.z
					else stop()
				)
		)
	)
)


2 Replies

plugin simpleObject rp_rooflight
name:"Roof Light"
classID:#(0xc139ae3, 0x4c925cf6)
category:"Scripted Primitives"
version:1.0
( 
	local box1
	local box0
	local plane1

	parameters creation rollout:creation
	(
		creation_method type:#integer ui:creation_method default:2
	)
	parameters params rollout:params
	(
		length type:#worldUnits ui:length default:0
		width type:#worldUnits ui:width default:0
		height type:#worldUnits ui:height default:1E-3
		lenghtsegments type:#integer ui:lenghtsegments default:10
		widthsegments type:#integer ui:widthsegments default:10
		smooth type:#boolean ui:smooth default:true
		frame_enabled type:#boolean ui:frame_enabled default:true
		frame_width type:#float ui:frame_width default:1E-3
		frame_height type:#float ui:frame_height default:1E-3
		mapcoords type:#boolean ui:mapcoords default:true animatable:false
		realWorldMapSize type:#boolean ui:rwMapSize default:false animatable:false
	)
parameters advanced rollout:advanced
	(
		autoedge type:#boolean ui:autoedge default:off
		autoedge_threshold type:#float ui:autoedge_threshold default:24
		remove_sides type:#boolean ui:remove_sides default:false
	)
rollout creation "Creation Method"
(
	radiobuttons creation_method labels:#("Cube	 ","Box	")
)
rollout params "Parameters"
(
	spinner length "Length:" type:#worldUnits range:[1E-3,1E9,0]
	spinner width "Width:" type:#worldUnits range:[1E-3,1E9,0]
	spinner height "Height:" type:#worldUnits range:[-1E9,1E9,0]
	spinner lenghtsegments "Lenght Segs:" type:#integer range:[1,1000,10] offset:[0,8]
	spinner widthsegments "Width Segs:" type:#integer range:[1,1000,10]
	checkbox smooth "Smooth" align:#right
	
	group "Frame"
	(
		checkbox frame_enabled "Enabled"
		spinner frame_width "Width: " type:#worldUnits range:[1E-3,1E9,0]
		spinner frame_height "Height: " type:#worldUnits range:[-1E9,1E9,0]
	)
	checkbox mapcoords "Generate Mapping Coords."
	checkbox rwMapSize "Real-World Map Size"
)
rollout advanced "Advanced"
(
	group "Auto Edge"
	(
		checkbutton autoedge "Auto Edge" across:2 offset:[-2,0]
		spinner autoedge_threshold type:#float range:[1E-3,1E9,24] align:#right width:65 offset:[0,2]
	)
	checkbox remove_sides "Remove Sides"
)
on Load do 
(
)		
on buildMesh do
(
	--avoid negative hole size
	size=amin #(width,length)
	if frame_width>(size/2) then frame_width=size/2
	
	local inner_width=width
	local inner_length=length
	if frame_enabled then 
	(
		inner_width=width-frame_width*2
		inner_length=length-frame_width*2
	)
	
	box1 = createInstance box \
		width:width length:length height:frame_height mapcoords:mapcoords realWorldMapSize:realWorldMapSize
	box0 = createInstance box \
		width:inner_width length:inner_length height:frame_height mapcoords:mapcoords realWorldMapSize:realWorldMapSize
	plane1 = createInstance plane lengthsegs:lenghtsegments widthsegs:widthsegments \
		width:inner_width length:inner_length mapcoords:mapcoords realWorldMapSize:realWorldMapSize


	------------------------------------------------------
	-- WAVE DEFORM PLANE START
	------------------------------------------------------
--	tempwave=TriMesh()
	tempwave = copy plane1.mesh
	local tempwave_verts=tempwave.verts
	local num_verts=tempwave.numverts
	local currentvert=1
	local width_segments_factor=180./widthsegments
	local length_segments_factor=180./lenghtsegments
	for y=0 to lenghtsegments do
	(
		py = y*length_segments_factor
		for x=0 to widthsegments do
		(
			px = x*width_segments_factor
			z=(sin px)*(sin py)*height
			tempwave_verts[currentvert].pos.z += z
			currentvert += 1
		)
	)
	------------------------------------------------------
	-- WAVE DEFORM PLANE END
	------------------------------------------------------
	
	tempmesh=TriMesh()
	if frame_enabled then 
	(
		tempmesh.mesh=box1.mesh
		for i = 5 to 12 do setFaceMatID tempmesh i 1000 --assign mat id to side faces, to find them again after boolean
			--boolean create frame
		if frame_enabled then tempmesh-=box0.mesh
	)
		
	------------------------------------------------------
	-- REMOVE SIDES START
	------------------------------------------------------
	if (remove_sides and frame_enabled) then
	(
		local sidefaces=#{} --init bitarray
		for i = 1 to tempmesh.numfaces do 
		(
			if (getFaceMatID tempmesh i)==1000 then append sidefaces i  --collect all faces with previously stored mat ID
		)
		meshop.deleteFaces tempmesh sidefaces  --delete side faces
	)
	
		--all tempmesh edges as bitarray
	local tempmesh_edges=tempmesh.edges as bitarray
	------------------------------------------------------
	-- REMOVE SIDES END
	------------------------------------------------------
	
	local tempwave_faces=tempwave.mesh.faces as bitarray
	if not smooth then meshop.autoSmooth tempwave tempwave_faces 0
		
	meshop.attach tempmesh tempwave

	------------------------------------------------------
	-- AUTO EDGE START
	------------------------------------------------------
		--do auto edge
	if autoedge then meshop.autoEdge tempmesh tempmesh_edges autoedge_threshold
	------------------------------------------------------
	-- AUTO EDGE END
	------------------------------------------------------
	------------------------------------------------------
	-- EDGE SELECTION START
	------------------------------------------------------
		--function by denisT
	fn isEdgeVisible emesh edge_index = if (iskindof emesh Editable_Mesh or iskindof emesh TriMesh) do
	(
		edge_index -= 1
		if (face_index = edge_index/3 + 1) <= emesh.numFaces do
		(
			edge_index_in_face = (mod edge_index 3) + 1
			getEdgeVis emesh face_index edge_index_in_face
		)
	)
		--set  edge selection to visible edges
	local edgeSelSet=#{}
	for i in tempmesh_edges do
	(
			if (isEdgeVisible tempmesh i) do append edgeSelSet i --collect the edge

	)
	setEdgeSelection tempmesh edgeSelSet --keep:false-- Select all visible edges
	------------------------------------------------------
	-- EDGE SELECTION END
	------------------------------------------------------

	
	--meshop.applyUVWMap tempmesh #box --tm:m3NodeTM --utile:2 vtile:2 wtile:2

	
--	mesh = TriMesh()
	mesh=tempmesh.mesh

		--clean up temp meshes
	delete tempmesh
	delete tempwave
)
tool create
(
	on mousePoint click do
		case click of
		(
			1: nodeTM.translation = gridPoint
			3:
			(
				if (not frame_enabled) then #stop
			)
			4:
			(
				if frame_enabled then #stop
			)
		)
	on mouseMove click do
		case click of
		(
			2: (
						--cube creation mode
					if (creation_method==1) then 
					(
						width = length = abs gridDist.x
					)
						--box creation mode
					else 
					(
						width = abs gridDist.x
						length = abs gridDist.y
						nodeTM.translation = gridPoint - [gridDist.x/2,gridDist.y/2,0]
					)
				
				)
			3: (
					if frame_enabled then
					(
						frame_width = abs gridDist.x
						frame_height = frame_width
					)
					else height = gridDist.z
				)
			4:
				(
				if frame_enabled then height = gridDist.z
					else stop()
				)
		)
	)
)

I optimized Mesh Build, and fixed Plane Deform…

other things are pretty clean.

Hi Dennis,
Thanks a lot for fixing the code, I owe you something!

local width_segments_factor=180./widthsegments

This one puzzled me for a moment until I realized that it’s just a shorter version of 180.0
Didn’t know it’s possible to write it that way.

Scripted objects are great fun, now I just need to find out how to easily build UVW maps for those TriMeshes.