Looking for intersection checking script...


#1

(Just realized I posted this in the wrong section earlier)

Recap:
I seem to remember seeing a script at some point that would highlight in red any intersecting faces between objects. But now I can’t find it. Did I imagine the whole thing?? Could someone can let me know either a) where that script can be found (if it exists) or b) how to set something like that up (if it doesn’t)? Thanks in advance!

I guess this is just geometry based collision detection… I’ve done stuff using IntersectRay before but with objects having complex shapes it becomes problematic (something along the lines of two hands with interlocking fingers for example).


#2

I’ve gotten to something that sort-of works – it finds all of the intersecting faces but seems to come up with a lot of “false positives”. I’m pretty sure that I’m doing the ray calculations wrong, but I don’t know what I’m supposed to be doing instead.

(To test this, it helps to have a multi-sub material on the objects. I’ll work that part of the script out a little better when I have the intersections working correctly.)

fArray = #() -- face array
    intersectCount = 0
    
    -- Populate faceVerts_Array
     for s = 1 to selection.count do
      (
      append fArray #()
      
     for f = 1 to (getNumFaces selection[s]) do
      (
      append fArray[s] #()
      
      vArray = meshop.getVertsUsingFace selection[s] f
      
      for v in vArray do
      (
      vertPos = meshop.getVert selection[s] v
      append fArray[s][f] vertPos
      ) -- end v loop
      ) -- end f loop
      ) -- end s loop
      
      for s = 1 to selection.count do
      (
      for f = 1 to fArray[s].count do
      (
      for v = 1 to fArray[s][f].count do
      (
      if v != fArray[s][f].count
      then
      (
      theRayF = ray fArray[s][f][v] (normalize (fArray[s][f][v + 1] - fArray[s][f][v]))
      theRayB = ray fArray[s][f][v + 1]	(normalize (fArray[s][f][v] - fArray[s][f][v + 1]))
      )
      else
      (
      theRayF = ray fArray[s][f][v] (normalize (fArray[s][f][1] - fArray[s][f][v]))
      theRayB = ray fArray[s][f][1] (normalize (fArray[s][f][v] - fArray[s][f][1]))
      )
      				
      for t = 1 to selection.count do
      (
      if selection[t] != selection[s] do
      (
      if (intersectRayEx selection[t] theRayF) != undefined do
      (
      --format "% face % hits % face %
" selection[s].name f selection[t].name
      (intersectRayEx selection[t] theRayF)[2]
      intersectCount = intersectCount + 1
           						
      setFaceMatID selection[s] f 2
      meshop.setFaceColor selection[s] 2 #{f} (color 255 0 0)
      						
      setFaceMatID selection[t] (intersectRayEx selection[t] theRayF)[2] 2
      meshop.setFaceColor selection[t] 2 #{f} (color 255 0 0)
      )
       )
       ) -- end t loop
       ) -- end v loop
       ) -- end f loop
       ) -- end s loop
       
           format "
Intersect count: %

" intersectCount

(also, what is up with the tabs on these forums??)


#3

Wow, I really should have checked that a bit more thoroughly before saying it worked. It… doesn’t. Can someone help me figure out why?


#4

Hi Malkalypse,
In general your method was in a very good direction, it only needed a few fixes.

Here is my interpretation:

(
	local intCount = 0
	local objs = for o in selection where isKindOf o editable_mesh collect o
	local ts = timeStamp()
	
	if objs.count > 1 then (
		progressStart "Checking Intersections... "
		
		for i = 1 to objs.count do (
			local numFaces = getNumFaces objs[i]
			
			for f = 1 to numFaces do (
				local verts = (meshop.getVertsUsingFace objs[i] f) as array
				local vertsPos = for v in verts collect meshop.getVert objs[i] v
				
				local rays = #()
				local raysLength = #()
				
				if verts.count == 3 then (
					for v = 1 to 3 do (
						local u = ((mod v 3) + 1) as integer
						local rayLength = distance vertsPos[v] vertsPos[u]
						
						append rays (ray vertsPos[v] (normalize(vertsPos[u] - vertsPos[v])))
						append rays (ray vertsPos[u] (normalize(vertsPos[v] - vertsPos[u])))
						
						join raysLength #(rayLength, rayLength)
					) -- end v loop
				) -- end if verts
				
				for j = 1 to objs.count where j != i and intersects objs[i] objs[j] do (
					for r = 1 to rays.count do (
						local newInt = intersectRayEx objs[j] rays[r]
						if newInt != undefined and distance rays[r].pos newInt[1].pos <= raysLength[r] then (
							intCount += 1
							
							--setFaceMatID objs[i] f 2
							meshop.setFaceColor objs[i] 0 #{f} (color 255 0 0)
							
							--setFaceMatID objs[j] newInt[2] 2
							meshop.setFaceColor objs[j] 0 #{newInt[2]} (color 255 0 0)
							
							exit
						) -- end if int
					) -- end r loop
				) -- end j loop
				
				progressUpdate (100.0 * (((i - 1.0) / objs.count) + (1.0 / objs.count) * (1.0 * f / numFaces)))
			) -- end f loop
			
			objs[i].vertexColorType = #color
			objs[i].shadeVertexColors = 1
			objs[i].showVertexColors = true
			gc()
		) -- end i loop
		progressEnd()
	) -- and if objs.count > 1
	
	format "
Intersection count: %
" intCount
	format "Intersection checking time: %

" ((timeStamp() - ts) / 1000.0)
)

#5

Thanks so much, That seems to work perfectly! I’m still not sure why mine didn’t but I’ll take a look to compare our scripts when I get a chance :slight_smile:


#6

The main difference between our versions is that I also check if the intersection happens somewhere in the middle of the edge or outside it with this test:

distance rays[r].pos newInt[1].pos <= raysLength[r]

you only checked if there was an intersection but the intersection could happen anywhere from the point where the ray begins and on the line defined by it’s direction and not only inside the edge.

Most of the other changes I did where for optimization reasons, like reducing the number of loops and variables, and exiting loops when they aren’t needed anymore.


#7

Ahhh, I missed checking the distance! That would definitely explain it!

But yeah, your code is much cleaner than mine as well. I’m sure I will end up using it a lot – I hope you don’t mind if I incorporate it as a function into other scripts down the line? (I’ll be sure to credit you if I end up sharing the scripts with any clients)


#8

No problem… :slight_smile:
Just from curiosity, what are you doing with this?
I tried to think of cool things to do with this script but couldn’t think of anything too interesting.


#9

I’m working on some medical illustrations that involve a large number of objects (bones, muscles, and nerves) all packed tightly together. It can sometimes be difficult to tell if these objects are visibly interpenetrating each other just by looking at them in the viewport.

Renders can show that they are in fact passing through each other at various places, but with high poly models it can be difficult to track the exact faces this is occuring with. Internal interpenetration is not that big a deal since it will not show up in renders, so this way all I need to do is look for red faces that are visible, and adjust them slightly.

In the space of a few hours yesterday, I managed to reduce over 800 interpenetrations to about 300 (the remaining interpenetrations being unnoticable in the rendered image and therefor inconsequential.)


#10

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.