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- mesh.py +60 -10
- 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 |
-
|
621 |
-
attributes=pygltflib.Attributes(
|
622 |
-
POSITION=1,
|
623 |
-
),
|
624 |
indices=0,
|
625 |
)])],
|
626 |
buffers=[
|
627 |
-
pygltflib.Buffer(byteLength=
|
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,
|
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,
|
643 |
-
target=pygltflib.ARRAY_BUFFER,
|
644 |
),
|
645 |
],
|
646 |
accessors=[
|
647 |
# 0 = triangles
|
648 |
pygltflib.Accessor(
|
649 |
bufferView=0,
|
650 |
-
componentType=pygltflib.UNSIGNED_INT,
|
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,
|
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]]
|
106 |
-
faces = faces.squeeze().cpu().numpy()
|
107 |
|
108 |
# export the final mesh
|
109 |
with torch.no_grad():
|
110 |
-
|
111 |
-
mesh
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|