Add Chromium-only Blender WebEngine parity work
This commit is contained in:
33
docs/web/coordinate-color-contract.md
Normal file
33
docs/web/coordinate-color-contract.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Coordinate and Color Contract v1
|
||||
|
||||
## Coordinate spaces
|
||||
|
||||
Blender scene data is the authority. The browser adapter performs one explicit
|
||||
conversion at the SceneIR -> Three.js boundary; React components never convert
|
||||
coordinates independently.
|
||||
|
||||
| Data | Blender source | Web representation | Rule |
|
||||
| --- | --- | --- | --- |
|
||||
| Object transform | local/world matrices | column-major `Float32Array(16)` | preserve parent inverse and negative scale |
|
||||
| Position/vector | Blender Z-up | Three.js Y-up adapter space | convert once in `three-adapter` |
|
||||
| Normal/tangent | evaluated mesh | normalized buffer attributes | inverse-transpose for object scale |
|
||||
| UV | mesh loop corner | `uv` buffer attribute | preserve V direction from source contract |
|
||||
| Distance | Blender unit | meters only at import/export boundary | do not silently rescale scene values |
|
||||
| Camera | Blender camera | Three.js camera | preserve perspective/orthographic parameters |
|
||||
|
||||
## Color spaces
|
||||
|
||||
- Base color and emission textures are decoded as sRGB unless Blender metadata
|
||||
explicitly says otherwise.
|
||||
- Metallic, roughness, normal, mask and weight textures remain linear data.
|
||||
- Vertex colors are converted according to their Blender color attribute domain and
|
||||
storage type; no implicit gamma conversion is allowed in the SceneIR serializer.
|
||||
- Exposure and tone mapping belong to the Three.js renderer settings, not to
|
||||
material data.
|
||||
|
||||
## Test fixtures
|
||||
|
||||
The contract is validated with an axis object, a non-uniformly scaled cube, a
|
||||
negative-scale mirror, a perspective camera, an orthographic camera, an animated
|
||||
object and an sRGB/linear texture pair. Every fixture records source values and
|
||||
adapter values in `tests/golden/coordinate-color/`.
|
||||
27
docs/web/dependency-matrix.md
Normal file
27
docs/web/dependency-matrix.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Web Dependency Matrix
|
||||
|
||||
This is the initial dependency decision for the browser build. A dependency may
|
||||
move from `待验证` only after a task adds a build or browser regression test.
|
||||
|
||||
| Dependency or module | Decision | Web role | Evidence or next task |
|
||||
| --- | --- | --- | --- |
|
||||
| `blenlib`, `guardedalloc` | 保留 | Blender base/runtime utilities | W-022 |
|
||||
| `makesdna`, `makesrna` | 保留 | DNA/RNA data and property schema | W-022 |
|
||||
| `blenloader`, `blenkernel` | 保留 | `.blend` read/write and data blocks | W-022, W-030 |
|
||||
| `bmesh` | 保留 | mesh editing and Decimate primitives | W-022, W-074 |
|
||||
| `depsgraph` | 保留 | hierarchy, modifiers, evaluated mesh | W-067, W-093 |
|
||||
| selected `modifiers` | 保留白名单 | Blender 5.2 types are identity-complete; evaluated parity remains fixture-gated | [modifier support matrix](modifier-support-matrix.md), W-066, W-074 |
|
||||
| `windowmanager`, `editors`, `ghost` | React replacement | Blender-style UI semantics, not desktop window backend | W-018, W-019 |
|
||||
| Blender `draw/gpu` viewport | 关闭首期 | Three.js is the browser renderer | W-013, W-050 |
|
||||
| Python runtime and automatic `.blend` scripts | 关闭首期 | security and package-size boundary | W-117 |
|
||||
| Cycles, CUDA/OptiX, Embree | 关闭首期 | server-side or native rendering only | roadmap non-goal |
|
||||
| OpenVDB, USD, FFmpeg | 关闭首期 | server-side or later format modules | W-021 |
|
||||
| React + TypeScript | 保留 | application UI and state | W-010 |
|
||||
| Three.js (vendored) | 保留 | WebGL2 viewport and scene adapter; runtime has no CDN dependency | W-013, W-050 |
|
||||
| Emscripten runtime | 保留 | Blender C/C++ to WebAssembly | W-020~W-025 |
|
||||
| zlib 1.3.1 (vendored) | 保留 | gzip `.blend` decompression in Blender file reader | W-030 |
|
||||
| zstd 1.5.7 (vendored) | 保留 | zstd `.blend` decompression in Blender file reader | W-030 |
|
||||
| IndexedDB | 保留 | project metadata and small persistent records in StorageWorker | W-014, W-041 |
|
||||
| OPFS | 保留 | large `.blend`, assets, snapshots and LOD cache | W-040, W-077 |
|
||||
|
||||
No CAD kernel or Bitbybit/OCCT module is part of this matrix.
|
||||
71
docs/web/depsgraph-evaluation-contract.md
Normal file
71
docs/web/depsgraph-evaluation-contract.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Blender Depsgraph Evaluation Contract
|
||||
|
||||
`evaluateDepsgraph` is an explicit WebEngine Worker command intended to evaluate
|
||||
the currently opened `.blend` with Blender 5.2's native loader and dependency
|
||||
graph. It does not reinterpret the SceneIR modifier metadata in TypeScript.
|
||||
|
||||
Current status: the native module executes Blender 5.2 full loading, view-layer
|
||||
synchronization, graph build, tagged update and frame evaluation in the headless
|
||||
WASM runtime for the declared fixtures. The wasm32 DNA bridge recursively aligns
|
||||
64-bit members, and the Web ID registry includes embedded NodeTree, Camera,
|
||||
Light, Lattice and Grease Pencil data. The command returns the native
|
||||
`BlenderDepsgraph/EVALUATED` report;
|
||||
loader, graph or schema failures remain structured errors and never become
|
||||
Three.js approximations.
|
||||
|
||||
The native evaluation sequence is:
|
||||
|
||||
1. Initialize Blender's headless data runtime once per WASM module.
|
||||
2. Load the saved buffer with `BLO_read_from_memory`.
|
||||
3. Synchronize view layers, build the viewport Depsgraph and apply tagged and
|
||||
frame evaluation.
|
||||
4. Return modifier identity/status for every evaluated object and final mesh
|
||||
vertex positions and triangle indices for every mesh
|
||||
object, keyed by stable SceneIR object/Mesh IDs. Each mesh also returns its
|
||||
original modifier stack in order. Entries carry Blender's persistent UID,
|
||||
registered type name, viewport/render/edit/cage flags, target object IDs,
|
||||
the previous-stack and cross-object dependency edges, and an explicit
|
||||
status: `EVALUATED`, `DISABLED` or `BLOCKED`. Blocked entries carry a stable
|
||||
`errorCode`, human-readable `error` and actionable `suggestion`; they are
|
||||
never silently treated as successful evaluation.
|
||||
|
||||
The result is validated by `parseDepsgraphEvaluation`. Every mesh must have a
|
||||
16-value world matrix, exactly `vertexCount * 3` position values and exactly
|
||||
`triangleCount * 3` in-range integer indices. A load, initialization or graph
|
||||
failure returns the existing structured WebEngine error; it must never fall
|
||||
back to a Three.js approximation.
|
||||
|
||||
The rigged fixture is checked against a golden written by desktop Blender 5.2.
|
||||
The golden disables the fixture's Preview Decimate modifier solely to isolate
|
||||
shape-key plus armature deformation. The current Web deformation evaluator
|
||||
already compares final positions under the declared maximum and RMS error
|
||||
budget. Native WASM Depsgraph evaluation must pass the same comparison and
|
||||
repeated memory-safety runs before this contract is considered complete.
|
||||
|
||||
The offline regression `npm --prefix web run test:depsgraph` checks this report
|
||||
schema for all declared fixtures and verifies the rigged stack order
|
||||
`Armature -> Decimate`, its stack edge, the Armature target object edge and
|
||||
Blender's structured "requires more than 3 input faces" Decimate block.
|
||||
Drivers and constraints remain separate matrix entries. Geometry Nodes now has
|
||||
two explicitly bounded native closures described below; it is not a claim of
|
||||
general node-graph evaluation.
|
||||
|
||||
The category fixture suite adds Generate, Deform, Physics, Geometry Nodes and
|
||||
Grease Pencil desktop goldens. Twenty-four category types execute native Web
|
||||
implementations and compare topology/positions, including serialized
|
||||
Mesh/Surface Deform bind caches and frame-6 Build/Wave output. Subdivision uses
|
||||
the locally linked OpenSubdiv 3.7.0 CPU evaluator; exact Boolean uses local GMP
|
||||
6.3.0; Curve evaluates through Blender's native modifier after registering the
|
||||
Curves ID type. Their category goldens now pass in wasm32.
|
||||
|
||||
Geometry Nodes is intentionally narrower than Blender's full lazy-function
|
||||
runtime. The evaluator accepts a three-node graph containing either Transform
|
||||
Geometry in Components mode with literal defaults, or Set Position with an
|
||||
unlinked constant selection/offset. Both use Blender mesh APIs and match desktop
|
||||
goldens. Other graph shapes produce `BLENDER_MODIFIER_ERROR`; simulation/bake
|
||||
state produces `GEOMETRY_NODES_SIMULATION_UNAVAILABLE` and preserves input geometry.
|
||||
|
||||
Other unsupported implementations retain their original DNA type code through
|
||||
a disabled placeholder and report `UNSUPPORTED_MODIFIER_TYPE`; they are not
|
||||
rewritten to `None`. Unsupported resource closures are validated before their
|
||||
implementation can mutate geometry or enter an unavailable runtime path.
|
||||
31
docs/web/local-dependencies.md
Normal file
31
docs/web/local-dependencies.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 本地依赖策略
|
||||
|
||||
浏览器运行时禁止从 CDN、远程 ESM 或第三方脚本地址加载功能模块。依赖分为
|
||||
三类:
|
||||
|
||||
| 类别 | 当前模块 | 本地实现 |
|
||||
| --- | --- | --- |
|
||||
| 项目 vendored 运行时 | Three.js 0.185.1、OrbitControls、WebEngine glue/WASM | `web/app/src/vendor/`、`web/app/public/vendor/` |
|
||||
| WASM 构建压缩库 | zlib 1.3.1、zstd 1.5.7 | `blender-5.2.0/extern/zlib/`、`blender-5.2.0/extern/zstd/`,由 Web CMake 的本地静态 target 使用 |
|
||||
| npm 构建依赖 | React、ReactDOM、Vite、TypeScript | `web/package-lock.json` 锁定,Vite 打入本地 `dist/assets/index-*.js` |
|
||||
| 测试/工具依赖 | Playwright、ESLint、Emscripten | `web/node_modules`、系统 Emscripten 和本机 Chrome;不进入浏览器产物 |
|
||||
|
||||
`tools/web/check-local-deps.sh` 是发布前门禁:检查 runtime dependencies 在本地
|
||||
安装、Three.js 没有回退到 npm runtime import、vendor 资源存在,并扫描源码和
|
||||
`dist/` 中的 CDN/远程 ESM 地址,同时按 `engine-manifest.json` 校验本地 WASM
|
||||
SHA-256。npm registry 只发生在开发机首次安装阶段;发布/浏览器运行只提供
|
||||
`web/dist` 的同源静态文件。离线开发需要预先保留 `node_modules` 或 npm
|
||||
缓存,随后可用 `npm ci --offline` 重建,运行时不再访问 registry。
|
||||
|
||||
Blender Web CMake 不使用 `ExternalProject`、FetchContent 或构建时下载。zlib
|
||||
和 zstd 的源码、许可证和 CMake 输入已放入 `blender-5.2.0/extern/`;浏览器只
|
||||
加载 `web_engine.js` 与同源 `web_engine.wasm`,不加载 SQLite WASM、OCCT 或
|
||||
任何远程模块。
|
||||
|
||||
可复现的离线检查命令:
|
||||
|
||||
```text
|
||||
cd web
|
||||
npm ci --offline --ignore-scripts
|
||||
npm run check:local-deps
|
||||
```
|
||||
66
docs/web/mesh-buffer-layout.md
Normal file
66
docs/web/mesh-buffer-layout.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# MeshIR Buffer Layout
|
||||
|
||||
This document is the versioned boundary between the Blender reader and the
|
||||
Three.js renderer. The compatibility C ABI returns a JSON snapshot. The
|
||||
preferred ABI separates JSON metadata from a native WBG1 geometry stream, and
|
||||
the Worker transfers each typed mesh buffer without reconstructing large JSON
|
||||
arrays. JSON arrays remain a fallback for older engine binaries.
|
||||
|
||||
## Coordinate and topology contract
|
||||
|
||||
- Blender source coordinates are right-handed, Z-up, with forward `-Y`.
|
||||
- Positions and normals use packed little-endian IEEE-754 `float32` values.
|
||||
- `indices` are packed little-endian unsigned 32-bit integers and reference
|
||||
`positions` vertices.
|
||||
- `topology` is `triangles`; every three indices form one triangle.
|
||||
- `triangleCornerIndices` maps every index entry to the original Blender mesh
|
||||
corner. It is required when UV or color attributes are present because a
|
||||
single position can have multiple corner values.
|
||||
- `triangleMaterialIndices` has one non-negative integer per triangle and
|
||||
indexes `materialSlotIds`.
|
||||
|
||||
## SceneIR fields
|
||||
|
||||
| Field | Element count | Type | Domain |
|
||||
| --- | ---: | --- | --- |
|
||||
| `positions` | `vertexCount * 3` | `float32` | Point |
|
||||
| `normals` | `vertexCount * 3` | `float32` | Point, normalized |
|
||||
| `indices` | `triangleCount * 3` | `uint32` | Triangle corners |
|
||||
| `triangleCornerIndices` | `triangleCount * 3` | `uint32` | Blender Corner |
|
||||
| `uvs` | `cornerCount * 2` | `float32` | Corner, optional |
|
||||
| `colors` | `cornerCount * 4` | `float32` RGBA | Corner, optional |
|
||||
| `triangleMaterialIndices` | `triangleCount` | `uint32` | Face expanded to triangles |
|
||||
| `triangleFaceIndices` | `triangleCount` | `uint32` | Source face for edit selection |
|
||||
| `edgeVertexIndices` | `edgeCount * 2` | `uint32` | Edge endpoints |
|
||||
| `tangents` | `cornerCount * 4` | `float32` | Corner tangent/sign, optional |
|
||||
| `splitNormals` | `cornerCount * 3` | `float32` | Corner normal, optional |
|
||||
|
||||
`bounds.min` and `bounds.max` are three finite JSON numbers in source object
|
||||
space. `materialSlotIds` are stable SceneIR IDs and never contain embedded
|
||||
material data.
|
||||
|
||||
## Native WBG1 stream
|
||||
|
||||
The stream starts with `WBG1`, a little-endian schema version and mesh count.
|
||||
Each mesh contains an ID length, eleven element counts, UTF-8 ID bytes, then
|
||||
the following arrays in order:
|
||||
|
||||
```text
|
||||
positions:f32, indices:u32, normals:f32, triangleCornerIndices:u32,
|
||||
uvs:f32, colors:f32, triangleMaterialIndices:u32,
|
||||
triangleFaceIndices:u32, edgeVertexIndices:u32, tangents:f32,
|
||||
splitNormals:f32
|
||||
```
|
||||
|
||||
Every count is element-based and every scalar is 4 bytes, so array starts stay
|
||||
4-byte aligned. The decoder rejects truncation/trailing bytes, unknown mesh
|
||||
IDs, count/summary mismatches and indices outside `vertexCount`. Topology
|
||||
changes must regenerate triangle-face and edge mappings; stale source arrays
|
||||
are never accepted.
|
||||
|
||||
`geometryStatus: "binary"` means metadata references a transferred per-mesh
|
||||
buffer through `geometryBufferId`. `geometryStatus: "available"` is the JSON
|
||||
fallback. After the initial WBG1 generation, `MeshGeometryDelta` carries
|
||||
`meshId`, field, byte offset and transferable replacement bytes for stable-size
|
||||
changes; topology or attribute-layout changes replace only that mesh envelope.
|
||||
Network-style progressive sub-mesh streaming is not implied by WBG1.
|
||||
143
docs/web/modifier-support-matrix.md
Normal file
143
docs/web/modifier-support-matrix.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Blender 5.2 Modifier Web Support Matrix
|
||||
|
||||
This matrix separates file recognition, dependency extraction and evaluated
|
||||
result parity. Loading a modifier type is not evidence that its Web result
|
||||
matches Blender desktop.
|
||||
|
||||
## Status levels
|
||||
|
||||
| Level | Meaning |
|
||||
| --- | --- |
|
||||
| `IDENTITY` | Type code/name, UUID, stack order and mode flags are preserved. |
|
||||
| `PARAMETERS` | Declared parameters are present in SceneIR. No evaluated mesh is implied. |
|
||||
| `TARGET_EDGE` | Cross-object target IDs are present in the native Depsgraph report. |
|
||||
| `NATIVE_FIXTURE` | Native WASM Depsgraph behavior is covered by a Blender fixture/golden. |
|
||||
| `COMMAND` | A revisioned Web command can execute and has undo/redo or isolated-preview coverage. |
|
||||
| `BLOCKED` | No parity claim. An enabled unsupported/invalid entry must return a structured block. |
|
||||
|
||||
## Current verified set
|
||||
|
||||
| Modifier | Identity | Parameters | Target edge | Native fixture | Command |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Subdivision Surface | yes | levels/type | no | desktop/WASM topology and geometry parity through local OpenSubdiv 3.7.0 CPU evaluator | no |
|
||||
| Mirror | yes | axis/merge flags | optional mirror object | desktop/WASM geometry parity | no |
|
||||
| Boolean (Exact) | yes | operation/solver | target object | desktop/WASM surface parity through local GMP 6.3.0 | no |
|
||||
| Decimate | yes | mode/ratio/iterations/delimit | no | structured small-mesh error | Collapse/Un-Subdivide/Dissolve command |
|
||||
| Armature | yes | target/group/deform flags | yes | rigged shape-key golden | enable/disable + undo/redo |
|
||||
| Bevel | yes | width/segments/profile | no | desktop/WASM geometry parity | no |
|
||||
| Lattice | yes | target/group/strength/flags | yes | desktop/WASM geometry parity | no |
|
||||
| Curve | yes | target/group/axis/flags | yes | desktop/WASM topology and geometry parity | no |
|
||||
| Hook | yes | target/subtarget/group/falloff/force | yes | desktop/WASM geometry parity | no |
|
||||
| Mesh Deform | yes | target/group/grid/flags | yes | bound-cache desktop/WASM geometry parity | no |
|
||||
| Shrinkwrap | yes | targets/group/distance/type/mode/limit | primary/aux targets | desktop/WASM geometry parity | no |
|
||||
| Surface Deform | yes | target/group/falloff/strength/flags | yes | bound-cache desktop/WASM geometry parity | no |
|
||||
| Array/Solidify | yes | fixture parameters | object edges where used | desktop/WASM geometry parity | no |
|
||||
| Triangulate/Weld | yes | fixture parameters | no | desktop/WASM topology and geometry parity | no |
|
||||
| Build/Wave | yes | frame/time parameters | object/texture edges where used | frame-6 desktop/WASM geometry parity | no |
|
||||
| Geometry Nodes | yes | node group/default socket values | node-group edge | bounded Transform Geometry and Set Position closures match desktop | no |
|
||||
| Edge Split | yes | angle/sharp flags | no | desktop/WASM topology and geometry parity | no |
|
||||
| Screw | yes | axis/angle/steps/merge | optional axis object | desktop/WASM topology and geometry parity | no |
|
||||
| Displace | yes | direction/strength/mid-level/space | optional mapping object | constant local-space desktop/WASM parity; resource configurations block | no |
|
||||
|
||||
Native `targetObjectIds` currently covers Array, Mirror, Boolean, Lattice, Curve, Armature, Hook,
|
||||
Mesh Deform, Shrinkwrap, Surface Deform, Screw and Displace mapping objects.
|
||||
The ordered `dependsOn` list contains the prior stack entry followed by those
|
||||
external object IDs. These SceneIR entries remain `METADATA_ONLY`; the Worker
|
||||
still blocks topology/LOD commands until evaluated input is available.
|
||||
|
||||
## Complete Blender 5.2 identity coverage
|
||||
|
||||
The lightweight reader now covers every DNA slot from `0` through `86`; a C++
|
||||
`static_assert` fails the build when `NUM_MODIFIER_TYPES` grows without a table
|
||||
update. The category-golden native whitelist contains 24 evaluated types:
|
||||
`SUBSURF`, `MIRROR`, `ARRAY`, exact `BOOLEAN`, `BEVEL`, `SOLIDIFY`,
|
||||
`TRIANGULATE`, `WELD`, `LATTICE`, `HOOK`, `SHRINKWRAP`, `SIMPLE_DEFORM`,
|
||||
`MESH_DEFORM`, `SURFACE_DEFORM`, `CURVE`, `BUILD`, `WAVE` and the bounded
|
||||
`NODES` closures, plus `SMOOTH`, `CAST`, `WIREFRAME`, `EDGE_SPLIT`, `SCREW` and
|
||||
bounded `DISPLACE`.
|
||||
Armature, Shape Key and Decimate have earlier dedicated
|
||||
fixtures. The remaining identity-only types are:
|
||||
|
||||
`NONE`, `SOFT_BODY`, `UV_PROJECT`,
|
||||
`PARTICLE_SYSTEM`, `PARTICLE_INSTANCE`, `EXPLODE`, `CLOTH`,
|
||||
`COLLISION`, `FLUID_SIM`, `MASK`, `MULTIRES`, `SURFACE`, reserved slot `31`,
|
||||
`WARP`, `WEIGHT_VG_EDIT`, `WEIGHT_VG_MIX`, `WEIGHT_VG_PROXIMITY`,
|
||||
`OCEAN`, `DYNAMIC_PAINT`, `REMESH`, `SKIN`, `LAPLACIAN_SMOOTH`, `UV_WARP`,
|
||||
`MESH_CACHE`, `LAPLACIAN_DEFORM`, `DATA_TRANSFER`,
|
||||
`NORMAL_EDIT`, `CORRECTIVE_SMOOTH`, `MESH_SEQUENCE_CACHE`, `WEIGHTED_NORMAL`,
|
||||
`FLUID`, `MESH_TO_VOLUME`, `VOLUME_DISPLACE`, `VOLUME_TO_MESH`,
|
||||
`GREASE_PENCIL_OPACITY`, `GREASE_PENCIL_SUBDIV`, `GREASE_PENCIL_COLOR`,
|
||||
`GREASE_PENCIL_TINT`, `GREASE_PENCIL_SMOOTH`, `GREASE_PENCIL_OFFSET`,
|
||||
`GREASE_PENCIL_NOISE`, `GREASE_PENCIL_MIRROR`, `GREASE_PENCIL_THICKNESS`,
|
||||
`GREASE_PENCIL_LATTICE`, `GREASE_PENCIL_DASH`, `GREASE_PENCIL_MULTIPLY`,
|
||||
`GREASE_PENCIL_LENGTH`, `GREASE_PENCIL_WEIGHT_ANGLE`,
|
||||
`GREASE_PENCIL_ARRAY`, `GREASE_PENCIL_WEIGHT_PROXIMITY`,
|
||||
`GREASE_PENCIL_HOOK`, `GREASE_PENCIL_LINEART`, `GREASE_PENCIL_ARMATURE`,
|
||||
`GREASE_PENCIL_TIME`, `GREASE_PENCIL_ENVELOPE`, `GREASE_PENCIL_OUTLINE`,
|
||||
`GREASE_PENCIL_SHRINKWRAP`, `GREASE_PENCIL_BUILD`,
|
||||
`GREASE_PENCIL_SIMPLIFY`, `GREASE_PENCIL_TEXTURE`.
|
||||
|
||||
## Blocking contract
|
||||
|
||||
An enabled unregistered native modifier returns `UNSUPPORTED_MODIFIER_TYPE`.
|
||||
An enabled target-based modifier without a target returns
|
||||
`MODIFIER_TARGET_MISSING`. An error raised by Blender itself returns
|
||||
`BLENDER_MODIFIER_ERROR`. Resource/configuration-dependent Displace returns
|
||||
`MODIFIER_CONFIGURATION_UNSUPPORTED`; simulation/bake GN returns
|
||||
`GEOMETRY_NODES_SIMULATION_UNAVAILABLE`. A target path that reaches the owner returns
|
||||
`MODIFIER_DEPENDENCY_CYCLE`. All blockers include the modifier object/name/type,
|
||||
`error`, and an actionable `suggestion`. Viewport-disabled modifiers remain
|
||||
`DISABLED` and do not inherit stale evaluated errors.
|
||||
|
||||
## Category fixtures
|
||||
|
||||
| Category | Blender 5.2 golden | Current Web result |
|
||||
| --- | --- | --- |
|
||||
| Generate | Subdivision, Mirror, Array, Boolean, Bevel, Solidify, Triangulate, Weld | All eight execute native Blender code. Subdivision matches the 26-vertex/48-triangle OpenSubdiv golden; Exact Boolean matches the 12-vertex/20-triangle surface golden. |
|
||||
| Deform | Lattice, Hook, Shrinkwrap, Simple Deform, Mesh Deform, Surface Deform | All six match desktop geometry; Mesh/Surface fixtures contain real bind caches and target deformation. |
|
||||
| Curve | Curve target and evaluated output in a dedicated fixture | Native Curve evaluation matches desktop topology and positions within the declared floating-point tolerance. |
|
||||
| Physics/time | Build and Wave at frame 6; disabled Cloth, Soft Body and Collision | Build and Wave match desktop geometry at frame 6; simulation entries remain `DISABLED`. |
|
||||
| Geometry Nodes | Self-contained Transform Geometry, Set Position and simulation-zone graphs | Constant Transform and Set Position match desktop positions/topology. Simulation zones preserve input and return `GEOMETRY_NODES_SIMULATION_UNAVAILABLE` without consuming temporal state. |
|
||||
| Grease Pencil | One drawing plus all 26 GP modifier types exposed by Blender 5.2 Python | GP data loads; all modifier codes/modes are preserved and remain `DISABLED`. |
|
||||
| Extended native | Edge Split, Screw and bounded Displace | All match desktop topology/positions; RGB/resource Displace preserves input and returns `MODIFIER_CONFIGURATION_UNSUPPORTED`. |
|
||||
|
||||
Line Art is exposed as `LINEART` rather than with the `GREASE_PENCIL_` prefix;
|
||||
the generator includes it explicitly. The fixtures, desktop goldens and
|
||||
comparison runner are generated by
|
||||
`tools/web/generate-modifier-fixtures.py`,
|
||||
`tools/web/generate-modifier-goldens.py` and checked offline with
|
||||
`npm --prefix web run test:modifier-goldens`.
|
||||
|
||||
## Local native dependencies
|
||||
|
||||
Subdivision uses the local OpenSubdiv 3.7.0 source and archive under
|
||||
`blender-5.2.0/extern/opensubdiv-source`. The Web build enables its CPU-only
|
||||
static evaluator and disables GPU, examples, documentation and tests. The
|
||||
archive MD5 is `470d53c4d4335a601c33a052ce7c33b4`; SHA-256 is
|
||||
`f843eb49daf20264007d807cbc64516a1fed9cdb1149aaf84ff47691d97491f9`.
|
||||
|
||||
Exact Boolean uses the local GMP 6.3.0 DFSG source plus Emscripten static
|
||||
archives under `blender-5.2.0/extern/gmp-source` and
|
||||
`blender-5.2.0/extern/gmp-wasm`. The source archive MD5 is
|
||||
`d4a3890b5e28df535b653b07798b11b2`; SHA-256 is
|
||||
`bd2966e6d277f79328e894a5a9f3ba3fbf2ed2be81def5f48623e30c23fb1572`.
|
||||
`WITH_MANIFOLD` remains off: Blender 5.2's verified Exact solver path uses GMP,
|
||||
so Manifold is not part of the tested runtime closure. wasm32 and desktop may
|
||||
choose different valid diagonals on coplanar faces; the golden therefore
|
||||
compares oriented surface area and geometry instead of requiring identical
|
||||
triangle indices.
|
||||
|
||||
`npm --prefix web run check:local-deps` verifies both source archive hashes,
|
||||
the OpenSubdiv CMake source and the local GMP/GMPXX headers and WASM archives.
|
||||
|
||||
## Future whitelist expansion
|
||||
|
||||
1. Add deterministic physics cache stepping for Cloth/Soft Body/Collision;
|
||||
Build and Wave are complete for the current frame golden.
|
||||
2. Expand Geometry Nodes from the verified Transform Geometry and Set Position closures in small
|
||||
node/dependency batches. Simulation zones, bake data, fields, instances and
|
||||
the full lazy-function graph remain outside the current whitelist.
|
||||
3. Enable Grease Pencil modifiers in small dependency batches; keep target and
|
||||
simulation types disabled until their external resources are validated.
|
||||
4. Add native geometry goldens for the remaining Generate/Deform families,
|
||||
including Cast, Remesh, Multires and volume conversions.
|
||||
78
docs/web/third-party-notices.json
Normal file
78
docs/web/third-party-notices.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"packages": [
|
||||
{
|
||||
"name": "Blender",
|
||||
"version": "5.2.0",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"source": "blender-5.2.0/",
|
||||
"notice": "Blender source and license files remain in the upstream source tree."
|
||||
},
|
||||
{
|
||||
"name": "React",
|
||||
"version": "19.2.8",
|
||||
"license": "MIT",
|
||||
"source": "web/node_modules/react (installed from locked npm package)"
|
||||
},
|
||||
{
|
||||
"name": "ReactDOM",
|
||||
"version": "19.2.8",
|
||||
"license": "MIT",
|
||||
"source": "web/node_modules/react-dom (installed from locked npm package)"
|
||||
},
|
||||
{
|
||||
"name": "Three.js",
|
||||
"version": "0.185.1",
|
||||
"license": "MIT",
|
||||
"source": "web/app/src/vendor/three/"
|
||||
},
|
||||
{
|
||||
"name": "Emscripten runtime",
|
||||
"version": "3.1.69",
|
||||
"license": "MIT",
|
||||
"source": "local emsdk"
|
||||
},
|
||||
{
|
||||
"name": "Vite",
|
||||
"version": "8.2.0",
|
||||
"license": "MIT",
|
||||
"source": "web/node_modules/vite (build-time only)"
|
||||
},
|
||||
{
|
||||
"name": "TypeScript",
|
||||
"version": "5.9.3",
|
||||
"license": "Apache-2.0",
|
||||
"source": "web/node_modules/typescript (build-time only)"
|
||||
},
|
||||
{
|
||||
"name": "Playwright",
|
||||
"version": "1.62.1",
|
||||
"license": "Apache-2.0",
|
||||
"source": "web/node_modules/@playwright/test (test-time only)"
|
||||
},
|
||||
{
|
||||
"name": "OpenSubdiv",
|
||||
"version": "3.7.0",
|
||||
"license": "Apache-2.0",
|
||||
"source": "blender-5.2.0/extern/opensubdiv-source"
|
||||
},
|
||||
{
|
||||
"name": "GMP",
|
||||
"version": "6.3.0",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"source": "blender-5.2.0/extern/gmp-source"
|
||||
},
|
||||
{
|
||||
"name": "zlib",
|
||||
"version": "1.3.1",
|
||||
"license": "Zlib",
|
||||
"source": "blender-5.2.0/extern/zlib/ (vendored build dependency)"
|
||||
},
|
||||
{
|
||||
"name": "zstd",
|
||||
"version": "1.5.7",
|
||||
"license": "BSD-3-Clause",
|
||||
"source": "blender-5.2.0/extern/zstd/ (vendored build dependency)"
|
||||
}
|
||||
]
|
||||
}
|
||||
19
docs/web/three-vendor.md
Normal file
19
docs/web/three-vendor.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Three.js 本地资源
|
||||
|
||||
当前使用 Three.js `0.185.1`。运行时模块已从锁定的 npm 包复制到项目源码:
|
||||
|
||||
- `web/app/src/vendor/three/three.module.js`
|
||||
- `web/app/src/vendor/three/three.core.js`
|
||||
- `web/app/src/vendor/three/addons/controls/OrbitControls.js`
|
||||
|
||||
视口适配器只引用上述相对路径,OrbitControls 的裸 `three` 导入也已改为
|
||||
本地相对导入。构建产物把代码打进本地 `index` chunk,不从 CDN 或网页运行时
|
||||
网络加载 Three.js。`@types/three` 仅作为开发期类型依赖。
|
||||
|
||||
## 校验
|
||||
|
||||
```text
|
||||
three.module.js bbf5ed13fe4373f5bd38b14ea8e62e9f157327da5638edc6d3863e08b167c9c7
|
||||
three.core.js 3718df126d69c125362a03340913204470d8c50238605150e57f808840fb7759
|
||||
OrbitControls.js 1e08bf297c9062aa5055a9d649d8a8458c3871aa31c7d600f535a06f567e7cad
|
||||
```
|
||||
Reference in New Issue
Block a user