Challenge: Object under cursor

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

REPLY TO THREAD
 
Thread Tools Search this Thread Display Modes
  04 April 2014
I'm having issues with seemingly any kind of ray hit under max 2009. I've tested 2014 without issues, and do not know about any versions in between the two.

Example code:

(
	fn G3P_getObjUnderCursorE =
	(
		local oList = #()
		for o in Geometry do
			if (intersectRay o (mapScreenToWorldRay mouse.pos)) != undefined then
				append oList o.name
		format "%\n" oList
	)
	G3P_getObjUnderCursorE()
)



Test scene below(something like a production mesh, as I never ran into this issue with standard "programmer's test scenes of boxes and teapots")
www.per128.com/pub/crap/per128_JigSawTest.max

Results:
As I keep evaluating the above code while moving the mouse pointer over the scene (even holding down CTRL+E to trigger it repeatedly), much of the time I'll get good results. Sometimes it seems impossible to get bad results. Then I rotate the viewport slightly, or make a selection change, or interact with the app in some way, and suddenly it seems impossible to get a good result. It will return hits on objects which are nowhere near the mouse pointer.

I've used ray hit methods for years in 2009 without much of a problem, but these were scripts where the function was triggered so rarely that on the occasions it didn't work, the user would just rotate the view and try again and not think much of it. When the script relies on continuously getting accurate results several times a second, these issues become much more significant.

I'm trying to see whether this can be fixed in the SDK, by comparing 2009 and 2014 SDKs, but I have very limited experience with the SDK, so I might be looking at a solution without realizing it.
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
i recommend you to check this thread http://forums.cgsociety.org/showthr...shGridIntersect
 
  04 April 2014
Thanks a lot, DenisT.
RayMeshGridIntersect seems to return 100% dependable results.
It's terribly slow, however.

I'm including my code below, for anyone else who has similar issues.

Efforts have been made to speed things up. intersectRayScene is used to get a list of initial nodes (although results are broken, the correct node is always included among the others). Then I check rayMeshGridIntersect against the nodes that result from that. Finally I sort and get the closest node.

There's a millisecond display in there to show performance. It's spending more than 200ms on this end, but I don't see what can be done about it, except:

There is one more optimization I should try... to sort by distance based on the initial intersectRayScene result. This would assume that the function always returns the correct position result for the nodes that are genuinely hit. This would typically reduce the number of nodes that need to be processed by rayMeshGridIntersect, since I can walk through the quicksorted result and use the first node encountered by rayMeshGridIntersect as my final result, instead of testing every single result of intersectRayScene.



(
	fn theRayMeshGridIntersect pRay pO =
	(
		local myRMGI = rayMeshGridIntersect()
		myRMGI.initialize 1							-- increasing this just slows things down
		myRMGI.addnode pO							-- have found no way of dealing with multiple nodes
		myRMGI.buildgrid()
		myRMGI.intersectray pRay.pos pRay.dir true	-- bool = double sided
		local hitIndex = myRMGI.getclosesthit()
		local hitDist = myRMGI.getHitDist hitIndex	-- returns -1 if invalid
		myRMGI.free()
		hitDist
	)
	fn theGetObjUnderCursorG =
	(
		local t = timeStamp()
		local ray = mapScreenToWorldRay mouse.pos	--[1055,500]
		local os = for o in (intersectRayScene ray) where not o[1].isHidden and not o[1].isFrozen collect o[1]
		local hits = for o in os where (hitDist = theRayMeshGridIntersect ray o) != -1.0 collect #(o, hitDist)
		fn sortDistances n1 n2 = if n1[2] < n2[2] then -1 else if n1[2] > n2[2] then 1 else 0
		qsort hits sortDistances					-- graceful when hits is empty
		for hit in hits do
			format "% (%) \n" hit[1].name hit[2]
		format "%ms\n" (timeStamp() - t)
	)
	theGetObjUnderCursorG()
)
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
first of all the mxs help doesn't say true about
Properties

<RayMeshGridIntersect>.nodeList ArrayParameter default: #() -- node array; Node_List
Get/set the array of nodes.

NoteDespite the implementation as an array parameter, the RayMeshGridIntersect does NOT actually operate on all objects in the list, but only on the FIRST object in the list. If the intersection against multiple objects is required, a separate RayMeshGridIntersect instance should be created for each one and the intersections have to be processed one after the other within a MAXScript loop.

this slows everything down.
 (
	delete objects
	for k=1 to 1000 do geosphere pos:(random -[100,100,100] [100,100,100]) wirecolor:gray
	completeredraw()
)

