[Closed] RayMeshGridIntersect
I’m trying to sort out what everything does in this but the help isn’t a lot of help. I’m having issues with intersectRay some time and it is missing, I gather from the help that RayMeshGridIntersect is better. Am I correct first of all.
Also I can get it to work with one object without a problem. How ever I can’t get it to work with multiple. Using addNode it sounds as though I can add multiple nodes but only the first one that I can is being detected. Also does any one know what .nodeList is for? I can set an array of nodes to it but I don’t see what it is doing at all.
Here is a little test:
$point01 is where I’m firing the ray from.
$sphere01 is the object that I’m setting the position to see where I hit.
$plane01 and $sphere02 are objects I’m trying to hit.
rm = RayMeshGridIntersect() --create an instance of the Reference Target
rm.Initialize 10 --init. the voxel grid size to 10x10x10
rm.addNode $plane01 --add the sphere to the grid
rm.addNode $Sphere02--add the sphere to the grid
rm.nodeList=#($plane01,$Sphere02)
rm.buildGrid()
theHitsCount=rm.intersectRay $point01.pos $point01.transform.row3 false
dist=rm.getHitDist (rm.getClosestHit())
$Sphere01.pos=$point01.pos+($point01.transform.row3*dist)
Any insight would be great.
I asked the very same thing long ago, and people seemed to conclude that it’s only possible to use one node at a time. Nodelist doesn’t seem to work either, it’s not updated when node is added, and when you set the array manually it doesn’t seem to have any effect on anything. Combining the meshes seems to be the only option.
Still the system is vastly better than intersectray in many cases. I’ve made a set of functions where one just initializes and others cast rays exactly like intersectray would. It runs a lot faster and hits backfacing.
RayMeshGridIntersect is faster and gives you a few more options, but I don’t think the accuracy differs much from the legacy intersectRay function.
Here’s a quick test with the available methods (10000 iterations):
MeshProjIntersect : 1076 milliseconds.
RayMeshGridIntersect : 681 milliseconds.
intersectRay : 1979 milliseconds.
As for the multiple nodes issue with RayMeshGridIntersect, I never got that to work either. The weird thing is, MeshProjIntersect has a .GetHitNode function while it only works on a single node (.SetNode method) whereas the RayMeshGridIntersect interface does not have a .GetHitNode function while it is supposed to take multiple objects…
Martijn
Interesting that you get those results as mine were not the same. I recieved about the same amount of time for the hits. Actualy I think that rayMeshGridIntersect was a bit slower.
I don’t really have experience of rays falsely missing in either method, other than intersectray’s inability to hit backfacing. I don’t think there is much difference if the traced mesh is simple, but raymeshgridintersect definitely gains speed as mesh density increases. Think I’ve tested much greater differences than magicm’s example. Gridsize has some effect on it too. When you trace deforming/moving meshes there’s not that big difference because the grid initializing takes quite a bit of time when you have to do it often.
IN playing with it I think that I have a good solution. I will just how much faster the method is.
I used RayMeshGridIntersect on an MXS project that I stopped developing in 2006, and I was using 3ds Max 6 for development. Its been a while, but I do remember some points on using it.
-
Here is a post discussing a MeshProjIntersect/RayMeshGridIntersect comparison.
-
I remember getting intersections from RayMeshGridIntersect() about 4 times as fast as intersectRayEx(). I was working with single-object terrain meshes of 30k-60k faces. Here is some related info.
- I do remember having rays occasionally go right through a mesh without detecting any hits(maybe 1 in every few thousand rays). I definitely encountered this with intersectRayEx, but I think the same behavior occured with RayMeshGridIntersect. I concluded this was probably an unavoidable rounding error allowing the ray to slip in between faces, but I can’t be sure. I do remember how I dealt with it, though…
I was sending rays vertically down onto a terrain mesh in a regular grid pattern, so I had my process send 1 ray followed (if needed) by 4 successive rays tightly surrounding it. As soon as a ray hit, the result was used and no more rays were sent. Thus, all 5 rays would be sent ONLY if the first 4 all missed, and a miss was only reported/concluded if the 5th ray didn’t hit. This eliminated the rounding error misses while not skewing my results in any serious way.
- As far as using multiple nodes, I don’t know why it doesn’t work but it would not surprise me if it was never functional. As described in the 3rd post of the comparison thread mentioned above, the original implementation of RayMeshGridIntersect had several bugs and busted methods. Bobo logged the bugs he found, but maybe this one got through?
Regardless of the cause, you might consider whether you’d reallly want to have the same RayMeshGridIntersect instance handling more than one mesh…I think its possible that it might run slower. (Personally, I’d probably initialize and maintain a separate grid for each mesh while using both simultaneously.) I could be wrong about this, but here is why I’m thinking it might matter: From what I understand, the voxel-based acceleration grid subdivides the node’s object bounding box space into a set number of volumes (voxels) along each axis. When initializing with a gridsize of 10, for example, the grid is broken into 1000 (10^3) voxels.
From the overall face list for the node mesh, a face list for each voxel is created that includes every face that exists (entirely or partially) within that voxel. Faces spanning voxels occur in multiple voxel lists. When a ray is tested against the acceleration grid, the intersected voxels are determined first and then ray testing is done on every face in the lists of every intersected voxel. (In contrast, the intersectRay/intersectRayEx methods test a ray against every face in the mesh. This is where the actual acceleration comes from…the testing is the same, but restricted to a much smaller face count.)
In the case of multiple nodes using the same RayMeshGridIntersect instance, I’m not sure if it would create a common, world-aligned grid encompassing every assigned node, or whether it would give each node its own grid but simply with the same gridSize setting (the docs are not specific about this). Obviously, the former case could be very slow/inefficient depending on the location and proximity of the various mesh nodes. In the latter case, the grids would be custom fit…but not custom subdivided.
In other words, meshes of drastically different sizes or face counts would not end up with ideal gridSizes. If separate acceleration grids were created for each mesh and used simultaneously, you could actually customize every gridSize to its mesh according to its properties. (See the second thread mentioned above regarding optimal gridSize settings.)
The following function was used by my script to calculate optimal gridSize settings per mesh:
fn getFastGridSize = (
local calcsize = (((TheMesh.numfaces / 250.0) + 2) as integer)
if calcsize > 500 then 500 else calcsize
)
That is some good info. I suspected that it worked this and and that is why my tests were faster with intersectRay, I had only a standard plane so it had very few faces. Once there are more faces it will go much higher.
Unfortunitly you have to pass a node to rayGridMeshIntersect and not a triMesh, now I can build node from the triMesh but I’m not sure that I want to do that.
If I have several nodes I will need to do the testing of which hit is closest and I would think that would get slower. So what do you think, build a mesh out of all the colision objects and use that or loop through a list of colision objects and do a comparison?
John I just read over the posts that you pointed me to. Great info and thanks for sharing it.
Something I just tried worked that looks like it is a possible solution to dealing with multiple objects. SnapShatAsMesh all the nodes and attach them together. Create a mesh using mesh mesh:$theAttachedMeshObjects, create and build the rayMeshGrid and then delete the $theAttachedMeshObjects. It all still works. I would think this is faster when doing the hits as it only need to do one voxel pass and then one pass over the faces. I guess I should set up a test of this but it might work well.