--- id: wiki-2026-0508-raycasting title: Raycasting category: 10_Wiki/Topics status: verified canonical_id: self aliases: [ray casting, ray-object intersection, picking, ray-sphere, ray-triangle] duplicate_of: none source_trust_level: A confidence_score: 0.95 verification_status: applied tags: [graphics, geometry, ray-tracing, picking, collision] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript/GLSL framework: Three.js, WebGPU, three-mesh-bvh --- # Raycasting ## 매 한 줄 > **"매 ray 와 매 geometry 의 intersection test"**. 매 1968 Arthur Appel 의 매 first hidden surface paper 매 origin, 매 1992 Wolfenstein 3D 의 매 game engine signature. 매 2026 의 매 universal primitive: mouse picking, hit-test, AR placement, lighting, AI vision-cone, BIM section. 매 Raycasting ≠ Ray Tracing — 매 single ray (no recursion) vs 매 recursive light path. ## 매 핵심 ### 매 raycasting vs raytracing | | Raycasting | Ray Tracing | |---|---|---| | Recursion | 매 single hit | 매 reflection / refraction recursive | | Cost | 매 O(log N) per ray (BVH) | 매 50-1000x heavier | | Use | Picking, collision | Photorealistic render | ### 매 Ray = origin + t·direction - t > 0: 매 forward. - nearest hit: 매 minimum t > 0. - ray vs primitive: 매 sphere / plane / triangle / AABB / OBB. ### 매 acceleration structure - BVH (Bounding Volume Hierarchy): 매 dominant 매 2026. - KD-tree: 매 static scene 매 slightly faster build. - Octree: 매 voxel world. - Spatial hash: 매 dynamic scene. ### 매 응용 1. Mouse picking (Three.js Raycaster). 2. AR object placement (hit-test with depth). 3. AI line-of-sight / vision cone. 4. Bullet physics (sweep test). 5. Audio occlusion (raycast for muffle). 6. BIM 의 section plane / clipper. ## 💻 패턴 ### 1. Three.js mouse picking ```ts import * as THREE from 'three'; const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); window.addEventListener('pointerdown', (e) => { mouse.x = (e.clientX / innerWidth) * 2 - 1; mouse.y = -(e.clientY / innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const hits = raycaster.intersectObjects(scene.children, true); if (hits.length) console.log('Hit:', hits[0].object.name, hits[0].point); }); ``` ### 2. Ray-sphere intersection (analytic) ```ts function raySphere(ro: V3, rd: V3, center: V3, r: number): number { const oc = sub(ro, center); const b = dot(oc, rd); const c = dot(oc, oc) - r * r; const h = b * b - c; if (h < 0) return -1; const t = -b - Math.sqrt(h); return t >= 0 ? t : -1; } ``` ### 3. Ray-triangle (Möller-Trumbore) ```ts function rayTriangle(ro: V3, rd: V3, a: V3, b: V3, c: V3): number { const e1 = sub(b, a), e2 = sub(c, a); const p = cross(rd, e2); const det = dot(e1, p); if (Math.abs(det) < 1e-8) return -1; const inv = 1 / det; const tv = sub(ro, a); const u = dot(tv, p) * inv; if (u < 0 || u > 1) return -1; const q = cross(tv, e1); const v = dot(rd, q) * inv; if (v < 0 || u + v > 1) return -1; return dot(e2, q) * inv; } ``` ### 4. BVH-accelerated picking (three-mesh-bvh) ```ts import { computeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh'; THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree; THREE.Mesh.prototype.raycast = acceleratedRaycast; mesh.geometry.computeBoundsTree(); // 매 once // 매 매 raycast 100x+ faster ``` ### 5. AR hit-test (WebXR) ```ts const session = await navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['hit-test'] }); const refSpace = await session.requestReferenceSpace('viewer'); const hitSource = await session.requestHitTestSource({ space: refSpace }); session.requestAnimationFrame(function frame(t, frame) { const results = frame.getHitTestResults(hitSource); if (results.length) { const pose = results[0].getPose(refSpace); placeReticleAt(pose.transform.matrix); } session.requestAnimationFrame(frame); }); ``` ### 6. Vision cone (AI agent) ```ts function canSee(agent: Agent, target: V3, world: BVH): boolean { const dir = normalize(sub(target, agent.pos)); const angle = Math.acos(dot(dir, agent.forward)); if (angle > agent.fov / 2) return false; const dist = length(sub(target, agent.pos)); if (dist > agent.sightRange) return false; const hit = world.raycastFirst(agent.pos, dir); return !hit || hit.t >= dist - 0.01; } ``` ### 7. WebGPU compute-shader raycast ```wgsl @compute @workgroup_size(64) fn cs_raycast(@builtin(global_invocation_id) id: vec3u) { let ray = rays[id.x]; var t_min = 1e30; var hit_idx = -1; for (var i = 0u; i < tri_count; i++) { let t = ray_triangle(ray, tris[i]); if (t > 0.0 && t < t_min) { t_min = t; hit_idx = i32(i); } } results[id.x] = Hit(t_min, hit_idx); } ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | < 1k triangles | Naive Three.js raycaster 충분 | | 1k-100k triangles | three-mesh-bvh (BVH on CPU) | | 100k-10M, dynamic | refit BVH per frame + worker | | 10M+ static | WebGPU compute + GPU BVH | | Voxel world (Minecraft-ish) | DDA / Amanatides-Woo (매 grid traversal) | | AR placement | WebXR hit-test API (매 system-provided) | **기본값**: Three.js + three-mesh-bvh 매 web 의 standard. 매 dynamic 매 BVH refit. 매 GPU compute 매 last resort. ## 🔗 Graph - 부모: [[Computational Geometry]] · [[Computer Graphics]] - 응용: [[Collision Detection]] - Adjacent: [[KD-Tree]] ## 🤖 LLM 활용 **언제**: 매 3D scene 매 user input mapping (click/touch/AR). 매 line-of-sight / occlusion query. 매 sweep collision 1-shot. **언제 X**: 매 2D UI hit-test (DOM event 매 충분). 매 dense per-pixel intersection — 매 GPU rasterization 매 더 fast. ## ❌ 안티패턴 - **매 frame 의 brute-force intersect 모든 triangle**: 매 100k tri scene 매 60fps 의 X — 매 BVH 필수. - **BVH refit 의 X 매 dynamic mesh**: 매 stale tree → 매 missed hits. - **Far plane 무시**: 매 무한 ray 매 매 distant unimportant geom hit. - **Ray direction 매 unnormalized**: 매 t value 매 distance 의 X — 매 모든 distance compare 매 broken. - **Single-precision float 의 self-intersection**: 매 origin offset (`+ 0.001 * normal`) 매 epsilon 처리. ## 🧪 검증 / 중복 - Verified (Möller-Trumbore 1997 paper, Three.js 2026 source, three-mesh-bvh 0.7+). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Möller-Trumbore + BVH + WebXR hit-test + WebGPU compute |