50 lines
4.0 KiB
Python
50 lines
4.0 KiB
Python
"""Immutable-source evaluated geometry export, owner-selected complete v020."""
|
|
import bpy,json,hashlib,struct
|
|
from pathlib import Path
|
|
from mathutils import Vector,Matrix
|
|
root=Path.cwd();source=Path(bpy.data.filepath)
|
|
donor=root.parent/'NODEDC_ENGINE_INFRA/nodedc-source/public/3dassetnode/model.glb'
|
|
with donor.open('rb') as f:
|
|
f.read(12);n,t=struct.unpack('<II',f.read(8));donor_json=json.loads(f.read(n))
|
|
# Same physical PBR parameters as the drone's untextured metal/rubber/steel.
|
|
material_rules={'metal':1,'rubber':2,'steel':6,'paint':3}
|
|
materials={}
|
|
for kind,index in material_rules.items():
|
|
spec=donor_json['materials'][index]['pbrMetallicRoughness'];m=bpy.data.materials.new('NodeDC '+kind);m.use_nodes=True
|
|
bs=m.node_tree.nodes.get('Principled BSDF');bs.inputs['Base Color'].default_value=spec.get('baseColorFactor',[1,1,1,1]);bs.inputs['Metallic'].default_value=spec.get('metallicFactor',1);bs.inputs['Roughness'].default_value=spec.get('roughnessFactor',1);materials[kind]=m
|
|
source_scene=bpy.context.scene;source_scene.frame_set(1);dg=bpy.context.evaluated_depsgraph_get()
|
|
instances=[]
|
|
for inst in dg.object_instances:
|
|
o=inst.object;src=o.original;cols=[c.name for c in src.users_collection]
|
|
if o.type not in {'MESH','CURVE'} or src.hide_render:continue
|
|
if any(c.hide_render for c in src.users_collection) or any(('STUDIO' in c or 'BOOLEAN' in c or 'DATUM' in c) for c in cols):continue
|
|
# Exclude standalone instancing source collections; their placed instances survive.
|
|
if not inst.is_instance and not src.visible_get():continue
|
|
mesh=bpy.data.meshes.new_from_object(o,preserve_all_data_layers=True,depsgraph=dg)
|
|
names=[slot.material.name.lower() if slot.material else '' for slot in o.material_slots]
|
|
for idx in range(len(mesh.materials)):
|
|
name=names[idx] if idx<len(names) else ''
|
|
kind='rubber' if any(k in name for k in ['rubber','gasket','polymer','elastomer','jacket','asa']) else 'steel' if any(k in name for k in ['zinc','steel','brass','spring']) else 'paint' if any(k in name for k in ['paint','coated','black','charcoal']) else 'metal'
|
|
mesh.materials[idx]=materials[kind]
|
|
if not mesh.materials:mesh.materials.append(materials['metal'])
|
|
instances.append((src.name,mesh,inst.matrix_world.copy(),inst.is_instance))
|
|
scene=bpy.data.scenes.new('Mission Core rover export');bpy.context.window.scene=scene
|
|
objects=[]
|
|
for name,mesh,matrix,_ in instances:
|
|
o=bpy.data.objects.new(name,mesh);scene.collection.objects.link(o);o.matrix_world=matrix;objects.append(o)
|
|
bpy.context.view_layer.update()
|
|
lo=Vector((min((o.matrix_world@Vector(v))[i] for o in objects for v in o.bound_box) for i in range(3)))
|
|
hi=Vector((max((o.matrix_world@Vector(v))[i] for o in objects for v in o.bound_box) for i in range(3)))
|
|
shift=Vector((-(lo.x+hi.x)/2,-(lo.y+hi.y)/2,-lo.z))
|
|
for o in objects:o.matrix_world=Matrix.Translation(shift)@o.matrix_world
|
|
source_object_count=len(objects)
|
|
bpy.ops.object.select_all(action='SELECT')
|
|
bpy.context.view_layer.objects.active=objects[0]
|
|
bpy.ops.object.join()
|
|
joined=bpy.context.object
|
|
for uv in list(joined.data.uv_layers):joined.data.uv_layers.remove(uv)
|
|
out=root/'apps/control-station/public/rover-scene/dcd006-v020.glb'
|
|
bpy.ops.export_scene.gltf(filepath=str(out),export_format='GLB',use_selection=True,use_active_scene=True,export_animations=False,export_cameras=False,export_lights=False,export_extras=False,export_yup=True,export_apply=False,export_texcoords=False,export_attributes=False,export_vertex_color='NONE')
|
|
manifest={'source':source.name,'source_sha256':hashlib.sha256(source.read_bytes()).hexdigest(),'model':'DCD-006 v020 complete rover','source_object_count':source_object_count,'render_mesh_count':1,'original_bounds':[list(lo),list(hi)],'dimensions_m':list(hi-lo),'translation_m':list(shift),'glb_bytes':out.stat().st_size,'glb_sha256':hashlib.sha256(out.read_bytes()).hexdigest(),'material_source_sha256':hashlib.sha256(donor.read_bytes()).hexdigest(),'material_rules':material_rules,'source_saved':False}
|
|
(out.parent/'dcd006-v020.json').write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n');print(json.dumps(manifest))
|