Phase 6: pycvc.load_model binding + native (VTK-free) add_gltf - #160
Merged
Conversation
added 2 commits
July 26, 2026 22:07
Binds cvc::model into pycvc and switches the scene helper's glTF loader off VTK's vtkGLTFReader to libcvc's native Assimp path (completes the native mesh/image loading arc, Phases 1-6). - pycvc_model.i (new): pycvc.load_model(path) -> pycvc.model. Mirrors pycvc_image.i's direct-wrap style. model.meshes / model.materials are %template'd std::vector proxies exposed as properties; the nested model::mesh is lifted with %feature(flatnested) so meshes[i].geometry()/ .material/.name work. material.base_color()/emissive() return tuples and base_color_texture() a pycvc.image (boost::array + by-value image members are %ignore'd and re-exposed via distinct-named %extend aliased back to the natural name — the same-name-%extend-swallowed-by-%ignore gotcha). model.merged() -> geometry, model.extents() -> 6-tuple. load_model needs no app (read_model returns bare value types; read-only accessors tolerate a null context). - pycvc.i: %include pycvc_model.i after image/geometry are wrapped. - CMakeLists.txt: wire pycvc_model.i into pycvc.i's DEPENDS + register test_pycvc_model.py. - pymod_gl/scenes.py: add_gltf now loads via pycvc.load_model(path).merged() (one flattened single-color geometry, matching the previous look) and adds through the native scene path (add_child_geometry when parented, else addGraphics), setting the uniform material via the GeometryNode setters (setUseSingleColor/setColor/setOpacity/setAmbient/setDiffuse/setSpecular, all public + %include'd in pycvc_gl.i). Imports NO vtkGLTFReader. building_occupancy still rasterizes via VTK (separate offscreen concern). Verified: pycvc builds; test_pycvc_model 1/1 (assimp loads an OBJ+MTL+PNG -> mesh/UVs/material/texture, merged() flatten, bad-extension raise); 11 other core pycvc tests pass. add_gltf can't run without a live GL scene; smoke- checked (AST: no vtk import; every setter it calls is public in GeometryNode.h + %include'd). black -l100 + ruff clean.
Adversarial review flagged test_extents_is_six_tuple as toothless: the flat z=0 triangle fixture's bbox collapses to all-zeros, so asserting only len==6 + finiteness could not distinguish a correct extents_bbox marshaling from a swapped/transposed/default one. Add a non-planar tetra fixture (bbox x[0,2] y[0,3] z[0,4]) and assert the concrete (minx..maxz) values, so the (minx,miny,minz,maxx,maxy,maxz) order is actually proven. Passes 1/1.
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.
Completes the native mesh/image loading arc (Phases 1–6): binds
cvc::modelinto pycvc and switches the scene helper's glTF loader off VTK'svtkGLTFReaderto libcvc's native Assimp path.pycvc.load_model(Part A)New
bindings/pycvc/pycvc_model.i(direct-wrap, mirroringpycvc_image.i):pycvc.load_model(path)→pycvc.modelfor any Assimp-supported format (obj/ply/stl/fbx/gltf/glb/…).model.meshes/model.materials—%template'dstd::vectorproxies (indexable +len()), exposed as properties; nestedmodel::meshlifted via%feature(flatnested)someshes[i].geometry()/.material/.namework.material.base_color()/.emissive()→ tuples;.base_color_texture()→pycvc.image;.base_color_texture_path,.metallic,.roughness,.has_base_color_texture(). (boost::array + by-value image members%ignore'd and re-exposed via distinct-named%extendaliased back — the same-name-swallowed-by-%ignoregotcha.)model.merged()→geometry,model.extents()→ 6-tuple. No app needed.Native
add_gltf(Part B)pymod_gl/scenes.py:add_gltfnow doespycvc.load_model(path).merged()(one flattened single-color geometry — the demo renders a uniform-color city, matching the old look) and adds through the native scene path (add_child_geometrywhen parented, elseaddGraphics), setting the uniform material via the publicGeometryNodesetters. Imports novtkGLTFReader. (building_occupancystill rasterizes via VTK — a separate offscreen concern.)Verification
pycvcbuilds;test_pycvc_model1/1 (Assimp loads an OBJ+MTL+PNG → mesh / UVs / material / decoded texture;merged()flatten; bad-extension raises); 11 other core pycvc tests pass, no regressions. (Localpycvc_integrationfails only on a missing VTK OpenGL runtime lib when importingpycvc_gl— an env artifact, unrelated to this pycvc-module change; passes in CI's full VTK stack.)add_gltfneeds a live GL scene to run; smoke-checked (AST: no vtk import; every setter it calls is public inGeometryNode.hand%include'd inpycvc_gl.i). black -l100 + ruff clean.With this, both volrover's C++ (
read_geometry) and Python (load_model/geometry.load) load glTF/obj/fbx/… natively via libcvc.