UNPKG

p5.raycaster

Version:

a simple p5js library for semi 3d rendering with ray casting

113 lines (106 loc) 4.26 kB
/** * some helper functions */ class Util { /** * find the intersection point between two line, return null if they don't intersect * * @param {Vector} p0 an object with x, y property denoting a point, can be a p5.Vector object * @param {Vector} p1 an object with x, y property denoting a point, can be a p5.Vector object * @param {Vector} p2 an object with x, y property denoting a point, can be a p5.Vector object * @param {Vector} p3 an object with x, y property denoting a point, can be a p5.Vector object * @param {boolean} segment if true, check only if line segments defined by the point intersect, default is false * @returns the intersection point */ static lineIntersection(p0, p1, p2, p3, segment = false) { let A1 = p1.y - p0.y; let B1 = p0.x - p1.x; let C1 = A1 * p0.x + B1 * p0.y; let A2 = p3.y - p2.y; let B2 = p2.x - p3.x; let C2 = A2 * p2.x + B2 * p2.y; let d = A1 * B2 - A2 * B1; if (d === 0) return null; let x = (B2 * C1 - B1 * C2) / d, y = (A1 * C2 - A2 * C1) / d; if (segment) { let rx = (x - p0.x) / (p1.x - p0.x); let ry = (y - p0.y) / (p1.y - p0.y); if ((rx >= 0 && rx <= 1) || (ry >= 0 && ry <= 1)) { return { x: x, y: y }; } else { return null; } } return { x: x, y: y }; } /** * find the intersection points between a line and a circle, return null if they don't intersect * * @param {Vector} p1 an object with x, y property denoting a point, can be a p5.Vector object * @param {Vector} p2 an object with x, y property denoting a point, can be a p5.Vector object * @param {Vector} center an object with x, y property denoting a point, can be a p5.Vector object * @param {number} r radius of the circle * @param {boolean} internal flag for calling this internally within the library, return only info needed * @returns an array of two points or null */ static lineCircleIntersection(p1, p2, center, r, internal = false) { let a, b, c, bb4ac; let dp = { x: 0, y: 0 } dp.x = p2.x - p1.x; dp.y = p2.y - p1.y; a = dp.x * dp.x + dp.y * dp.y; b = 2 * (dp.x * (p1.x - center.x) + dp.y * (p1.y - center.y)); c = center.x * center.x + center.y * center.y; c += p1.x * p1.x + p1.y * p1.y; c -= 2 * (center.x * p1.x + center.y * p1.y); c -= r * r; bb4ac = b * b - 4 * a * c; if (bb4ac < 0) return null; if (internal) { return { b: (-b - Math.sqrt(bb4ac)) / (2 * a) }; } let mu1 = (-b + sqrt(bb4ac)) / (2 * a); let mu2 = (-b - sqrt(bb4ac)) / (2 * a); return [{ x: p1.x + mu1 * (p2.x - p1.x), y: p1.y + mu1 * (p2.y - p1.y) }, { x: p1.x + mu2 * (p2.x - p1.x), y: p1.y + mu2 * (p2.y - p1.y) }]; } /** * rotate an vector by an angle, return a new object {x, y} * @param {Vector} v * @param {number} ang * @returns new vector */ static rotateVector(v, ang) { return { x: v.x * Math.cos(ang) - v.y * Math.sin(ang), y: v.x * Math.sin(ang) + v.y * Math.cos(ang) } } static combineSort(order, dist, amount) { let gap = amount; let swapped = false; while (gap > 1 || swapped) { gap = Math.floor((gap * 10) / 13); if (gap == 9 || gap == 10) { gap = 11; } if (gap < 1) { gap = 1; } swapped = false; for (let i = 0; i < amount - gap; i++) { let j = i + gap; if (dist[i] < dist[j]) { [dist[i], dist[j]] = [dist[j], dist[i]]; //Swap distances [order[i], order[j]] = [order[j], order[i]]; //Swap sort order swapped = true; } } } } static normalize(v) { let ms = v.x * v.x + v.y * v.y if (ms === 1) return { x: v.x, y: v.y }; return { x: v.x / Math.sqrt(ms), y: v.y / Math.sqrt(ms) }; } } export default Util;