The x-angle transformation for LAYER3 slabs assumed SweptArea
is always IfcArbitraryClosedProfileDef (which has OuterCurve),
but composite profiles use IfcCompositeProfileDef instead.
Apply the coord scaling to each sub-profile individually.
Generated with the assistance of an AI coding tool.
generate_section_reference_points had no handler for
MODEL_VIEW target view, causing it to silently return
None. Add MODEL_VIEW branch that clips the section line
to XY camera bounds while preserving the Z coordinate
for correct 3D placement.
Generated with the assistance of an AI coding tool.
Guard the int() cast on CardinalPoint in
BIM_OT_edit_assigned_material so a None value (no cardinal
point set) no longer raises a TypeError.
Generated with the assistance of an AI coding tool.
Extracted from the font file like so:
python3 -c "
from fontTools.ttLib import TTFont
tt = TTFont('src/bonsai/bonsai/bim/data/fonts/OpenGost Type B TT.ttf')
for record in tt['name'].names:
if record.nameID == 13:
print(record.toUnicode())
"
Wire up wgpu init + scene load + RAF render so the embedded sample
sidecar paints on the canvas in both browsers.
Root-cause fix: BufferPool::addSubBuffer spin-waited on
PopErrorScope, which resolves via JS microtask on Dawn-web. The
spin blocked the JS event loop, so the microtask never fired and
the first allocation hung the page indefinitely. Skip the
error-scope dance on Emscripten; trust the buffer pointer.
ViewportCore: add initWgpuAsyncWeb (nested-callback adapter→device
chain with AllowSpontaneous mode, no spin) and loadSidecarFromPath
(Qt-free entry point). waitTickInstance becomes a no-op shim on
web; cull-threads / streaming_thread_ / wgpuSurfacePresent gated
off; chunk I/O runs inline.
main_web.cpp: AppState + initWgpuAsyncWeb → buildPipelines (+
HiZ/edge/pick) → loadSidecarFromPath → ready flag → Module._app_ptr
handoff. The RAF loop lives in shell.html (NOT here) because any
RAF helper called from inside Dawn-web's wgpu Promise.then chain
stalls the device callback.
CMakeLists.txt: EXIT_RUNTIME=0 + Module.noExitRuntime=true (shell)
keeps wasm alive past main() so the device promise lands; no
Asyncify; export _raf_tick_c so shell.html's RAF can call it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1) Async-wait spin loops in initWgpu / probeAndCreatePool / pick /
screenshot finalize all called wgpuInstanceProcessEvents in a tight
while. wgpu-native drives queued callbacks from there; Dawn-web
queues the callback for an event-loop tick that never happens
because wasm doesn't yield back to JS. Page hung at the first
await (RequestAdapter) and Firefox flagged the tab as slow.
New `waitTickInstance` helper calls emscripten_sleep(0) on
Emscripten (Asyncify unwinds wasm, JS resolves WebGPU promises,
resume) before wgpuInstanceProcessEvents drains completions into
our callback. Desktop path is unchanged. All five
`while (!done) ProcessEvents` sites switch to the helper.
2) streaming_thread_.start() inside initWgpu spawns a std::thread.
On Emscripten that needs -pthread + COOP/COEP headers from the
hosting page. None of that is wired yet, so the start is gated
`#if !defined(__EMSCRIPTEN__)`. The sync chunk-load fallback
already inside driveStreamingLoads carries the load until #88
replaces it with emscripten_fetch.
3) wgpuSurfacePresent at the end of render() aborted with
"wgpuSurfacePresent is unsupported (use requestAnimationFrame via
html5.h instead)" — Dawn-web composites the canvas at the end of
the RAF tick automatically. Call skipped on Emscripten;
WebViewportHost::requestFrame is the RAF-tick driver.
Page now loads, brings up wgpu, configures the surface, and renders
one frame with the configured background. The frame log in the
status overlay shows the first-frame startup spike (~1000 fps from
a 1 ms tick); subsequent frames are paint-on-demand, which on the
empty scene means no frames at all — consistent with the desktop
event-driven model.
Replaces the standalone wgpu-only clear-color spike in main_web.cpp
with a real WebViewportHost implementation: surface creation via the
emdawnwebgpu canvas-selector source, framebufferSize through
emscripten_get_element_css_size + dpr, requestFrame as a deferred
flag the RAF main_loop consumes, quit through emscripten_force_exit.
main_web.cpp now does the same lifecycle the desktop initWgpu shell
does: core_.initWgpu(web_limits=true) → buildPipelines → buildHiz/
Edge/Pick. The render loop runs core_.render() once per RAF tick when
the host has flagged a frame pending, with a surface reconfigure on
size changes.
Builds clean under emcc 6.0 + emdawnwebgpu (1.4 MB wasm, 278 KB JS
glue). Renders an empty scene with the configured background — the
plumbing is end-to-end through the same ViewportCore code path the
desktop build uses. No sidecar load yet: that lands with the
emscripten_fetch streaming backend (#88).