OverviewFilesCommitsIssuesDocsReleasesPeers

blender-bridge commits / 27c1521

Fix B3+B5: remove dead texture_id code, disable SVT material
- Remove texture_id writes from _export_node, _detect_and_push_changes, and change_detector.py flush (total 3 write sites) - Remove texture_id read and SVT material conditional from import_changes - Revert material blob from 48 to 44 bytes in scene_import.py - Remove dead _texture_lookup, set_texture_lookup, mark_texture_objects_dirty - Always use StandardMaterial3D (SVT returns in Phase 2 with per-texture pages) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
27c152180236039a480b4b923c77a97aec497529
by plankatron <fleeky@gmail.com> · 2026-03-04T18:04:09.000Z

Changed files (4) +15 -100

blender_addon/__init__.py +0 -12
……@@ -219,9 +219,6 @@ def _poll_timer_impl(generation: int):
219219 # Bake immediately so tiles flow on this tick
220220 _baker.bake_full_image(img_name)
221221 print(f"BlenderBridge: Baked texture '{img_name}'")
222 # Re-flush objects using this texture so texture_id is sent
223 if _detector is not None:
224 _detector.mark_texture_objects_dirty(img_name)
225222
226223 # Flush accumulated Blender changes to SHM and notify Godot
227224 if _detector is not None:
……@@ -301,16 +298,10 @@ def _attempt_reconnect():
301298 _detector._geometry_hashes.clear() # Force re-detect all geometry
302299 _detector.register()
303300 _detector.set_resize_callback(_on_shm_resized)
304 _detector.set_texture_lookup(
305 lambda name: _baker._texture_ids.get(name, 0) if _baker else 0
306 )
307301 else:
308302 _detector = ChangeDetector(_shm, MAX_OBJECTS)
309303 _detector.register()
310304 _detector.set_resize_callback(_on_shm_resized)
311 _detector.set_texture_lookup(
312 lambda name: _baker._texture_ids.get(name, 0) if _baker else 0
313 )
314305
315306 # Reuse existing baker to preserve _texture_ids (prevents re-requesting
316307 # all textures on reconnect). Only update SHM reference and ring buffer.
……@@ -472,9 +463,6 @@ class BRIDGE_OT_connect(bpy.types.Operator):
472463 tile_ring_size = TILE_RING_SIZE
473464 _baker = TileBaker(_shm, tile_size=128, max_mips=8)
474465 _baker.init_ring_buffer(tile_ring_offset, tile_ring_size)
475 _detector.set_texture_lookup(
476 lambda name: _baker._texture_ids.get(name, 0) if _baker else 0
477 )
478466
479467 # Set up non-blocking procedural baker
480468 _proc_baker = ProceduralBaker()
blender_addon/change_detector.py +0 -44
……@@ -104,8 +104,6 @@ class ChangeDetector:
104104 self._had_shading_update = False
105105 # Callback for notifying Godot of SHM resize: fn(new_size, new_region_size)
106106 self._resize_callback = None
107 # Callback to resolve image name → VT texture_id (0 = not registered)
108 self._texture_lookup = None
109107
110108 def register(self):
111109 """Register the depsgraph handler."""
……@@ -186,35 +184,6 @@ class ChangeDetector:
186184 """Set a callback for SHM resize notifications: callback(new_size, new_region_size)."""
187185 self._resize_callback = callback
188186
189 def set_texture_lookup(self, callback):
190 """Set a callback to resolve image name → VT texture_id (0 = not registered)."""
191 self._texture_lookup = callback
192
193 def mark_texture_objects_dirty(self, image_name: str):
194 """Mark all objects using a texture image for UPDATE_FULL re-flush.
195
196 Called when a texture_id becomes available after registration,
197 so the material blob includes the correct texture_id.
198 """
199 if bpy is None:
200 return
201 for obj in bpy.data.objects:
202 if obj.type != "MESH" or obj.active_material is None:
203 continue
204 mat = obj.active_material
205 if not mat.use_nodes or not mat.node_tree:
206 continue
207 for node in mat.node_tree.nodes:
208 if node.type != "BSDF_PRINCIPLED":
209 continue
210 bc_input = node.inputs.get("Base Color")
211 if bc_input and bc_input.is_linked:
212 from_node = bc_input.links[0].from_node
213 if (from_node.type == "TEX_IMAGE" and from_node.image
214 and from_node.image.name == image_name):
215 self._pending[obj.name] = UPDATE_FULL
216 break
217
218187 @staticmethod
219188 def _hash_transform(mat) -> int:
220189 """FNV-1a hash of 4×4 matrix floats for change detection."""
……@@ -741,19 +710,6 @@ class ChangeDetector:
741710 blob_abs_offset += written
742711 blob_rel_offset += written
743712
744 # Write texture_id (uint32): 0 = no texture, >0 = VT texture ID
745 tex_id = 0
746 if self._texture_lookup is not None:
747 bc_input = bsdf.inputs.get("Base Color")
748 if bc_input and bc_input.is_linked:
749 from_node = bc_input.links[0].from_node
750 if from_node.type == "TEX_IMAGE" and from_node.image:
751 tex_id = self._texture_lookup(from_node.image.name)
752 self._shm.write_blob(
753 blob_abs_offset, struct.pack("<I", tex_id)
754 )
755 blob_abs_offset += 4
756 blob_rel_offset += 4
757713 if not has_mat:
758714 self._shm.write_blob(
759715 blob_abs_offset, struct.pack("<I", 0)
blender_addon/scene_import.py +2 -4
……@@ -296,13 +296,12 @@ class SceneImporter:
296296 if cursor + 4 <= data_end:
297297 has_material = struct.unpack("<I", bytes(self._shm._mm[cursor:cursor + 4]))[0]
298298 cursor += 4
299 if has_material and cursor + 48 <= data_end:
299 if has_material and cursor + 44 <= data_end:
300300 mat_data = np.frombuffer(
301301 bytes(self._shm._mm[cursor:cursor + 44]),
302302 dtype=np.float32,
303303 )
304304 cursor += 44
305 cursor += 4 # skip texture_id (VT, not used in Blender)
306305 self._apply_material_to_mesh(mesh, mat_data)
307306
308307 obj = bpy.data.objects.new(mesh.name, mesh)
……@@ -512,11 +511,10 @@ class SceneImporter:
512511 if cursor + 4 <= data_end:
513512 has_material = struct.unpack("<I", bytes(self._shm._mm[cursor:cursor + 4]))[0]
514513 cursor += 4
515 if has_material and cursor + 48 <= data_end:
514 if has_material and cursor + 44 <= data_end:
516515 mat_data = np.frombuffer(
517516 bytes(self._shm._mm[cursor:cursor + 44]),
518517 dtype=np.float32,
519518 )
520519 cursor += 44
521 cursor += 4 # skip texture_id (VT, not used in Blender)
522520 self._apply_material_to_mesh(mesh, mat_data)
src/blender_bridge.cpp +13 -40
……@@ -570,10 +570,6 @@ uint32_t BlenderBridge::_export_node(Node3D *node, uint32_t index, uint8_t *blob
570570 mat_data[10] = std_mat->get_emission_energy_multiplier();
571571 memcpy(blob_base + blob_offset, mat_data, 44);
572572 blob_offset += 44;
573 // texture_id = 0 (Godot-origin meshes have no VT texture)
574 uint32_t tex_id = 0;
575 memcpy(blob_base + blob_offset, &tex_id, 4);
576 blob_offset += 4;
577573 } else {
578574 uint32_t has_material = 0;
579575 memcpy(blob_base + blob_offset, &has_material, 4);
……@@ -1085,48 +1081,28 @@ void BlenderBridge::import_changes(Node *root) {
10851081 memcpy(&has_material, base + cursor, 4);
10861082 cursor += 4;
10871083 }
1088 if (has_material && cursor + 48 <= data_end) {
1084 if (has_material && cursor + 44 <= data_end) {
10891085 float mat_data[11];
10901086 memcpy(mat_data, base + cursor, 44);
10911087 cursor += 44;
10921088
1093 uint32_t texture_id = 0;
1094 memcpy(&texture_id, base + cursor, 4);
1095 cursor += 4;
1096
10971089 Color albedo(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
10981090 float roughness_val = mat_data[4];
10991091 float metallic_val = mat_data[5];
11001092
1101 // Apply VT material if this mesh has a registered texture
1102 bool used_vt = false;
1103 if (texture_id > 0 && !_virtual_texture_path.is_empty()) {
1104 Node *vt_node = get_node_or_null(_virtual_texture_path);
1105 VirtualTexture *vt = Object::cast_to<VirtualTexture>(vt_node);
1106 if (vt) {
1107 Ref<ShaderMaterial> vt_mat = vt->create_vt_material(albedo, roughness_val, metallic_val);
1108 if (vt_mat.is_valid()) {
1109 mesh_inst->set_surface_override_material(0, vt_mat);
1110 used_vt = true;
1111 }
1112 }
1113 }
1114
1115 // Fallback: StandardMaterial3D with flat colors
1116 if (!used_vt) {
1117 Ref<StandardMaterial3D> std_mat;
1118 std_mat.instantiate();
1119 std_mat->set_albedo(albedo);
1120 std_mat->set_roughness(roughness_val);
1121 std_mat->set_metallic(metallic_val);
1122 Color emission(mat_data[6], mat_data[7], mat_data[8], mat_data[9]);
1123 if (emission.r > 0.0f || emission.g > 0.0f || emission.b > 0.0f) {
1124 std_mat->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
1125 std_mat->set_emission(emission);
1126 std_mat->set_emission_energy_multiplier(mat_data[10]);
1127 }
1128 mesh_inst->set_surface_override_material(0, std_mat);
1093 // StandardMaterial3D with Blender PBR properties
1094 Ref<StandardMaterial3D> std_mat;
1095 std_mat.instantiate();
1096 std_mat->set_albedo(albedo);
1097 std_mat->set_roughness(roughness_val);
1098 std_mat->set_metallic(metallic_val);
1099 Color emission(mat_data[6], mat_data[7], mat_data[8], mat_data[9]);
1100 if (emission.r > 0.0f || emission.g > 0.0f || emission.b > 0.0f) {
1101 std_mat->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
1102 std_mat->set_emission(emission);
1103 std_mat->set_emission_energy_multiplier(mat_data[10]);
11291104 }
1105 mesh_inst->set_surface_override_material(0, std_mat);
11301106 }
11311107
11321108 }
……@@ -1578,9 +1554,6 @@ void BlenderBridge::_detect_and_push_changes() {
15781554 mat_data[10] = std_mat->get_emission_energy_multiplier();
15791555 memcpy(base + blob_offset, mat_data, 44);
15801556 blob_offset += 44;
1581 uint32_t tex_id = 0;
1582 memcpy(base + blob_offset, &tex_id, 4);
1583 blob_offset += 4;
15841557 } else {
15851558 uint32_t has_material = 0;
15861559 memcpy(base + blob_offset, &has_material, 4);