f8b21af4be
10_Wiki/Topics 대규모 정리: - 오류 캡처/미완성 stub 문서 227개 제거 - 교차폴더 중복 43클러스터 병합 (63파일 → redirect) - 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건 - 카테고리 MOC 6개 신규 생성 - Graph 섹션 미해결 related-keyword 링크 10,058건 제거 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
197 lines
6.4 KiB
Markdown
197 lines
6.4 KiB
Markdown
---
|
|
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 |
|