terrain op• 데이터 종류: mesh → mesh
• 호출: import fullseye as fs; fs.ledger.mesh_scatter_boulders(V, F, *, density: 'float', d_min: 'float', d_max=None, exponent: 'float' = 3.1, seed: 'int' = 0, region_weights=None, aspect=(1.0, 0.7, 0.5), embed: 'float' = 0.35, subdiv: 'int' = 1, shape: 'str' = 'ellipsoid', orientation: 'str' = 'normal', burial=(0.3, 0.6), max_count=None, hull_points=None, return_info: 'bool' = False)(구현을 직접 호출하려면 import render3d; render3d.mesh_scatter_boulders(V, F, *, density: 'float', d_min: 'float', d_max=None, exponent: 'float' = 3.1, seed: 'int' = 0, region_weights=None, aspect=(1.0, 0.7, 0.5), embed: 'float' = 0.35, subdiv: 'int' = 1, shape: 'str' = 'ellipsoid', orientation: 'str' = 'normal', burial=(0.3, 0.6), max_count=None, hull_points=None, return_info: 'bool' = False), 원장에서 가져오려면 ops3d.get("mesh_scatter_boulders"))
메시 위에 반쯤 묻힌 암괴를 흩뿌립니다(크기는 멱법칙, seed 포함) → (V, F).
(또는 return_info=True 일 때 (V, F, info)).
shape='ellipsoid'(기본값, 기존 동작 그대로): 반축이 D/2 × aspect(1 : 0.7 : 0.5, 최단축은 국소 표면 법선 방향)인 icosphere 타원체를법선 둘레로 회전시키고 embed 만큼 가라앉힌다(0 = 면 위에 놓임, 1 = 중심이 표면 위). shape='hull': 모난 암괴 — 같은 종횡비에 20 % 반경 방향 지터를 준타원체 위의 seed 고정 난수 점들의 볼록 껍질(평평한 소면, 날카로운 모서리, Itokawa 바위의 모습), 암괴마다 hull_points 개의 점(기본값은 크기 의존:
10 + 8·log2(D/d_min), 10..40). orientation='random' 은 짧은 축을 법선에 맞추는 대신각 암괴에 균일 랜덤 회전을 준다. hull 의 경우 가라앉는 양은 sample_boulders 가 주는 크기 의존 burial 비율이다(기본적으로 암괴 높이의 30–60 % 가 표면 아래; embed 는 무시). max_count 는 같은 법칙에 따라 d_min 을 올려기대 개수를 제한한다(참고:
sample_boulders; info['d_min_effective'] 가 그 값을 보고한다).
위치와 크기는 sample_boulders 에서 온다(포아송 과정, N(>D) ∝ D^-exponent). 바위는 *넘겨받은 그대로의* 메시 위에 놓이므로 변위/ 세분이 끝난 지형을 넘겨야 최종 표면 위에 놓인다. terrain_region_mask 의 region_weights 는 바다(maria) 영역을 매끄럽게 유지한다. 바위는 실제지오메트리로 추가되므로 지형과 같은 래스터라이저/ 레이캐스트 경로로 자기 그림자, 투영 그림자, 가림이 생긴다. info = 샘플 dict 에 faces_per_boulder 와 n_boulders 를 더한 것. seed 하에서 결정적. Fail-closed.
절차: sample_boulders 로 위치(면 위의 균일 점), 면 법선, 지름 D 를 뽑고, 바위마다작은 메시를 만들어 입력 메시 뒤에 연결한다(정점은 끝에 추가, 면 index 는오프셋 적용됨). 입력의 정점과 면은 그대로 남으므로 info['faces_per_boulder'] 와원래 면 수로부터 바위의 면만 잘라낼 수 있다.
• density: 단위 면적(메시 단위²)당 D ≥ d_min 인 바위의 기대 개수. 실제 개수는 포아송 분포로 정해지며 0 개일 수도 있다(그때는 입력의 복사본을 반환).
• d_min < d_max(None = 10·d_min), exponent > 0, aspect 는 양수 3 요소, embed ∈ [0, 1], subdiv ∈ [0, 3] (타원체의 icosphere 세분), hull_points 는 [6, 200]. 모두 범위를 벗어나면 ValueError.
• shape='ellipsoid': 반축 D/2·aspect 인 타원체를 최단축이 법선을 따르는 방향으로 놓고, 중심을 법선 방향으로 semi_z·(1 − embed) 만큼 띄운다.
• shape='hull': 타원체 위 난수 점들의 볼록 껍질. 법선 방향 높이 범위 중 burial (기본 0.3~0.6, 작은 바위일수록 깊음)의 비율이 면 아래로 가라앉는다. embed 는 무시.
• orientation='random' 은 균일 랜덤 회전(4 원수, 즉 쿼터니언). 'normal' 은 법선 둘레의랜덤 회전. 회전의 난수는 seed + 1 의 generator 를 사용한다.
바위는 실제 지오메트리이므로 ambient_occlusion / cast_shadow / shadow_raycast 의레이에 보통대로 맞는다. 놓이는 면은 넘긴 메시 그 자체이므로 mesh_displace_spectrum 이나 mesh_subdivide 의 뒤 에 호출할 것(먼저 호출하면 바위가 지면에서 뜨거나 묻힌다).
• 샘플 데이터 카탈로그(DL URL / 라이선스) —— 2-D 는 skimage.data(BSD/public)+ 합성, 3-D 는 실데이터 소스(Stanford/PDS 등)의 DL URL.
• 연산자의 내력·참고문헌 —— 이 연산자 족의 바탕이 된 연구/기법의 출처.
• itokawa_regolith_hero — py -3.11 examples_3d/itokawa_regolith_hero.py
mesh 를 입력으로 받는 것)mesh_to_voxel · mesh_to_points · to_points · fuse_to_voxel · ambient_occlusion · cast_shadow · supersample_mesh · render_beauty
terrain)mesh_displace_fbm · terrain_region_mask · mesh_edge_lengths · mesh_subdivide · displacement_band_weights · mesh_displace_spectrum · bump_normals_fbm
*Provenance: render3d.py — 3D 연산자 레지스트리. 이 op 노트는 tools/opdocs.py md 가 자동 생성합니다(직접 편집하지 마세요).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.