I’ve created a script to switch lights on and off depending on their position inside or outside of a volume. This volume can be animated if needed. The clever part is taken from the cgtalk forums. The calculation to determine if an object is within a specific volume is done by casting rays in an arbitrary direction.
This is the pseudocode by Matan Halberstadt
1. add a normal modifier to the volume object, with the flip option turned ON 2. loop through all verts 2.1. p = position of current vert 2.2. fire a ray from p in an arbitrary direction like [0,0,1] at the volume object 2.3. if the ray missed then you are out side the volume else 2.3.1 turn the normal modifier on the volume object OFF 2.3.2 fire another ray from p in the same direction at the volume object 2.3.3 if the 2nd ray missed or distance from p to hit1 < distance from p to hit2 then you are inside the volume else you are outside the volume 2.3.4 turn the normal modifier on the volume object ON
I’ve taken this idea and incorporated it in a script to manipulate lights. The volume-detection however can be used to do many other things. Here are my examples.
|An array of lights|
|The lights light a displaced plane|
|A volume encloses some of the lights|
|Only the lights within the volume are switched on|
Insanto posted an alternative method on scriptspot. I’ve compared both methods of determining if a point is within a specific volume for speed. I’ve had to adjust my method, but it came out a bit faster. I’ve used the following maxscene and testscript to compare the speed. The scene is in max 2010. Download them here: CompareSpeed, or as fbx2009 format: TestVol_fbx2009.
fn isPointInVol obj pos = --checks if supplied position is inside supplied mesh object( if superclassOf obj == geometryClass do ( local tMesh = obj.mesh; local nVerts=tMesh.numverts; local isInVol = true for v = 1 to nVerts while isInVol do ( if asin (dot (getNormal tMesh v) (normalize(((getVert tMesh v)*obj.transform) - pos))) <= 0.0 do isInVol = false ) tMesh = nVerts = vPos = undefined return isInVol ) )--END isPointInVol FN
this is the method by Insanto the test results Average of ten iterations running on a bunch of points and a single volume 10 points check insanto: 20ms mine: 28ms 100 point check insanto: 199ms mine: 144ms 500 point check insanto: 934ms mine: 558ms