Get an object in Ray

Become a member of the CGSociety

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

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
Old 09 September 2009   #1
Get an object in Ray

Hi

is there any way to get the first object in ray casting path?



here is the code to cast rays as splines:

(
	fn drawRay pointA pointB type:#corner =
	(
		local sp = SplineShape pos:pointA
		addNewSpline sp
		addKnot sp 1 type #line PointA
		addKnot sp 1 type #line PointB
		updateShape sp
	)
	tool trackIntersection
	(
		on mousePoint clickno do
		(
			if clickno == 2 do
			(
				local viewPoint_ray = mapScreentoWorldRay viewPoint
				local p1 = viewPoint_ray.pos --viewport point
				local p2 = 
				(
					local dist = distance worldPoint p1
					viewPoint_ray.dir * dist*2 + viewPoint_ray.pos --scene point
				)
				drawRay p1 p2 --a straight line from the viewport passing through scene
			)
		)
	)
	starttool trackIntersection
)


thanks for any advice....
 
Old 09 September 2009   #2
so , I know is not the best way to do this... but is working now...

To test it put some object in Max scene and run the script:


(
	struct object_data (obj, ray)
	fn getObjIntersection ray =
	(
		--collect all visible objects in scene
		local objs = for o in objects where not o.isHidden collect o
		local od = #()
		local ray_dist	= #()
		--collect objects shoted by ray
		for o in objs do
		(
			local i = intersectRay o ray
			if i!= undefined do 
			(
				od += #(object_data o i)
				ray_dist	+= #(distance ray.pos i.pos)
			)
		)
		if od.count	  == 0
		then return undefined
		else if od.count == 1
		then return od[1] 
		else --return the closest object to ray begin
		(
			copy_ray_dist = #()+ray_dist --4fun
			sort copy_ray_dist
			return od[findItem ray_dist copy_ray_dist[1]]
		)
	)
	tool getObjectFromRay
	(
		on mousePoint clickno do
		(
			if clickno != 1 do
			(
				local viewPoint_ray = mapScreentoWorldRay viewPoint
				local obj_data = getObjIntersection viewPoint_ray
				if obj_data != undefined
				then 
				(
					select obj_data.obj 
					format "picked obj:%\n" obj_data
				)
				else 
				(
					max select none
					format "picked ground:worldPoint\tray:%\n" (ray worldPoint viewPoint_ray.dir)
				)
			)
		)
	)
	starttool getObjectFromRay
)
 
Old 09 September 2009   #3
updated version... now with interactive marker


  
  (
  	struct object_data (obj, ray)
  	fn getObjIntersection ray =
  	(
  		--collect all visible objects in scene
  		local objs = for o in objects where not o.isHidden collect o
  		local od = #()
  		local ray_dist	= #()
  		--collect objects shoted by ray
  		for o in objs do
  		(
  			local i = intersectRay o ray
  			if i!= undefined do 
  			(
  				od += #(object_data o i)
  				ray_dist	+= #(distance ray.pos i.pos)
  			)
  		)
  		if od.count	  == 0
  		then return undefined
  		else if od.count == 1
  		then return od[1] 
  		else --return the closest object to ray begin
  		(
  			copy_ray_dist = #()+ray_dist --4fun
  			sort copy_ray_dist
  			return od[findItem ray_dist copy_ray_dist[1]]
  		)
  	)
  	tool getObjectFromRay
  	(
  		local PaintMarker
  		on start do --create marker
  		(
  			max select none
  			PaintMarker = circle radius:10 pos:[0,0,0] wireColor:(color 80 250 80) displayRenderMesh:true name:"PaintMarker" thickness = 2
  		)
  		on mousemove clickno do
  		(
  			if clickno > 1 then --move marker ower surfaces or grid
  			(
  				local viewPoint_ray = mapScreentoWorldRay viewPoint
  				local obj_data = getObjIntersection viewPoint_ray
  				if obj_data != undefined
  				then 
  				(
  					--select obj_data.obj 
  					PaintMarker.pos = obj_data.ray.pos
  					PaintMarker.dir = obj_data.ray.dir
  					format "picked obj:%\n" obj_data
  				)
  				else 
  				(
  					--max select none
  					PaintMarker.pos = worldPoint
 					PaintMarker.dir = [0,0,-1]
  					format "picked ground:worldPoint\tray:%\n" (ray worldPoint viewPoint_ray.dir)
  				)
  				--#stop
  			)
  		)
  		on stop do
  		(
  			delete PaintMarker
  		)
  	)
  	starttool getObjectFromRay
  )
  

Last edited by MerlinEl : 09 September 2009 at 04:07 PM.
 
Old 09 September 2009   #4
Alternatively, you could use the intersectRayScene function that was introduced in max 2008 (avguard extensions). From the manual:

intersectRayScene <ray>

NEW in 3ds Max 2008: [AVG] Performs intersectRay on all nodes in the scene.

Returns an array of results, one entry per node hit, where each entry is a 2 element array containing the node and the intersectRay result for that node.

(
local r = ray [0,0,0] [1,0,0] --define a ray along X
for i = 0 to 4 do --loop 5 times
(
  box pos:[i * 30, 0, 0] --create a box
)
local hits = intersectRayScene r --intersect with scene
print hits --Misses box 1 because ray originates inside the box
)

#($Box:Box02 @ [30.000000,0.000000,0.000000], (ray [17.5,0,0] [-1,0,0]))
#($Box:Box03 @ [60.000000,0.000000,0.000000], (ray [47.5,0,0] [-1,0,0]))
#($Box:Box04 @ [90.000000,0.000000,0.000000], (ray [77.5,0,0] [-1,0,0]))
#($Box:Box05 @ [120.000000,0.000000,0.000000], (ray [107.5,0,0] [-1,0,0]))
OK

Martijn
 
Old 09 September 2009   #5
Originally Posted by MerlinEl: is there any way to get the first object in ray casting path?


the best way of getting the first object in ray casting path is to use intersectRayScene function. It returns an array of all hit nodes (including hidden) in order of nodes creation. You have sort this array by hit distance and exclude hidden nodes...


iray = ray <pos> <dir>
hit_nodes = for n in (intersectRayScene iray) where not n[1].isHidden collect #(n[1], n[2], distance iray.pos n[2].pos)
fn sortByHitDistance n1 n2 = if n1[3] < n2[3] then -1 else if n1[3] > n2[3] then 1 else 0 
qsort hit_nodes sortByHitDistance
hit_nodes[1] -- is closest
 
Old 09 September 2009   #6
Yes yes... that will be fastest way to do this.
Thank you magicm and you denisT
 
Old 09 September 2009   #7
Thread automatically closed

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.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed 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 08:01 AM.


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