Conversation
… Blender Popen(...).wait() blocked Blender's main thread for as long as CoACD took, with zero progress feedback and no way to cancel - on real-world non-manifold meshes that's multiple minutes even with default settings, which reads as a complete freeze. The CLI (both the main decomposition pass and the per-hull decimate pass) is now driven from bpy.app.timers, polled a step at a time, with a HUD status while it runs and Escape actually killing the subprocess.
…defaults A synchronously-frozen UI was an accidental guard against a user triggering Auto Convex (BETA) twice concurrently - now that it stays responsive during a run, nothing stopped a second invocation from racing the first on identically-named temp files. Adds a module-level lock (invoke() refuses a second run while one is active) plus unique per-run temp filenames as defense in depth, and makes sure the lock always gets released even if a job errors out unexpectedly. Also changes CoACD defaults: max hulls 16 (was -1/unlimited) and hull vertex cap 32 with decimation on by default (was 256, off) - unlimited hulls at full resolution is what made the original freeze so easy to hit.
"BETA" didn't communicate the actual tradeoff users need to know before choosing it over V-HACD: CoACD produces tighter, more precise hulls by searching for better cuts, but is significantly slower - the operator was never actually unstable, just slow and previously freeze-prone (#660). Renamed the operator label, panel/button text, and tooltips throughout to say so directly instead of "BETA", and updated the description text to call out the speed cost explicitly.
…iewport-less async step bpy.app.timers callbacks have no guaranteed context - bpy.context.space_data is None (or belongs to whatever editor the mouse happens to be over) unless the pointer is currently over this operator's own viewport, which is unlikely once a run takes minutes. postprocess_colliders() -> primitive_postprocessing() -> set_viewport_drawing() needs context.space_data.shading, so this crashed with AttributeError as soon as the mouse wasn't over the 3D viewport when the last subprocess finished - and since postprocess_colliders() processes hulls one at a time, every hull already handled before the crash kept its correct transform/parent/ modifiers, while every hull after it was left with its raw import-time transform and never parented. That's what looked like "some hulls get the right rotation/scale, others don't". Fixed by capturing a stable window/area/region in execute() and running every async completion step inside context.temp_override() with them, instead of trusting ambient bpy.context.
16 was already a big improvement over unlimited (-1), but Max Hulls is an output-count constraint rather than a search-quality one - tightening it further trims worst-case runtime without degrading individual cuts, unlike loosening threshold/MCTS params which would erode the precision this backend exists for.
Add [permissions].network declaration to match. Neither was previously declared/checked despite this addon already making a real network call on every register().
…s for speed Progress: pipe the subprocess's stdout through a background reader thread into a queue instead of letting it inherit the console - CoACD already prints phase headers and per-candidate percentages, they just weren't being read. _drain_progress_queue() parses them non-blockingly each poll so the HUD shows e.g. "DECOMPOSITION (MCTS) 87.5%" instead of just an elapsed-time counter, which is indistinguishable from being stuck on a multi-minute run. Defaults: measured four isolated runs of the same real (complex, non-manifold) asset at current settings. MCTS Depth 3->2 and Nodes 20->10 cut compute time ~38% (389s -> 239s) with no quality loss - concavity came out slightly better, not worse, because at 8 hulls the decomposition is already hull-count-constrained rather than search-constrained, so trimming the search doesn't cost precision that was being achieved anyway. Hausdorff Sampling Resolution only bought ~11% on its own; set to 1000, the lowest value the property's own range allows (tested at 200 via direct CLI, which is below the declared min and wasn't adopted here). Combined: 222s, a ~43% reduction from baseline with no measured quality regression.
…d status overlay while either backend runs The per-row settings HUD (D for decimate, S for shrink/inflate, etc.) kept drawing and looking interactive while a CoACD job was running, even though every one of those hotkeys is inert during a run (modal() swallows them - there's nothing to adjust until the job produces colliders). Replaced it with a dedicated, centered, warning-styled overlay (draw_async_job_overlay() in add_bounding_primitive.py) that fully replaces the settings HUD while an async job is active, and disappears back to the normal interactive HUD the moment it finishes - no separate step needed, since draw_viewport_overlay() just checks self._async_process each redraw. Extracted the reusable pieces both backends need into OBJECT_OT_add_bounding_object: _launch_async_process() (Popen with stdout piped through a daemon reader thread into a queue - splitting on '\r' as well as '\n', since V-HACD's progress lines are '\r'-delimited like a terminal progress bar, not '\n'-delimited like CoACD's) and _drain_async_progress() (drains that queue each poll via a _parse_progress_line() hook each operator overrides for its own CLI's output format). CoACD's own _launch_coacd_process/_drain_progress_queue were folded into these; its state renamed to the generic _async_process/_async_start_time so the shared overlay can findit via getattr() regardless of which backend is running. V-HACD itself gets the full #660 treatmeant: was still calling Popen.wait() synchronously (freezing Blender exactly like CoACD used to), now runs through the same bpy.app.timers poll loop, module-level run-in-progress lock, cancel handling, and context.temp_override() for its completion step. Simpler than CoACD's conversion since V-HACD has no per-hull decimate sub-stage - one subprocess per collider group, straight through to postprocessing. Verified: full test suite (11/11) against a real Blender instance: V-HACD command construction and its file-discovery logic (scans data_path for new .obj files, deliberately excluding per-hull numbered variants in favor of the combined decomp.obj) against the actual bundled executable; transform correctness (rotated + non-uniformly-scaled source object) by replicating postprocess_colliders()'s exact matrix_world/apply_transform logic and comparing the resulting world-space hull bounds against the source geometry; both backends' progress-line regexes against their real captured stdout output. Modal-operator dispatch itself (invoke() -> execute() -> timer-driven poll loop) couldn't be exercised in --background scripting - Blender skips invoke() and calls execute() directly in that mode - so that specific wiring relies on it being the same shared code path already exercised live for CoACD earlier in this work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.