[Closed] Testing if Objects are in Camera View
As the title says: I need to test if an object is inside the camera view or not.
Since I don’t have Max here where I am atm, I still couldn’t test this, but in advance, if anyone could offer support in this matter: I imagined creating a pyramid with the camera’s view size and using vol.select… Will this give me which objects are in the camera’s view range?
If not, any suggestions?
Thank you
Depending on the precision you want, you could either test the 6 corners of the bounding box of each object against the camera or each vertex. (the second method would be slower, although you could test every Nth vertex and hope you will catch any special parts of the object). I would go with the bounding box approach.
Then you take the code from the “How To … Develop a Vertex Renderer” in the MAXScript Reference and extract the part that converts world space coordinates into screen coordinates. Then you pass the 6 bounding box corners to that function and check if any of the points is inside the screen – in that case you are potentially seeing the object. If all points project outside of the screen coordinates, the object’s bbox does not intersect the camera cone.
You could of course do a two-stage test – first for bbox and if any of the box corners is in view, run a per-vertex test to make sure what exactly is visible.
Thanks for your reply, Bobo.
I already am going through every vertex of every object in selection for other reasons, so the complexity won’t change if I do a vertex check. I have each vertex position (3point), with this information, I want to make a function, for example: isSeenByCam 3point cam
This function would return true if seen and false if not.
Is this possible? To check per position (even if I have to create a small sphere, for example, and move it to the 3point position and delete it at the end of all verifications)
Remembering: processing time, luckily, isn’t something I need to worry about for this script…
Sorry about this, I did search through the forum, but haven’t found anything that gives me this clear hint… any insight is appreciated here.
Thanks in advance
Ah, about the two-stage test…
That is a great idea…
I’m gonna try it out, but I’m still a beginner programmer and even more beginner MaxScripter…
As I mentioned already, the code is in the MAXScript Reference, topic “How To… Develop a Vertex Renderer”.
I will strip the function from there and post the code in a minute…
fn getVertsInViewport theObject =
(
local theVerts = #() --return array
local theMesh = snapshotasmesh theObject --grab the mesh from top of the stack
local theCount = theMesh.numverts --get the number of vertices
local theTM = viewport.getTM() --get the current view's transformation
local screen_width = renderWidth --get the current render height
local screen_height = renderHeight --get the current render width
for v = 1 to theCount do --loop through all vertices
(
local thePos = (getVert theMesh v) * theTM --transform vertex in view space
--get the world location of the upper left corner of the camera view at the depth of the vertex
local screen_origin = mapScreenToView [0,0] (thePos.z) [screen_width,screen_height]
--get the bottom right corner at the vertex depth
local end_screen = mapScreenToView [screen_width,screen_height] (thePos.z) [screen_width,screen_height]
--calculate the world size based on the two corners
local world_size = screen_origin-end_screen
--calculate the X and Y aspect factors
local x_aspect = screen_width/(abs world_size.x)
local y_aspect = screen_height/(abs world_size.y)
--calculate the screen coordinates using all the above data:
local screen_coords = point2 (x_aspect*(thePos.x-screen_origin.x)) (-(y_aspect*(thePos.y-screen_origin.y)))
--if the vertex is outside of the screen (negative or higher than the render size), collect it
if screen_coords.x <= 0 or screen_coords.y <= 0 or screen_coords.x > screen_width or screen_coords.y > screen_height then
append theVerts v
)--end v loop
delete theMesh --release the memory used by the TriMesh
theVerts --return the collected vertices
)--end fn
--PROOF:
theMS = Mesh_Select() --create a mesh select modifier
addModifier $Teapot01 theMS --add the an existing teapot
theResult = getVertsInViewport $Teapot01 --get all invisible vertices of the teapot
setVertSelection $Teapot01 theMS theResult --select them in the mesh select mod
max modify mode --switch to modify panel
select $Teapot01 --select the teapot
subobjectlevel = 1 --go to vertex level to show the selection
--INSTEAD OF SELECTING, YOU CAN JUST CALL THE FUNCTION AND IF THE RESTURN ARRAY
--IS EMPTY, THE OBJECT IS COMPLETELY IN VIEW.
Tested with 64 segs. Teapot with 131,330 vertices – the function call takes 2.4 seconds on my machine.
Thanks for your reply, Bobo…
But I had already finished the script yesterday, just didn’t have time to advise…
I used some of that code…
As I said, processing time isn’t a worry, the processer I have is very powerful…
I tested my script (n³) (per anim time, per object, per vertex) on a scene with many elements and 900 frames… It took about 0.8 seconds per frame…
I disabled scene redraw to accelerate the process.
If anyone would like help in this matter, feel free to contact me
Bobo, another question… the snapshotAsMesh gives me error when I have a Group in selection (I made my script by all objects in selection)… Can I select all objects in the Group and unselect the Group… (via script)?
Thanks once again
I made something like that some weeks ago using Frustum Culling (a common method used in game programming with opengl and directx), but the Bobo’s solution is interesting and easier to implement…
I can send you the code if you want.
Well… sure… I think Bobo’s solution is more intuitive… But I’d appreciate you sending your solution, maybe it’s more efficient… If you want the one I implemented, I’ll send it too =)
Does anyone know how to solve the problem with the Groups that I mentioned before?
A group is a custom hierarchy with a Dummy Helper as the parent.
So when sending objects for checking, you should filter against non-geometry objects and target objects, like
theSelection = for o in selection where superclassof o == GeometryClass and classof o != TargetObject collect o