primerib1 Posted March 4 Share Posted March 4 (edited) Given a volume in the shape of an upright prism whose base is a parallelogram that lies flat/parallel to the world XY plane (plane of constant Z) The parallelogram defined by an origin vector, and 2 adjacent vertices (vertex1 and vertex2) all with the same Z as origin, And the prism additionally have a height Then the following function will return TRUE if a 3D coordinate (vector) pos is within the prism: integer InPrism(vector origin, vector vertex1, vector vertex2, float height, vector pos) { float m = pos.z - origin.z; if ((m < 0.0) || (m > height)) return FALSE; float a = vertex1.x - origin.x; float b = vertex2.x - origin.x; float c = pos.x - origin.x; float d = vertex1.y - origin.y; float e = vertex2.y - origin.y; float f = pos.y - origin.y; float divider = (a * e) - (b * d); m = ((c * e) - (b * f)) / divider; if ((m < 0.0) || (m > 1.0)) return FALSE; m = ((a * f) - (c * d)) / divider; if ((m < 0.0) || (m > 1.0)) return FALSE; return TRUE; } What is this useful for? Well, probably can be used in place of a multitude of invisiprims all with their own script all doing their own llVolumeDetect() ... EDIT: HOW IT WORKS First, it finds out if pos is between the lower bound and upper bound of the prism. Then, limiting to the 2D (X, Y) plane, it finds out the 2D vector for each of: O-V1, O-V2, O-pos Then, it orthogonalizes the O-pos vector into multiples of O-V1 and O-V2, let's call this m1 and m2. pos is within the parallelogram if and only if 0 < m1 < 1.0 and 0 < m2 < 1.0 The case where pos is on the edge of the parallelogram is kinda finicky to match (floating point accuracy limit), so the test is for inequality only. Edited March 4 by primerib1 1 Link to comment Share on other sites More sharing options...
primerib1 Posted March 4 Author Share Posted March 4 (edited) Here's an example how I used this to detect people inside of designated stall areas in my stable: list STALLS = [ <13.6, 122.8, 115.0>, <13.6, 120.0, 0.0>, <37.3, 122.8, 0.0>, 50, <13.7, 128.7, 115.0>, <13.7, 131.5, 0.0>, <28.5, 128.7, 0.0>, 50 ]; integer InStalls(vector pos) { vector origin; vector vertex1; vector vertex2; float height; integer i = -1; do { origin = llList2Vector(STALLS, ++i); vertex1 = llList2Vector(STALLS, ++i); vertex2 = llList2Vector(STALLS, ++i); height = llList2Float(STALLS, ++i); if (InPrism(origin, vertex1, vertex2, height, pos)) return TRUE; } while (i < 7); return FALSE; } 1 script, zero invisiprims, to watch over 2 disconnected areas of dissimilar sizes. Edited March 4 by primerib1 1 Link to comment Share on other sites More sharing options...
primerib1 Posted March 4 Author Share Posted March 4 The InPrism() function can probably be optimized further by pre-calculating the a, b, d, e, and divider values. But I'll leave that as a homework to y'all scripters 😉 Link to comment Share on other sites More sharing options...
primerib1 Posted March 23 Author Share Posted March 23 On 3/4/2024 at 7:07 PM, primerib1 said: Here's an example how I used this to detect people inside of designated stall areas in my stable: list STALLS = [ <13.6, 122.8, 115.0>, <13.6, 120.0, 0.0>, <37.3, 122.8, 0.0>, 50, <13.7, 128.7, 115.0>, <13.7, 131.5, 0.0>, <28.5, 128.7, 0.0>, 50 ]; integer InStalls(vector pos) { vector origin; vector vertex1; vector vertex2; float height; integer i = -1; do { origin = llList2Vector(STALLS, ++i); vertex1 = llList2Vector(STALLS, ++i); vertex2 = llList2Vector(STALLS, ++i); height = llList2Float(STALLS, ++i); if (InPrism(origin, vertex1, vertex2, height, pos)) return TRUE; } while (i < 7); return FALSE; } 1 script, zero invisiprims, to watch over 2 disconnected areas of dissimilar sizes. Do note that for the "vertex1" and "vertex2" vectors, I purposefully set their Z value to 0.0, because the Z value for the vertices are ignored anyways. Link to comment Share on other sites More sharing options...
primerib1 Posted March 23 Author Share Posted March 23 On 3/4/2024 at 7:03 PM, primerib1 said: EDIT: HOW IT WORKS First, it finds out if pos is between the lower bound and upper bound of the prism. Then, limiting to the 2D (X, Y) plane, it finds out the 2D vector for each of: O-V1, O-V2, O-pos Then, it orthogonalizes the O-pos vector into multiples of O-V1 and O-V2, let's call this m1 and m2. pos is within the parallelogram if and only if 0 < m1 < 1.0 and 0 < m2 < 1.0 The case where pos is on the edge of the parallelogram is kinda finicky to match (floating point accuracy limit), so the test is for inequality only. In theory, steps 2 and on can also be used to orthogonalize the Origin-Pos vector in 3D space, allowing detection for a non-upright prism volume. But the maths become so complex it gave me a headache ... plus Performance tanks due to how much float calculation is happening Debugging is a nightmare There is not much need to detect a pos in a non-upright-prism volume So I optimized the scenario and the code for an upright prism volume instead. Which covers like, probably 95% of use cases... Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now