Notifications
Clear all

[Closed] intersectRayScene not working… ?

For some reason intersectRayScene produces random results.

I have rock type objects floating over a sloping surface, and the ray is defined by the rock pos and is pointing straight down in Z at the surface. Sometimes it finds the terrain surface, and other times not, or it detects itself and nothing else…

I’ve been previously attaching objects in the scene so I know which object to intersectRay with to get a HitPos, but attaching gets to be waaay to slow with alot of geo. Using intersectRayScene is alot faster…if/when it works…

Any ideas? Thanks!

14 Replies
1 Reply
(@denist)
Joined: 1 year ago

Posts: 0

i don’t believe it. give a sample… i’m using intersectRayScene for many years and i’ve never seen a problem.

 lo1

If I remember correctly intersectRayScene doesn’t play well with editable poly objects.

Ahh… hmm, damn. I might have to stick with my attach method then… :(. At least for the automated option.

Basically, any object in the scene besides the selection can be used to get a position/ hit distance for my script. So unless they choose the object to check against, the automated method has to find the best match and use that without interaction.

When intersectRayScene works, it’s great, but my attach method would always work, but is 2-3x slower, or more, the bigger the scene gets.

Here’s my sceneI’m testing with.

Try using this code below, to Drop the Floating Rocks to the surface. Some will drop down, but others won’t. I know I can optomize my code somewhat, I saw a post on what you did for distance sorting.

-- I forgot who I got this Vector Code from on CGTalk, but thank you!
fn getVectorsAngle v1 v2 =
(
acos (dot (normalize v1) (normalize v2))
)
fn getNormalVector v1 v2 =
(
normalize (cross v1 v2)
)
fn rotateMatrix tm q =
(
x = tm.row1 * q
y = tm.row2 * q
z = tm.row3 * q
matrix3 x y z tm.pos
)

Start = timeStamp()
selection1 = selection as Array

dir = [0,0,-1]

 with redraw off
(
	for o in selection1 do
	(
		
		local theObj = for n in (intersectRayScene (ray o.pos (dir))) where not n[1].isHidden collect n --intersectRayScene (ray o.pos (dir)) -- collecting intersections

		if (theObj.count != 0) do 
		(
			local objArray = #()
			
			for obj in theObj do 
			(
				append objArray obj[1]
			)
			
			local selExists = finditem objArray o 
			if selExists != 0 do deleteItem objArray selExists
			
			if (objArray.count >  1) then
			(
				local dist = 10000000000
				
				for obj in objArray do 
				(
					local dist2 = distance (obj.pos) o.pos
					
					if dist2 < dist do theObj = obj
				)
			)
			else
			(
				theObj = objArray[1]
			)
			
			local theHitPos = intersectRay theObj (ray o.pos dir)
			local dist = distance (o.pos) (theHitPos.pos)

			move o (dist * dir)
				
			theNorm = theHitPos.dir

			za = o.transform.row3 * -1
			zb = theNorm * -1  --polyop.getfacenormal $Plane01 4 --b.transform.row3
			
			ang = getVectorsAngle za zb
			norm = getNormalVector za zb
			q = quat -ang norm -- not sure why the angle has to be negative, but it works...
			
			o.transform = rotateMatrix o.transform q
		)
	)
)

end = timeStamp()
format "Processing took % seconds
" ((end - start) / 1000.0)
1 Reply
(@denist)
Joined: 1 year ago

Posts: 0

i see the bug.
the function doesn’t return right intersection result for example for (ray $Sphere822.pos [0,0,1])

to make it work you have to move ray’s position along ray’s direction a little bit. unfortunately it hard to say what amount to move has to be. so i would move as far as possible. in this case we might get some extra nodes intersected that behind the original ray, but it still be faster than convert to mesh (or duplicate with mesh) all geometry objects in the scene.

Yep, like lo said, if I convert the Terrain Geo to Editable_Mesh, it works just fine.

 lo1

In an object placement tool I once wrote, I worked around this by creating mesh snapshots of all scene geometry and hiding the originals. This was surprisingly faster to execute than it sounds.

Hmm… yeah I was just thinking that too. I guess I could try that. So that would be less memory intensive/faster than attaching geo? I would assume so.

Edit: So I did what you said, and it’s something like 5-7x faster than my attach method :). I’ll have to re-write some things in my main script and all should be good