(
	local rm
	fn sortByDistance n1 n2 pos:[0,0,0] =
	(
		local d1 = distance n1[2].pos pos
		local d2 = distance n2[2].pos pos
		if d1 > d2 then 1 else if d1 < d2 then -1 else 0
	)
	fn pickingFace msg ir obj faceNum shift ctrl alt =
	(
		local node, face
		case msg of
		(
			--#mousePoint:
			#freeMove:
			(
				wray = mapScreenToWorldRay mouse.pos
				inodes = intersectRayScene wray
				inodes = for obj in inodes where not obj[1].ishiddenInVpt collect obj
				if inodes.count > 0 do
				(
					qsort inodes sortByDistance pos:wray.pos
					node = inodes[1][1]
					rm.free()
					rm.Initialize 10
					rm.addNode node
					rm.buildGrid()
					local hits = rm.intersectRay wray.pos wray.dir off
					
					faces = for i=1 to hits collect rm.getHitFace i
					if (i = rm.getClosestHit()) != 0 do face = faces[i]
					objects.wirecolor = gray
					node.wirecolor = orange
					--format "stack:% node:% face:%\n" inodes.count node.name face
				)
			)
		)
		if msg == #mouseAbort then #abort else #continue
	)
	
	rm = RayMeshGridIntersect()
	with undo off mouseTrack trackCallback:pickingFace
	rm.free()
	gc light:on
)
 
  04 April 2014
mousetrack ? I suggested mousetrack and got the following response !?

Quote: Mousetrack doesn't play well with epoly. I can't comment on the two others as you don't mention them by name.
 
  04 April 2014
Originally Posted by Klvnk: mousetrack ? I suggested mousetrack and got the following response !?

i think he meant that built-in mousetrack intersection feature doesn't work with anything else than editable mesh
 
  04 April 2014
Klvnk: Yes, DenisT only uses mousetrack for demonstration purposes, not for its intersection functionality.

With the optimizations I mentioned above, plus hints from DenisT, speed has improved somewhat.

However, with a epoly modifier like Meshsmooth, polyop.getHiddenFaces returns nothing. This means the artist still isn't getting expected results.

With the emesh modifier Turbosmooth, meshop.getHiddenFaces works just fine.


Has anyone faced this issue and come across a solution which won't kill what little is left of performance? Ultimately the goal is to get the faceId of the polygon under the mouse pointer.
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
Originally Posted by Per128: Has anyone faced this issue and come across a solution which won't kill what little is left of performance? Ultimately the goal is to get the faceId of the polygon under the mouse pointer.

you can see the #mousePoint commented in my code. this piece of code was used in one of my tools designed exactly for picking a face id from screen.
 
  04 April 2014
Originally Posted by denisT: you can see the #mousePoint commented in my code. this piece of code was used in one of my tools designed exactly for picking a face id from screen.


The difficulty lies in filtering out hidden faces, though, with polyop.getHiddenFaces seemingly not working for anything other than the base object.
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
Just a note before I proceed down this path:

I've been avoiding mesh snapshot for performance reasons, but this is all so slow now that it seems that I might as well use snapshop and emesh functions. Checking this out currently.
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
Originally Posted by Per128: Just a note before I proceed down this path:

I've been avoiding mesh snapshot for performance reasons, but this is all so slow now that it seems that I might as well use snapshop and emesh functions. Checking this out currently.

what do you really want? pick a screen or monitor?
 
  04 April 2014
Originally Posted by Per128: The difficulty lies in filtering out hidden faces, though, with polyop.getHiddenFaces seemingly not working for anything other than the base object.

BTW... do you see a big difference of your and my code performance?
 
  04 April 2014
Originally Posted by denisT: what do you really want? pick a screen or monitor?

There's a triggered event (can come at any time and frequency, but will wait until the last op is done + a time delay) which tries to read the matId of whatever the user is pointing at when it happens. This involves ignoring hidden geo.


Originally Posted by denisT: BTW... do you see a big difference of your and my code performance?


We do some different stuff logics-wise, but with very similar performance (end of post figures: my performance, yours, dot)

What I'm looking at doing now with regards to hidden faces is to check whether the baseobject has them, and then assume (not cool to assume, but it's the best solution I've found so far) that the end result of the stack has hidden faces as well, make a snapshot of that mesh, use reliable emesh functions on the snapshot, ignore real hidden faces at the top level, delete the snapshot. This is terribly ugly... Ought to be able to make a robust "get whatever the mouse is hovering over" function without all this messiness..


309ms
310ms
"."
308ms
309ms
"."
303ms
309ms
"."
306ms
342ms
"."
305ms
303ms
"."
302ms
355ms
__________________
http://www.per128.com - freelance 3d artist
 
  04 April 2014
well. i see that you're missing the point. try to understand what i'm doing in my code and why any snapmest is not critical.
 
  04 April 2014
Originally Posted by denisT: well. i see that you're missing the point. try to understand what i'm doing in my code and why any snapmest is not critical.


It seems we have nearly identical RayMeshGridIntersect code, and nearly identical performance as well. I appreciate that you want me to figure this out, but as far as I can tell we're doing the same stuff - how about a hint?

I didn't get the thing about "screen or monitor".
__________________
http://www.per128.com - freelance 3d artist
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 09:53 AM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.