RayMeshGridIntersect : ReferenceTarget

RayMeshGridIntersect - superclass: ReferenceTarget; super-superclass:MAXWrapper - 1:0 - classID: #(930131240, 656216840)

Provides advanced ray-to-mesh intersection methods using a uniform voxel grid as acceleration method.

Properties

<RayMeshGridIntersect>.nodeList ArrayParameter default: #() -- node array; Node_List

Get/set the array of nodes.

Note: Despite 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.

RayMeshGridIntersect interfaces

Interface: rayMeshGridIntersectOps

Methods

<void>initialize <integer>gridSize

Initializes the voxel grid with the specified grid size.

The grid size value defines the number of voxels along all 3 axes.

The actual size of the voxels depends on the bounding box of the nodes to be processed.

<void>addNode <node>addNode

Adds a node to the node list.

Please see the Note above - only the first object on the list will be used!

<void>buildGrid()

Fills in the voxel grid with data.

<void>free()

Removes all data from the voxel grid.

<integer>intersectBox <point3>min <point3>max

Performs a box intersection using the specified min. and max. points in world space.

<integer>intersectSphere <point3>center <float>radius

Performs a sphere intersection using the specified center and radius.

<integer>intersectRay <point3>p <point3>dir <boolean>doubleSided

Performs a ray intersection using the specified position and direction.

If the doubleSided argument is False, only intersection with faces whose normals point towards the ray will be collected.

When it is True, the faces will be considered double-sided and intersected even when their normals are pointing in the direction of the ray.

The result is 0 if not intersection was detected, or a positive number representing the number of faces that have been intersected.

<integer>intersectSegment <point3>p1<point3>p2 <boolean>doubleSided

Performs a segment intersection using the specified two world positions.

This is similar to intersectRay, but instead of a point and direction, the intersection ray is defined using two absolute positions in space, where p1 is the origin and the direction is from p1 to p2.

If the doubleSided argument is False, only intersection with faces whose normals point towards the ray will be collected.

When it is True, the faces will be considered double-sided and intersected even when their normals are pointing in the direction of the ray.

The result is 0 if no intersection was detected, or a positive number representing the number of faces that have been hit.

<integer>getHitFace <integer>index

Returns the index of the TriMesh face for the indexed hit.

The index can be a positive number between 1 and the number of hits reported by the last intersection method.

<point3>getHitBary <integer>index

Returns the Barycentric Coordinates of the TriMesh face for the indexed hit.

The index can be a positive number between 1 and the number of hits reported by the last intersection method.

<point3>getHitNormal <integer>index

Returns the face normal of the TriMesh face for the indexed hit in world space.

The index can be a positive number between 1 and the number of hits reported by the last intersection method.

<float>getHitDist <integer>index

Returns the distance to the indexed hit.

The index can be a positive number between 1 and the number of hits reported by the last intersection method.

<integer>intersectSegmentDebug <point3>p1 <point3>p2 <boolean>doubleSided <integer>gridID

This method is for debugging purposes only.

<integer>getClosestHit()

Returns the index of the closest hit.

<integer>getFarthestHit()

Returns the index of the farthest hit.

<integer>closestFace <point3>p

Performs intersections from the specified world point with all faces and returns the number of hits as integer.

You can use the getClosestHit() and getFarthestHit() to determine the closest and farthest faces to the specified world point, getHitDist() to determine the distance to every face, and getPerpDist() to determine the perpendicular distance to the point.

<float>getPerpDist <integer>index

Returns the perpendicular distance to the indexed hit.

The index can be a positive number between 1 and the number of hits reported by the last intersection method.

<void>ClearStats()

Clears all statistics.

<void>PrintStats()

Prints current statistics, including number of faces and number of searches performed.

The following example creates a sphere and a geosphere, registers the sphere with the voxel grid and then shoots rays from each vertex of the geosphere and selects the faces of the sphere that these rays have hit.

EXAMPLE

   (
       resetMaxFile #noprompt --reset the scene
       theSphere = Sphere radius:40 segs:50 pos:[100,200,300] --create a sphere
       theGeoSphere = Geosphere radius:100 segs:3 pos:[100,200,300] --create a geosphere
       theFacesArray = #() --init. an array to collect face selection

       rm = RayMeshGridIntersect () --create an instance of the Reference Target
       rm.Initialize 10 --init. the voxel grid size to 10x10x10
       rm.addNode theSphere --add the sphere to the grid
       rm.buildGrid () --build the grid data (collecting faces into the grid voxels)
       theGSMesh = snapshotasmesh theGeoSphere --grab the TriMesh of the Geosphere
       for v = 1 to theGSMesh.numverts do --go through all verts of the Geosphere
       (
           thePos = getVert theGSMesh v --get the position of the vertex
           theNormal = -(getNormal theGSMesh v) --get the normal of the vertex, reverse direction
           theHitsCount = rm.intersectRay thePos theNormal false --intersect the ray with the sphere
           if theHitsCount > 0 then --if have hit anything...
           (
               theIndex = rm.getClosestHit () --get the index of the closest hit by the ray
               theFace = rm.getHitFace theIndex --get the face index corresponding to that indexed hit
               append theFacesArray theFace --add to the face array to select the face...
           )
           else
               format "The Ray % Missed\n" v
       )

       ms = mesh_select() --create a mesh select modifier
       addModifier theSphere ms --add on top of the sphere
       select theSphere --select the sphere
       max modify mode --go to modify panel
       setFaceSelection theSphere 1 theFacesArray --set the selection in the MeshSelect
       subObjectLevel = 3 --go to face selection level
   )