Skip to content

Blender exporter, cluster demo app, and the 3D/animation fixes it needed - #365

Merged
corepunch merged 3 commits into
mainfrom
cluster-demo-blender-export
Oct 3, 2026
Merged

corepunch merged 3 commits into
mainfrom
cluster-demo-blender-export

Conversation

@corepunch

@corepunch corepunch commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

What this adds

  • tools/blender-export.py — runs inside Blender and writes an ORCA project's 3D assets: meshes (FBX → orca-fbx), shaders, materials, animation clips, a scene prefab, and a first-time package.lua and screen.
  • apps/cluster-demo/ — a 1920×720 digital instrument cluster built procedurally in Blender and exported with the tool. Each gauge has a linear fill-up clip; the app drives a gauge by setting its AnimationPlayer.CurrentTime. Demo/FillAll.xml scrubs every gauge together as a stand-in for real inputs.
  • orca-fbx (tools/fbx-import.cpp) — honours its arguments, creates the output directory, writes vertex colours, compiles against current headers and FBX SDK 2020.2. New make orca-fbx target.

Run the demo with build/bin/orca apps/cluster-demo after regenerating the meshes (see below).

Engine fixes

Getting an exported scene to render and animate in a running app exposed these:

SceneKit

  • Viewport3D crashed when its parent was a Screen (no Node2D).
  • Model3D discarded Material.BlendMode (unset node override came back as -1 through an unsigned parameter).
  • Camera: removed the ×1.05 FOV factor and fixed the horizontal→vertical conversion (same fix as b45c771); Fov/ZNear/ZFar now have defaults.
  • PrefabView3D loaded its prefab twice at startup.
  • TextBlock3D has a Color property instead of always drawing white.

Core / renderer

  • AnimationPlayer stalled after its first frame, and the frame clock did not advance on app-loop paints, so clips never played in a running app. The clock now advances in Screen's paint handler.
  • Setting CurrentTime on a stopped player applies the clip (scrubbing).
  • vec2/vec3/vec4 uniforms were corrupted by a missing break.
  • A shader's BlendMode/DepthTestFunction/DepthWriteEnabled became uniforms and never reached the draw call.
  • Render-pass tags were never registered.
  • CDATA text in XML was dropped.
  • Texture_Create crashed without a GL context.

Tools and docs

  • tools/create-app.py generates package.lua (the runtime no longer reads package.xml).
  • QUICKSTART.md, docs/animations.md and the orca-fbx premake project corrected.

Testing

  • make test-headless and make test pass locally on macOS; a scrubbing test was added to tests/test_animations.lua.
  • CI had been red on main since the SVG loader rework because three tests described removed code; they are brought up to date here: test_filesystem.c (tested the removed _ParseLoaderArgs), test_layout.lua (expected the removed &type=mask icon query, an ImageView in IconCard, and a centred panel to stretch), test_navigationhost.lua (looked for GameBack, now BackButton in the NavigationBar prefab).
  • The demo was run in the engine on macOS and compared against the Blender render; animations were confirmed by capturing successive frames.

Skills

Two skills document the pipeline for agents: .opencode/skills/orca-blender-pipeline (authoring in Blender for the exporter) and .opencode/skills/orca-3d-scene (project layout, scene XML, shaders/uniforms, animation binding, running and verifying). .claude/skills and .agents/skills are symlinks to .opencode/skills so Claude Code and Codex find them; AGENTS.md lists them.

Reviewer notes

  • Meshes are not in the PR. .gitignore ignores *.mesh, so apps/cluster-demo/Meshes/ only carries the <Mesh> declarations. Regenerate with Blender, the FBX SDK and make orca-fbx:
    blender -b apps/cluster-demo/blender/cluster.blend --python tools/blender-export.py -- apps/cluster-demo --collection InstrumentCluster
    (the headless invocation is untested; the export was run from an interactive Blender).
  • Behaviour changes to check against existing content: camera FOV is ~5% narrower than before, Material.BlendMode now takes effect, and the frame clock advances on every screen paint.
  • The exporter's texture path is untested (the demo has no images). Text in the demo is baked mesh, not TextBlock3D.
  • Not addressed: no asset cache (each Model3D loads its own material and compiles its own shader), Viewport3D always draws to the full window, orthographic cameras are ignored, orca new still writes package.xml.

