Does anyone know a good solution to achieve selection of similar geometry by selecting #all and comparing their bbox, position, vertex count?
I can find only code pieces which I can’t put together — any script-monster I do doesn’t work properly
Does anyone know a good solution to achieve selection of similar geometry by selecting #all and comparing their bbox, position, vertex count?
I can find only code pieces which I can’t put together — any script-monster I do doesn’t work properly
right now I have something like this:
dobj=#()
ar0=#()
global factorValue = 0.1
function comparesize obj1 obj2 factor = (
s1 = obj1.max - obj1.min --determine bounding boxes
s2 = obj2.max - obj2.min
if (s2.x >= (s1.x*(1-factor)) AND s2.x <= (s1.x*(1+factor))) OR (s2.x >= (s1.y*(1-factor)) AND s2.x <= (s1.y*(1+factor))) OR (s2.x >= (s1.z*(1-factor)) AND s2.x <= (s1.z*(1+factor)))THEN
if (s2.y >= (s1.y*(1-factor)) AND s2.y <= (s1.y*(1+factor))) OR (s2.y >= (s1.x*(1-factor)) AND s2.y <= (s1.x*(1+factor))) OR (s2.y >= (s1.z*(1-factor)) AND s2.y <= (s1.z*(1+factor))) THEN
if (s2.z >= (s1.z*(1-factor)) AND s2.z <= (s1.z*(1+factor))) OR (s2.z >= (s1.x*(1-factor)) AND s2.z <= (s1.x*(1+factor))) OR (s2.z >= (s1.y*(1-factor)) AND s2.z <= (s1.y*(1+factor))) THEN
(
return true
)
else return false
else return false
else return false
)
for i in selection do (
num=getNumVerts i.mesh
compSize = comparesize ar0 i factorValue
print compSize
if findItem ar0 num == 0 then (
append ar0 num
)
else if compSize == false then (
append ar0 num
)
else append dobj i
)
select dobj
CompleteRedraw()
it doesn’t work because I don’t know how to loop throught selected array with comparesize function
miauu, appreciate! but I already took a part of it for my needs which I showed above.
I think I looked through everything, even bought DDO (didn’t get a copy though)
I have to go to sleep now(here is 03:015 after midnight) but you can upload a test scene to show which objects are “similar” for you. I have tested the Select Similar script from scriptspot on 4 boxes(1 main and 3 copies) and when the Size(Bounding box) is on the script selects all 4 boxes as objects with similar sizes. Position and vertex count are easy to be added to the script.
thanks! here’s the scene with:
https://drive.google.com/open?id=17DEGbh5wHWa5aQmnJ6KQYDCsA4i9d3zs
the behavior I’m trying to create:
OK. But can you tell the names of 3-4 objects that are the same and the criteria that you use to “mark” them as “the same”?
OK. Those objects have the same verts count, size and overall shape. But why the script to which I gave you a link(and whcih you have tested) not works? Please, watch this video, where the same scirpt is used and it selects similar objects.
https://drive.google.com/open?id=1drAsbjgtl_VAHTnBvTY6ENEkodAJF_tR
thanks for the video!
it is work for single mesh comparison but I want to compare all (or selected) scene objects at once and select all duppies
Try this:
(
global rol_selectSimilar
try(destroyDialog rol_selectSimilar)catch()
rollout rol_selectSimilar "Select Similar"
(
checkBox chkBox_selectByBBox "Size(Bounding Box)"
checkBox chkBtn_vertsFaceCount "Verts/FAces count"
button btn_selectSimilar "Select Similar"
function GetShapeMeshPolyCount obj =
(
oldState = obj.render_renderable -- keep rend. state
obj.render_renderable = true -- set to true for next operation
res = (getPolygonCount obj) as string -- get Real mesh (v,f) !
obj.render_renderable = oldState -- restore state
res -- return result
)
on btn_selectSimilar pressed do
(
selObjsArr = selection as array
if selObjsArr.count != 0 do
(
similarObjsArr = #()
for i = 1 to selObjsArr.count where isValidNode selObjsArr[i] do
(
iObj = selObjsArr[i]
iMeshData = #(0,0)
if chkBtn_vertsFaceCount.checked do
(
iMeshData = if isShapeObject iObj then
(
GetShapeMeshPolyCount iObj
)
else
(
(getPolygonCount iObj) as string
)
)
for j = selObjsArr.count to i + 1 by -1 where isValidNode selObjsArr[j] do
(
if chkBox_selectByBBox.checked do
(
if (nodeGetBoundingBox iObj iObj.transform) as string == (nodeGetBoundingBox selObjsArr[j] selObjsArr[j].transform) as string do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
if chkBtn_vertsFaceCount.checked do
(
if isShapeObject selObjsArr[j] then
(
if (GetShapeMeshPolyCount selObjsArr[j]) == iMeshData do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
else
(
if (getPolygonCount selObjsArr[j]) as string == iMeshData do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
)
)
)
if similarObjsArr.count != 0 do select similarObjsArr
)
)
)
createdialog rol_selectSimilar
)
Select the objects you want to check and use the script. It will select all similar objects.
for some reason I can’t use it. If I tick both options I get:

but if I use only bbox option it work!
I have tested it in Max 2009. The script works with no errors when the both checkboxes are not turned On at the same time. Please, see this video: https://drive.google.com/open?id=19ZrdOAFSw6TepeBHTVzeThlJPJ2KKpzD
This should works with both checkboxes turned ON
(
global rol_selectSimilar
try(destroyDialog rol_selectSimilar)catch()
rollout rol_selectSimilar "Select Similar"
(
checkBox chkBox_selectByBBox "Size(Bounding Box)"
checkBox chkBtn_vertsFaceCount "Verts/FAces count"
button btn_selectSimilar "Select Similar"
function GetShapeMeshPolyCount obj =
(
oldState = obj.render_renderable -- keep rend. state
obj.render_renderable = true -- set to true for next operation
res = (getPolygonCount obj) as string -- get Real mesh (v,f) !
obj.render_renderable = oldState -- restore state
res -- return result
)
on btn_selectSimilar pressed do
(
selObjsArr = selection as array
if selObjsArr.count != 0 do
(
similarObjsArr = #()
for i = 1 to selObjsArr.count where isValidNode selObjsArr[i] do
(
iObj = selObjsArr[i]
iMeshData = #(0,0)
if chkBtn_vertsFaceCount.checked do
(
iMeshData = if isShapeObject iObj then
(
GetShapeMeshPolyCount iObj
)
else
(
(getPolygonCount iObj) as string
)
)
for j = selObjsArr.count to i + 1 by -1 where isValidNode selObjsArr[j] do
(
if chkBox_selectByBBox.checked do
(
if (nodeGetBoundingBox iObj iObj.transform) as string == (nodeGetBoundingBox selObjsArr[j] selObjsArr[j].transform) as string do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
if chkBtn_vertsFaceCount.checked and isValidNode selObjsArr[j] do
(
if isShapeObject selObjsArr[j] then
(
if (GetShapeMeshPolyCount selObjsArr[j]) == iMeshData do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
else
(
if (getPolygonCount selObjsArr[j]) as string == iMeshData do
(
appendIfUnique similarObjsArr selObjsArr[j]
deleteitem selObjsArr j
)
)
)
)
)
if similarObjsArr.count != 0 do select similarObjsArr
)
)
)
createdialog rol_selectSimilar
)
here is how i would search geometrically same objects (i would use mesh vertex positions hash)…
as you can see transform of objects doesn’t matter in this case:
fn roundFloat d pre:0.001 =
(
d = (d as float)/pre
v = if (d - (v1 = floor d)) > ((v2 = ceil d) - d) then v2 else v1
v*pre
)
fn roundPoint3 p pre:0.001 =
(
p.x = roundFloat p.x pre:pre
p.y = roundFloat p.y pre:pre
p.z = roundFloat p.z pre:pre
p
)
fn getMeshHash obj round:0 =
(
hash = 0
mesh = obj.mesh
for k=1 to mesh.numverts do
(
p = getvert mesh k
if round > 0 do roundPoint3 p pre:round
hash = gethashvalue p hash
)
hash
)
/*
delete objects
for k=1 to 100 do
(
teapot segs:(random 4 6) pos:(random -[100,100,100] [100,100,100]) rotation:(eulerangles 0 0 (random 0 180)) scale:([0.2,0.2,0.2] * (random 1 3))
)
-- find all the same as one selected:
(
node = selection[1]
hash = getMeshHash node
same = for obj in geometry where (getMeshHash obj) == hash collect obj
)
*/
you can use “round” to have less accuracy but adding some tolerance
you can use the hashing method to find similar (same) bounding boxes as well.
it needs only one point (size) or four points (transform) for hashing
here is a snippet to play with:
try(destroydialog FindSameRol) catch()
rollout FindSameRol "Find Same with denisT" width:191
(
fn roundFloat d pre:0.001 =
(
d = (d as float)/pre
v = if (d - (v1 = floor d)) > ((v2 = ceil d) - d) then v2 else v1
v*pre
)
fn roundPoint3 p pre:0.001 =
(
p.x = roundFloat p.x pre:pre
p.y = roundFloat p.y pre:pre
p.z = roundFloat p.z pre:pre
p
)
fn getBBoxHash obj round:0 hash:0 =
(
--bb = nodeLocalBoundingBox obj
tm = translate (rotate (scalematrix [1,1,1]) obj.transform.rotation) obj.transform.position
bb = nodeGetBoundingBox obj tm
size = bb[2] - bb[1]
if round > 0 do roundPoint3 size pre:round
gethashvalue size hash
)
fn getAnimHash obj round:0 hash:0 =
(
tm = obj.transform
for k=1 to 3 do
(
p = tm[k]
if round > 0 do roundPoint3 p pre:round
hash = gethashvalue p hash
)
hash
)
fn getMeshHash obj round:0 hash:0 =
(
mesh = obj.mesh
for k=1 to mesh.numverts do
(
p = getvert mesh k
if round > 0 do roundPoint3 p pre:round
hash = gethashvalue p hash
)
hash
)
group "Search: "
(
checkbox check_bbox_ch "Check Bounding Box" checked:off offset:[0,0]
checkbox check_anim_ch "Check Orientation" checked:off offset:[0,0]
checkbox check_mesh_ch "Check Geometry" checked:on
button find_same_bt "Find Same Objects" width:172 align:#left offset:[-4,4]
progressbar pb width:172 height:8 color:orange align:#left offset:[-4,-2]
label info_lb ">> " align:#left offset:[0,0]
)
group "Debug: "
(
button make_scene_bt "Make Test Scene" width:172 align:#left offset:[-4,0]
)
fn runCompare source targets compare_fn color: =
(
pb.value = 0.0
pb.color = color
hash = compare_fn source
found = #()
for k=1 to targets.count do
(
pb.value = 100.0 * k / targets.count
target = targets[k]
if (compare_fn target) == hash do append found target
)
found
)
on find_same_bt pressed do undo "Find Same" on
(
if iskindof (source = selection[1]) GeometryClass do
(
pb.value = 0.0
targets = geometry as array
if check_bbox_ch.state do
(
targets = runCompare source targets getBBoxHash color:green
)
if check_anim_ch.state do
(
targets = runCompare source targets getAnimHash color:blue
)
if check_mesh_ch.state do
(
targets = runCompare source targets getMeshHash color:orange
)
if targets.count > 0 do select targets
info_lb.text = ">> " + targets.count as string + " objects found"
)
)
on make_scene_bt pressed do undo "Make Test Scene" on
(
delete objects
for k=1 to 100 do
(
teapot segs:(random 4 6) pos:(random -[100,100,100] [100,100,100]) rotation:(eulerangles 0 0 (90 *(random 0 3))) scale:([0.2,0.2,0.2] * (random 1 3))
)
select objects[random 1 objects.count]
)
)
createdialog FindSameRol