UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

135 lines (110 loc) 4.79 kB
import { assert } from "../../../../../core/assert.js"; import { bvh32_query_user_data_ray } from "../../../../../core/bvh2/binary/2/bvh32_query_user_data_ray.js"; import { typed_array_value_denormalize } from "../../../../../core/collection/array/typed/typed_array_value_denormalize.js"; import { SurfacePoint3 } from "../../../../../core/geom/3d/SurfacePoint3.js"; import { computeTriangleRayIntersection } from "../../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js"; const scratch_array = [] const scratch_hit = new SurfacePoint3() /** * * @param {SurfacePoint3} result * @param {BinaryUint32BVH} bvh * @param {number[]|ArrayLike<number>} vertices * @param {number} vertex_offset Unless you're using an interleaved buffer of some kind, this will be 0 * @param {number} vertex_stride Unless you're using an interleaved buffer, this should be 3 * @param {boolean} vertex_data_normalized do we need to denormalize vertex data? * @param {number[]|ArrayLike<number>|undefined} indices if this is set to undefined - implicit indexing will be used * @param {number} origin_x * @param {number} origin_y * @param {number} origin_z * @param {number} direction_x * @param {number} direction_y * @param {number} direction_z * @param {number} max_distance How far can the ray travel from origin? tMax * @returns {boolean} */ export function bvh32_geometry_raycast( result, bvh, vertices, vertex_offset, vertex_stride, vertex_data_normalized, indices, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, max_distance ) { assert.isBoolean(vertex_data_normalized, 'vertex_data_normalized'); assert.isNumber(max_distance, 'max_distance'); let hit_found = false; const hit_count = bvh32_query_user_data_ray( scratch_array, 0, bvh, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, max_distance, ); let best_distance_sqr = max_distance * max_distance; let a, b, c; for (let i = 0; i < hit_count; i++) { const triangle_index = scratch_array[i]; const index3 = triangle_index * 3; if (indices !== undefined) { assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?'); a = indices[index3]; b = indices[index3 + 1]; c = indices[index3 + 2]; } else { // implicit indices a = index3; b = index3 + 1; c = index3 + 2; } const a_address = a * vertex_stride + vertex_offset; const b_address = b * vertex_stride + vertex_offset; const c_address = c * vertex_stride + vertex_offset; assert.lessThan(a_address + 2, vertices.length, 'a-vertex overflow'); assert.lessThan(b_address + 2, vertices.length, 'b-vertex overflow'); assert.lessThan(c_address + 2, vertices.length, 'c-vertex overflow'); let ax = vertices[a_address]; let ay = vertices[a_address + 1]; let az = vertices[a_address + 2]; let bx = vertices[b_address]; let by = vertices[b_address + 1]; let bz = vertices[b_address + 2]; let cx = vertices[c_address]; let cy = vertices[c_address + 1]; let cz = vertices[c_address + 2]; // denormalize if necessary if (vertex_data_normalized) { ax = typed_array_value_denormalize(ax, vertices); ay = typed_array_value_denormalize(ay, vertices); az = typed_array_value_denormalize(az, vertices); bx = typed_array_value_denormalize(bx, vertices); by = typed_array_value_denormalize(by, vertices); bz = typed_array_value_denormalize(bz, vertices); cx = typed_array_value_denormalize(cx, vertices); cy = typed_array_value_denormalize(cy, vertices); cz = typed_array_value_denormalize(cz, vertices); } const triangle_hit_found = computeTriangleRayIntersection( scratch_hit, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, bx, by, bz, cx, cy, cz ) if (!triangle_hit_found) { continue; } hit_found = true; const distance_sqr = scratch_hit.position._distanceSqrTo(origin_x, origin_y, origin_z); if (distance_sqr < best_distance_sqr) { best_distance_sqr = distance_sqr; result.copy(scratch_hit); } } return hit_found; }