Thanks!

 lo1

If it helps you, this is my object placement tool.

tool PlaceObj prompt:"Left click to place the asset in the scene. Right click to place the asset in default position. Hold SHIFT to ignore surface orientation." numPoints:2
(
	fn sortByHitDistance n1 n2 = if n1[2] < n2[2] then -1 else if n1[2] > n2[2] then 1 else 0 	
	
	local theAssets, gR
	local _qsort = qsort
	local _translate = translate
	local _matFromNorm = matrixFromNormal
	local _iRay = intersectRay
	local hitNodes
	
	on start do
	(		
		setWaitCursor()
		theAssets = (selection as array)
		hitNodes = for o in (geometry as array) where not o.isSelected and not o.isHiddenInVpt and not o.boxMode and o.renderable collect
		(	
			local snap = snapshot o
			snap.wirecolor = o.wirecolor
			snap			
		)
		gR = point pos:[selection.center.x,selection.center.y,selection.min.z] cross:off
		for o in theAssets where o.parent==undefined do o.parent=gR
		setArrowCursor()
	)
	
	on freeMove do
	(
		local theRay = mapScreenToWorldRay viewPoint
		local hit_results = for o in hitNodes collect 
		(
			local n = _iRay o theRay
			if n!=undefined then #(n, distance theRay.pos n.pos) else dontCollect
		)		
		if hit_results.count>0 then 
		(
			_qsort hit_results sortByHitDistance
			if shiftKey then gr.transform = _translate (matrix3 1) hit_results[1][1].pos
				else gr.transform = _translate (_matFromNorm hit_results[1][1].dir) hit_results[1][1].pos
		)		
		else gr.transform = _translate (matrix3 1) worldPoint
	)
	
	on mouseAbort arg do gR.transform = (matrix3 1)
	
	on stop do
	(
		with undo off (delete gR)
		with undo off delete hitNodes
		select theAssets
	)
)

Yeah, that’s kinda what I thought Denis. But then the concern was if i pushed too far past the object, causing it to not detect the surface properly. Doing the snapshotasMesh seems to work pretty fast.

Before I was using the built in Voxel method, using RayMeshGridIntersect(). But this uses up alot of memory and takes quite a bit of time to build before starting. I was only using this before because I wasn’t sure/ didn’t know I could use the intersectRayScene method to get the object to check against. But now using this, my script runs like I said, 5-7x faster on average.

I suppose I could do some tests taking my script how I had before, and set the Pos to be the Bounds Box lowest point and check from there. Although doing tests before, having the pos inside the center of the object worked fine, but then it would randomly not work othertimes.

1 Reply
(@denist)
Joined: 1 year ago

Posts: 0

snapshortasmesh works fast, but you have to snapshot as mesh object. that’s slow

other solution is to find all objects which bounding box in the ray coordinate system intersects with bounding box of projected node, and snapshot only found objects. that might be faster than shapshot all geometry objects.

Well doing what you said

  local  dir = [0,0,-1] --o.objectTransform.row3*-1
  local thePos = [o.center.x, o.center.y, (nodeLocalBoundingBox o)[1].z]
 		
  local theObj = for n in (intersectRayScene (ray thePos (dir))) where not n[1].isHidden collect n --intersectRayScene (ray o.pos (dir)) -- collecting intersections

This works now in my scene that didn’t work before.

Edit: Yeah, using this method, now it takes around .5 seconds vs. 1-2 seconds

1 Reply
(@denist)
Joined: 1 year ago

Posts: 0

that’s what i talked about… anyway i would try the bbox method.

Page 1 / 2