gpearson100

Find Coinstances 1.01

Sep 22nd, 2020
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.66 KB | None | 0 0
  1. -- https://stackoverflow.com/questions/53210099/removing-overlapping-faces-in-3dsmax
  2. -- Written By Colin Senner
  3. -- www.colinsenner.com
  4.  
  5. -- Functions
  6. global trim_dupsArray
  7. global findPolyCoinstancedFaces
  8. global findMeshCoinstancedFaces
  9. global findCoinstancedObjects
  10. global compareCenterAndNormalsPoly
  11. global compareCenterAndNormalsMesh
  12.  
  13. -- Rollouts
  14. global rlt_findCoinstances
  15.  
  16. -- Variables
  17. global todo
  18.  
  19. if rlt_findCoinstances != undefined then destroyDialog rlt_findCoinstances
  20.  
  21.  
  22. rollout rlt_findCoinstances "Find Coinstances 1.01" (
  23. dropDownList lst_todo items:#("Select Only Duplicates","Select All") selection:1 width:140
  24. button btn_Find "Find" width:70
  25. button btn_Help "?" offset:[60,-24] height:16 width:20
  26. on lst_todo selected sel do ( todo = sel )
  27.  
  28. on btn_Help pressed do (
  29. local txt = ""
  30. txt += "Help Dialog v1.01 - Find CoInstances, by Colin Senner\n\n"
  31. txt += "Find CoInstances works in two ways:\n\n"
  32. txt += " 1. With Multiple Objects selected it will find objects that are cloned on top of each other\n"
  33. txt += " resulting in animation flickering because of coplanarity\n\n"
  34. txt += " 2. With a single object selected it will find and select faces that are coplanar\n\n"
  35. txt += "To select all faces which are coplanar use the list-box to \"Select All\", or\n"
  36. txt += "To select only those faces which are copies of the original, use \"Select Only Duplicates\"\n"
  37. messagebox txt title:"Help" beep:false
  38. )
  39.  
  40. on btn_Find pressed do (
  41. local objs = getCurrentSelection()
  42.  
  43. if objs.count == 1 then (
  44. if classof objs[1] == Editable_Poly then (
  45. if lst_todo.selection == 1 then
  46. dupFaces = (findPolyCoinstancedFaces objs[1] returnOnlyDupes:true)
  47. else if lst_todo.selection == 2 then
  48. dupFaces = (findPolyCoinstancedFaces objs[1] returnOnlyDupes:false)
  49. ) else if classof objs[1] == Editable_Mesh then (
  50. if lst_todo.selection == 1 then
  51. dupFaces = (findMeshCoinstancedFaces objs[1] returnOnlyDupes:true)
  52. else if lst_todo.selection == 2 then
  53. dupFaces = (findMeshCoinstancedFaces objs[1] returnOnlyDupes:false)
  54. ) else (
  55. messageBox "Please select an editable poly or mesh."
  56. return false
  57. )
  58.  
  59. objs[1].selectedFaces = dupFaces
  60. subObjectLevel = 4
  61. ) else (
  62. -- Multiple Objects Selected
  63. clearSelection()
  64. dupObjs = (findCoInstancedObjects objs)
  65. select dupObjs
  66. )
  67. )
  68. )
  69. createDialog rlt_findCoinstances 160 60
  70.  
  71.  
  72. fn findPolyCoinstancedFaces obj returnOnlyDupes:false = (
  73. local objArrSFC = #()
  74. local objArrNrm = #()
  75. local dupFaces = #{}
  76. format "findpoly returnOnlyDupes:%\n" returnOnlyDupes
  77.  
  78. if classof obj == Editable_Poly then (
  79. for i = 1 to obj.faces.count do (
  80. objArrSFC[i] = (polyOp.getSafeFaceCenter obj i)
  81. objArrNrm[i] = (polyOp.getFaceNormal obj i)
  82. )
  83. dupFaces = (compareCenterAndNormalsPoly objArrSFC objArrNrm returnOnlyDupes:returnOnlyDupes)
  84. ) else
  85. return undefined
  86.  
  87. dupFaces
  88. )
  89.  
  90. -- Looks through two arrays for Matching SafeFaceCenters if matching another in the array,
  91. -- if found, checks arrNrm array to see if the normals or inverse normals match
  92. fn compareCenterAndNormalsPoly arrSFC arrNrm returnOnlyDupes:false = (
  93. local dupBitArr = #{}
  94. local invNrm, index
  95.  
  96. for i = 1 to arrSFC.count do (
  97. index = findItem arrSFC arrSFC[i]
  98. if index != 0 and index != i then (
  99. local invNrm = (arrNrm[index]*[-1,-1,-1])
  100. if (arrNrm[i] == arrNrm[index]) or (arrNrm[i] == invNrm) then (
  101. dupBitArr[i] = true
  102. if not(returnOnlyDupes) then
  103. dupBitArr[index] = true
  104. print dupBitArr
  105. )
  106. )
  107. )
  108. dupBitArr
  109. )
  110.  
  111. -- Looks through two arrays for Matching SafeFaceCenters if matching another in the array,
  112. -- if found, checks arrNrm array to see if the normals or inverse normals match
  113. fn compareCenterAndNormalsMesh arrSFC arrNrm returnOnlyDupes:false = (
  114. local dupBitArr = #{}
  115. local invNrm, index
  116.  
  117. for i = 1 to arrSFC.count do (
  118. index = findItem arrSFC arrSFC[i]
  119. if index != 0 and index != i then (
  120. local invNrm = for p in arrNrm[index] collect (p*[-1,-1,-1])
  121.  
  122. if ((arrNrm[i] as string) == (arrNrm[index] as string)) or ((arrNrm[i] as string) == (invNrm as string)) then (
  123. dupBitArr[i] = true
  124. if not(returnOnlyDupes) then
  125. dupBitArr[index] = true
  126. print dupBitArr
  127. )
  128. )
  129. )
  130. dupBitArr
  131. )
  132.  
  133. -- findMeshCoinstancedFaces returns a bitarray of coplanar faces
  134. fn findMeshCoinstancedFaces obj returnOnlyDupes:false = (
  135. local objArrSFC = #()
  136. local objArrNrm = #()
  137. local dupFaces = #{}
  138.  
  139. if classof obj == Editable_Mesh then (
  140. for i = 1 to obj.faces.count do (
  141. objArrSFC[i] = (meshOp.getFaceCenter obj i)
  142. objArrNrm[i] = (meshOp.getFaceRNormals obj i)
  143. )
  144. dupFaces = (compareCenterAndNormalsMesh objArrSFC objArrNrm returnOnlyDupes:returnOnlyDupes)
  145. ) else
  146. return undefined
  147.  
  148. dupFaces
  149. )
  150.  
  151. -- findCoinstancedObjects returns an array of duplicate objects
  152. fn findCoinstancedObjects arr = (
  153. local dupObjs = #()
  154.  
  155. for o in arr do (
  156. for j in arr where o != j do (
  157. -- Defex code hack for selecting only the duplicate
  158. if ((o.transform as string) == (j.transform as string)) and (o.min == j.min) and (o.max == j.max) and (o.wirecolor == j.wirecolor) then (
  159. append dupObjs j
  160. j.wirecolor = color 250 243 210
  161. )
  162. -- end Defex code
  163. --if ((o.transform as string) == (j.transform as string)) and (o.min == j.min) and (o.max == j.max) then
  164. --append dupObjs j
  165. )
  166. )
  167. trim_dupsArray dupObjs
  168. )
  169.  
  170. fn trim_dupsArray a = (
  171. for i in a.count to 1 by -1 do
  172. (
  173. idx = findItem a a[i]
  174. if (idx != 0) AND (idx != i) do (
  175. deleteItem a i
  176. )
  177. )
  178. a
  179. )
  180.  
  181. /*fn trim_dupsArrayString arr = (
  182. for i=arr.count to 1 by -1 do (
  183. for j=arr.count to 1 by -1 do (
  184. if i != j and (arr[i] as string) == (arr[j] as string) then (
  185. deleteItem arr j
  186. )
  187. )
  188. )
  189. arr
  190. )*/
Add Comment
Please, Sign In to add comment