🤖 Generated with Claude Code

corepunch and others added 3 commits October 2, 2026 22:22
Getting an exported 3D scene to render and animate in a real app exposed a
run of engine bugs. Each is fixed where it lives:

SceneKit
- Viewport3D crashed on a Screen parent (Screen has no Node2D).
- Model3D discarded Material.BlendMode: an unset node override read back as
  -1 through an unsigned parameter and replaced the material's mode.
- Camera projection: drop the 1.05 FOV fudge and convert horizontal FOV
  correctly (same fix as b45c771); give Fov/ZNear/ZFar usable defaults.
- PrefabView3D loaded its prefab twice at startup.
- TextBlock3D gets a Color property instead of always drawing white.

Core / renderer
- AnimationPlayer stalled after its first frame, and the frame clock never
  advanced on app-loop paints, so clips could not play in a running app.
- Setting AnimationPlayer.CurrentTime while stopped now applies the clip, so
  a clip can be scrubbed from an input value.
- vec2/vec3/vec4 uniforms fell through into the int case and were corrupted.
- Shader BlendMode/DepthTestFunction/DepthWriteEnabled became uniforms and
  never reached the draw call.
- Render-pass tags were never registered.
- CDATA text content in XML was dropped.
- Texture_Create crashed without a GL context (headless tests).

Tools and docs
- orca-fbx: honour arguments, create the output directory, write vertex
  colours, compile against current headers and FBX SDK 2020.2; add a
  `make orca-fbx` target and fix the premake project.
- create-app.py generates package.lua (package.xml is no longer loaded).
- QUICKSTART and docs/animations.md match what the loader accepts.

Adds a headless test for AnimationPlayer scrubbing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tools/blender-export.py runs inside Blender and writes an ORCA project's 3D
assets from the open file: meshes (FBX through orca-fbx), one Shader per
shader node group with a "<group>.frag" text block, one Material per Blender
material (uniforms read from the group node's inputs), AnimationClips from
actions, a scene prefab with one AnimationPlayer per clip, and a first-time
package.lua and screen.

apps/cluster-demo is its first output: a 1920x720 digital instrument cluster
built procedurally in Blender (blender/build_cluster.py, blender/cluster.blend).
Every gauge has a linear fill-up clip; the app drives a gauge by setting its
player's CurrentTime, and Animations.lua names each clip's signal and range.
Demo/FillAll.xml scrubs all gauges together as a stand-in for real inputs.

.mesh files are ignored by .gitignore, so Meshes/ only carries the <Mesh>
declarations; run the exporter to regenerate the binary meshes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CI has failed on main since the SVG loader rework: three tests still
described code that no longer exists.
- test_filesystem.c tested _ParseLoaderArgs, removed with the .svg loader;
  keep only the inline-XML expansion test so the binary links again.
- test_layout.lua expected the removed "&type=mask" icon query and an
  ImageView in IconCard; both are VectorView now. The CSS popup test
  expected a centred panel to stretch; align-items: center sizes it to its
  content, so assert that instead.
- test_navigationhost.lua looked for "GameBack"; the back control moved into
  the NavigationBar prefab as "BackButton".

Add two skills, .opencode/skills/orca-blender-pipeline (authoring a Blender
scene so tools/blender-export.py can turn it into a project) and
.opencode/skills/orca-3d-scene (project layout, scene XML, shaders and
uniforms, animation players scrubbed from inputs, running and verifying),
and expose all skills to Claude Code and Codex through .claude/skills and
.agents/skills symlinks. AGENTS.md lists them; apps/cluster-demo/README.md
explains the reference project. Ignore Blender's *.blend1 backups.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@corepunch
corepunch merged commit 11bfc57 into main Oct 3, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant