[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()
)
)
)
)
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.