Spaces:
mashroo
/
Running on Zero

YoussefAnso commited on
Commit
4bc1108
·
1 Parent(s): 841251d

Add vertex color support in Mesh class and update GLB export in CRM model. Enhance mesh attributes and material handling for vertex colors, ensuring proper integration in GLTF format.

Browse files
Files changed (2) hide show
  1. mesh.py +60 -10
  2. model/crm/model.py +12 -4
mesh.py CHANGED
@@ -611,20 +611,56 @@ class Mesh:
611
  blob = f_np_blob + v_np_blob
612
  byteOffset = len(blob)
613
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  # base mesh
615
  gltf = pygltflib.GLTF2(
616
  scene=0,
617
  scenes=[pygltflib.Scene(nodes=[0])],
618
  nodes=[pygltflib.Node(mesh=0)],
619
  meshes=[pygltflib.Mesh(primitives=[pygltflib.Primitive(
620
- # indices to accessors (0 is triangles)
621
- attributes=pygltflib.Attributes(
622
- POSITION=1,
623
- ),
624
  indices=0,
625
  )])],
626
  buffers=[
627
- pygltflib.Buffer(byteLength=len(f_np_blob) + len(v_np_blob))
628
  ],
629
  # buffer view (based on dtype)
630
  bufferViews=[
@@ -632,22 +668,22 @@ class Mesh:
632
  pygltflib.BufferView(
633
  buffer=0,
634
  byteLength=len(f_np_blob),
635
- target=pygltflib.ELEMENT_ARRAY_BUFFER, # GL_ELEMENT_ARRAY_BUFFER (34963)
636
  ),
637
  # positions; as vec3 array
638
  pygltflib.BufferView(
639
  buffer=0,
640
  byteOffset=len(f_np_blob),
641
  byteLength=len(v_np_blob),
642
- byteStride=12, # vec3
643
- target=pygltflib.ARRAY_BUFFER, # GL_ARRAY_BUFFER (34962)
644
  ),
645
  ],
646
  accessors=[
647
  # 0 = triangles
648
  pygltflib.Accessor(
649
  bufferView=0,
650
- componentType=pygltflib.UNSIGNED_INT, # GL_UNSIGNED_INT (5125)
651
  count=f_np.size,
652
  type=pygltflib.SCALAR,
653
  max=[int(f_np.max())],
@@ -656,7 +692,7 @@ class Mesh:
656
  # 1 = positions
657
  pygltflib.Accessor(
658
  bufferView=1,
659
- componentType=pygltflib.FLOAT, # GL_FLOAT (5126)
660
  count=len(v_np),
661
  type=pygltflib.VEC3,
662
  max=v_np.max(axis=0).tolist(),
@@ -665,6 +701,20 @@ class Mesh:
665
  ],
666
  )
667
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
  # append texture info
669
  if self.vt is not None:
670
 
 
611
  blob = f_np_blob + v_np_blob
612
  byteOffset = len(blob)
613
 
614
+ # Create attributes dictionary
615
+ attributes = pygltflib.Attributes(POSITION=1)
616
+ accessor_count = 2 # Start after position (0) and indices (1)
617
+
618
+ # Add vertex colors if they exist
619
+ if self.vc is not None:
620
+ vc_np = self.vc.detach().cpu().numpy().astype(np.float32)
621
+ vc_np_blob = vc_np.tobytes()
622
+
623
+ # Add vertex color buffer view
624
+ gltf.bufferViews.append(
625
+ pygltflib.BufferView(
626
+ buffer=0,
627
+ byteOffset=byteOffset,
628
+ byteLength=len(vc_np_blob),
629
+ byteStride=12, # vec3
630
+ target=pygltflib.ARRAY_BUFFER,
631
+ )
632
+ )
633
+
634
+ # Add vertex color accessor
635
+ gltf.accessors.append(
636
+ pygltflib.Accessor(
637
+ bufferView=accessor_count,
638
+ componentType=pygltflib.FLOAT,
639
+ count=len(vc_np),
640
+ type=pygltflib.VEC3,
641
+ max=vc_np.max(axis=0).tolist(),
642
+ min=vc_np.min(axis=0).tolist(),
643
+ )
644
+ )
645
+
646
+ # Add to attributes
647
+ attributes.COLOR_0 = accessor_count
648
+ accessor_count += 1
649
+
650
+ blob += vc_np_blob
651
+ byteOffset += len(vc_np_blob)
652
+
653
  # base mesh
654
  gltf = pygltflib.GLTF2(
655
  scene=0,
656
  scenes=[pygltflib.Scene(nodes=[0])],
657
  nodes=[pygltflib.Node(mesh=0)],
658
  meshes=[pygltflib.Mesh(primitives=[pygltflib.Primitive(
659
+ attributes=attributes,
 
 
 
660
  indices=0,
661
  )])],
662
  buffers=[
663
+ pygltflib.Buffer(byteLength=byteOffset)
664
  ],
665
  # buffer view (based on dtype)
666
  bufferViews=[
 
668
  pygltflib.BufferView(
669
  buffer=0,
670
  byteLength=len(f_np_blob),
671
+ target=pygltflib.ELEMENT_ARRAY_BUFFER,
672
  ),
673
  # positions; as vec3 array
674
  pygltflib.BufferView(
675
  buffer=0,
676
  byteOffset=len(f_np_blob),
677
  byteLength=len(v_np_blob),
678
+ byteStride=12, # vec3
679
+ target=pygltflib.ARRAY_BUFFER,
680
  ),
681
  ],
682
  accessors=[
683
  # 0 = triangles
684
  pygltflib.Accessor(
685
  bufferView=0,
686
+ componentType=pygltflib.UNSIGNED_INT,
687
  count=f_np.size,
688
  type=pygltflib.SCALAR,
689
  max=[int(f_np.max())],
 
692
  # 1 = positions
693
  pygltflib.Accessor(
694
  bufferView=1,
695
+ componentType=pygltflib.FLOAT,
696
  count=len(v_np),
697
  type=pygltflib.VEC3,
698
  max=v_np.max(axis=0).tolist(),
 
701
  ],
702
  )
703
 
704
+ # Add material for vertex colors
705
+ if self.vc is not None:
706
+ gltf.materials.append(pygltflib.Material(
707
+ pbrMetallicRoughness=pygltflib.PbrMetallicRoughness(
708
+ baseColorFactor=[1.0, 1.0, 1.0, 1.0],
709
+ metallicFactor=0.0,
710
+ roughnessFactor=1.0,
711
+ ),
712
+ alphaMode=pygltflib.OPAQUE,
713
+ alphaCutoff=None,
714
+ doubleSided=True,
715
+ ))
716
+ gltf.meshes[0].primitives[0].material = 0
717
+
718
  # append texture info
719
  if self.vt is not None:
720
 
model/crm/model.py CHANGED
@@ -102,13 +102,21 @@ class CRM(nn.Module):
102
  verts[..., 0]*= -1
103
  verts[..., 2]*= -1
104
  verts = verts.squeeze().cpu().numpy()
105
- faces = faces[..., [2, 1, 0]][..., [0, 2, 1]]#[..., [1, 0, 2]]
106
- faces = faces.squeeze().cpu().numpy()#faces[..., [2, 1, 0]].squeeze().cpu().numpy()
107
 
108
  # export the final mesh
109
  with torch.no_grad():
110
- mesh = trimesh.Trimesh(verts, faces, vertex_colors=colors, process=False) # important, process=True leads to seg fault...
111
- mesh.export(f'{out_dir}.obj')
 
 
 
 
 
 
 
 
112
 
113
  def export_mesh_wt_uv(self, ctx, data, out_dir, ind, device, res, tri_fea_2=None):
114
 
 
102
  verts[..., 0]*= -1
103
  verts[..., 2]*= -1
104
  verts = verts.squeeze().cpu().numpy()
105
+ faces = faces[..., [2, 1, 0]][..., [0, 2, 1]]
106
+ faces = faces.squeeze().cpu().numpy()
107
 
108
  # export the final mesh
109
  with torch.no_grad():
110
+ # Create a Mesh object with the data
111
+ from mesh import Mesh
112
+ mesh = Mesh(
113
+ v=torch.from_numpy(verts).float(),
114
+ f=torch.from_numpy(faces).int(),
115
+ vc=torch.from_numpy(colors).float(),
116
+ device='cpu'
117
+ )
118
+ # Write as GLB
119
+ mesh.write(out_dir)
120
 
121
  def export_mesh_wt_uv(self, ctx, data, out_dir, ind, device, res, tri_fea_2=None):
122