Guest User

RaycastMatID

a guest
Feb 1st, 2026
56
0
98 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.82 KB | None | 0 0
  1. macroScript RaycastMatID
  2. category:"PoC"
  3. tooltip:"Raycast MatID"
  4. (
  5. fn getFaceMatIDFromNode node faceIndex = (
  6. local matID = undefined
  7. if faceIndex != undefined do (
  8. -- Primary method: Standard Mesh
  9. -- getFaceMatID works reliably on Editable_Mesh nodes.
  10. if (isKindOf node Editable_Mesh) or (classOf node == TriMesh) then (
  11. try ( matID = getFaceMatID node faceIndex ) catch ()
  12. )
  13. -- If it's a Poly, we usually can't trust the FaceIndex (tri) against the Poly structure directly
  14. -- without converting the Poly to Mesh first.
  15. -- So we return undefined, and let the caller handle the layout conversion (via snapshot/fallback).
  16. )
  17. matID
  18. )
  19.  
  20. on execute do (
  21. clearListener()
  22.  
  23. local mousePos = mouse.pos
  24. local viewRay = mapScreenToWorldRay mousePos
  25.  
  26. local hits = intersectRayScene viewRay
  27.  
  28. if hits.count == 0 then ( print "No hit"; return () )
  29.  
  30. local closestNode = undefined
  31. local closestDist = 1.0e9
  32.  
  33. for h in hits do (
  34. local hitNode = h[1]
  35. local hitRay = h[2]
  36. if not hitNode.isHidden do (
  37. local d = distance viewRay.pos hitRay.pos
  38. if d < closestDist do (
  39. closestDist = d
  40. closestNode = hitNode
  41. )
  42. )
  43. )
  44.  
  45. if closestNode == undefined then ( print "No hit (all hidden?)"; return () )
  46.  
  47. -- format "Hit: % class=%\n" closestNode.name (classOf closestNode)
  48.  
  49. local isVRayProxy = matchPattern ((classOf closestNode) as string) pattern:"*VRayProxy*"
  50.  
  51. if not isVRayProxy then (
  52. -- NORMAL MESH/POLY PATH
  53. local tStart = timeStamp()
  54. local exHit = intersectRayEx closestNode viewRay
  55.  
  56. local faceIdx = "NA"
  57. local mID = "NA"
  58. local status = "FAIL"
  59.  
  60. -- Helper to process a successful hit on a node
  61. fn processHit theNode theHit = (
  62. local f = theHit[2] -- face index
  63. local id = getFaceMatIDFromNode theNode f
  64. #(f, id)
  65. )
  66.  
  67. if exHit != undefined then (
  68. faceIdx = exHit[2]
  69. local res = processHit closestNode exHit
  70. if res[2] != undefined then (
  71. mID = res[2]
  72. status = "OK"
  73. ) else (
  74. -- Hit existed, but checking MatID on this specific node type failed (e.g. Poly).
  75. -- Fall through to fallback
  76. status = "NeedMeshFallback"
  77. )
  78. ) else (
  79. status = "RayMissedGeo"
  80. )
  81.  
  82. -- FALLBACK: If we missed OR if we couldn't get MatID (Poly), try snapshot
  83. if status == "RayMissedGeo" or status == "NeedMeshFallback" then (
  84. try (
  85. -- snapshot creates a NEW temp NODE that is a collapsed Editable Mesh
  86. local tempMeshNode = snapshot closestNode
  87.  
  88. local exHitMesh = intersectRayEx tempMeshNode viewRay
  89. if exHitMesh != undefined then (
  90. faceIdx = exHitMesh[2]
  91. mID = getFaceMatIDFromNode tempMeshNode faceIdx
  92. status = "OK_ViaMesh"
  93. ) else (
  94. status = "RayMissedGeo_EvenAsMesh"
  95. )
  96. delete tempMeshNode
  97. ) catch (
  98. status = "FallbackException"
  99. )
  100. )
  101.  
  102. local tEnd = timeStamp()
  103. local dt = tEnd - tStart
  104. format "Hit: % class=% dt=%ms face=% matID=%\n" closestNode.name (classOf closestNode) dt faceIdx mID
  105.  
  106. ) else (
  107. -- VRAYPROXY PATH
  108. local proxyNode = closestNode
  109.  
  110. -- APPROACH A: vrayMeshImport()
  111. local tA0 = timeStamp()
  112. local resA_Face = "NA"
  113. local resA_MatID = "NA"
  114. local resA_Count = 0
  115. local statusA = "FAIL"
  116.  
  117. try (
  118. local oldSel = selection as array
  119. select proxyNode
  120.  
  121. local imported = undefined
  122. try ( imported = vrayMeshImport() ) catch ( statusA = "FuncNotFound" )
  123.  
  124. if imported != undefined and classOf imported == Array and imported.count > 0 then (
  125. resA_Count = imported.count
  126. local meshObj = imported[1]
  127. meshObj.transform = proxyNode.transform
  128.  
  129. local exHit = intersectRayEx meshObj viewRay
  130. if exHit != undefined then (
  131. resA_Face = exHit[2]
  132. local foundID = getFaceMatIDFromNode meshObj resA_Face
  133. if foundID != undefined then resA_MatID = foundID
  134. statusA = "OK"
  135. ) else ( statusA = "MissedImportMesh" )
  136.  
  137. delete imported
  138. ) else (
  139. if statusA != "FuncNotFound" then statusA = "ImportReturnedEmpty"
  140. )
  141. select oldSel
  142. ) catch ( statusA = "Exception: " + (getCurrentException()) )
  143.  
  144. local tA1 = timeStamp()
  145. local dtA = tA1 - tA0
  146. format "ApproachA: dt=%ms, face=%, matID=%, importedMeshes=%, status=%\n" dtA resA_Face resA_MatID resA_Count statusA
  147.  
  148.  
  149. -- APPROACH B: Snapshot (Display Mesh + EditPoly + Snapshot)
  150. local tB0 = timeStamp()
  151. local resB_Face = "NA"
  152. local resB_MatID = "NA"
  153. local statusB = "FAIL"
  154. local oldDisplay = undefined
  155. local modAdded = undefined
  156.  
  157. try (
  158. if isProperty proxyNode #display then (
  159. oldDisplay = proxyNode.display
  160. proxyNode.display = 3 -- Whole mesh
  161. )
  162.  
  163. modAdded = Edit_Poly()
  164. addModifier proxyNode modAdded
  165.  
  166. -- Create a snapshot NODE (Editable Mesh) of this state
  167. -- This treats it 'like a normal mesh' for the raycaster
  168. local tempNode = snapshot proxyNode
  169.  
  170. local exHit = intersectRayEx tempNode viewRay
  171. if exHit != undefined then (
  172. resB_Face = exHit[2]
  173. resB_MatID = getFaceMatIDFromNode tempNode resB_Face
  174. statusB = "OK"
  175. ) else (
  176. statusB = "MissedSnapshot"
  177. )
  178.  
  179. delete tempNode
  180.  
  181. ) catch ( statusB = "Exception: " + (getCurrentException()) )
  182.  
  183. -- Cleanup B
  184. if modAdded != undefined do (
  185. local modIndex = undefined
  186. for m = 1 to proxyNode.modifiers.count do (
  187. if proxyNode.modifiers[m] == modAdded do modIndex = m
  188. )
  189. if modIndex != undefined do deleteModifier proxyNode modIndex
  190. )
  191. if oldDisplay != undefined do proxyNode.display = oldDisplay
  192.  
  193. local tB1 = timeStamp()
  194. local dtB = tB1 - tB0
  195. format "ApproachB: dt=%ms, face=%, matID=%, status=%\n" dtB resB_Face resB_MatID statusB
  196. )
  197. )
  198. )
  199.  
Advertisement
Add Comment
Please, Sign In to add comment