kopia lustrzana https://github.com/OpenDroneMap/ODM
PoC GLB write
rodzic
b29a4f1a70
commit
75c8068836
|
@ -0,0 +1,212 @@
|
|||
import os
|
||||
import rasterio
|
||||
import warnings
|
||||
import numpy as np
|
||||
import pygltflib
|
||||
|
||||
warnings.filterwarnings("ignore", category=rasterio.errors.NotGeoreferencedWarning)
|
||||
|
||||
def load_obj(obj_path, _info=print):
|
||||
if not os.path.isfile(obj_path):
|
||||
raise IOError("Cannot open %s" % obj_path)
|
||||
|
||||
obj_base_path = os.path.dirname(os.path.abspath(obj_path))
|
||||
obj = {
|
||||
'materials': {},
|
||||
}
|
||||
vertices = []
|
||||
uvs = []
|
||||
normals = []
|
||||
|
||||
faces = {}
|
||||
current_material = "_"
|
||||
|
||||
with open(obj_path) as f:
|
||||
_info("Loading %s" % obj_path)
|
||||
|
||||
for line in f:
|
||||
if line.startswith("mtllib "):
|
||||
# Materials
|
||||
mtl_file = "".join(line.split()[1:]).strip()
|
||||
obj['materials'].update(load_mtl(mtl_file, obj_base_path, _info=_info))
|
||||
elif line.startswith("v "):
|
||||
# Vertices
|
||||
vertices.append(list(map(float, line.split()[1:4])))
|
||||
elif line.startswith("vt "):
|
||||
# UVs
|
||||
uvs.append(list(map(float, line.split()[1:3])))
|
||||
elif line.startswith("vn "):
|
||||
normals.append(list(map(float, line.split()[1:4])))
|
||||
elif line.startswith("usemtl "):
|
||||
mtl_name = "".join(line.split()[1:]).strip()
|
||||
if not mtl_name in obj['materials']:
|
||||
raise Exception("%s material is missing" % mtl_name)
|
||||
|
||||
current_material = mtl_name
|
||||
elif line.startswith("f "):
|
||||
if current_material not in faces:
|
||||
faces[current_material] = []
|
||||
|
||||
a,b,c = line.split()[1:]
|
||||
|
||||
if a.count("/") == 2:
|
||||
av, at, an = map(int, a.split("/")[0:3])
|
||||
bv, bt, bn = map(int, b.split("/")[0:3])
|
||||
cv, ct, cn = map(int, c.split("/")[0:3])
|
||||
|
||||
faces[current_material].append((av - 1, bv - 1, cv - 1, at - 1, bt - 1, ct - 1, an - 1, bn - 1, cn - 1))
|
||||
else:
|
||||
av, at = map(int, a.split("/")[0:2])
|
||||
bv, bt = map(int, b.split("/")[0:2])
|
||||
cv, ct = map(int, c.split("/")[0:2])
|
||||
faces[current_material].append((av - 1, bv - 1, cv - 1, at - 1, bt - 1, ct - 1))
|
||||
|
||||
obj['vertices'] = np.array(vertices, dtype=np.float32)
|
||||
obj['uvs'] = np.array(uvs, dtype=np.float32)
|
||||
obj['normals'] = np.array(normals, dtype=np.float32)
|
||||
obj['faces'] = faces
|
||||
|
||||
return obj
|
||||
|
||||
def load_mtl(mtl_file, obj_base_path, _info=print):
|
||||
mtl_file = os.path.join(obj_base_path, mtl_file)
|
||||
|
||||
if not os.path.isfile(mtl_file):
|
||||
raise IOError("Cannot open %s" % mtl_file)
|
||||
|
||||
mats = {}
|
||||
current_mtl = ""
|
||||
|
||||
with open(mtl_file) as f:
|
||||
for line in f:
|
||||
if line.startswith("newmtl "):
|
||||
current_mtl = "".join(line.split()[1:]).strip()
|
||||
elif line.startswith("map_Kd ") and current_mtl:
|
||||
map_kd_filename = "".join(line.split()[1:]).strip()
|
||||
map_kd = os.path.join(obj_base_path, map_kd_filename)
|
||||
if not os.path.isfile(map_kd):
|
||||
raise IOError("Cannot open %s" % map_kd)
|
||||
|
||||
_info("Loading %s" % map_kd_filename)
|
||||
|
||||
mats[current_mtl] = True
|
||||
# with rasterio.open(map_kd, 'r') as r:
|
||||
# mats[current_mtl] = r.read()
|
||||
return mats
|
||||
|
||||
|
||||
def obj2glb(input_obj, output_glb, _info=print):
|
||||
obj = load_obj(input_obj, _info=_info)
|
||||
|
||||
vertices = obj['vertices']
|
||||
uvs = obj['uvs']
|
||||
|
||||
vertices_blob = vertices.tobytes()
|
||||
uvs_blob = uvs.tobytes()
|
||||
|
||||
faces = obj['faces']['material0000']
|
||||
# TODO: all faces
|
||||
|
||||
faces = np.array(faces, dtype=np.uint32)
|
||||
|
||||
#faces = faces[:2] # TODO REMOVE
|
||||
#print(faces)
|
||||
|
||||
indices = faces[:,0:3]
|
||||
uv_indices = faces[:,3:6]
|
||||
if faces.shape[1] == 9:
|
||||
normal_indices = faces[:,6:9]
|
||||
else:
|
||||
normal_indices = None
|
||||
|
||||
#faces_blob = faces.tobytes()
|
||||
|
||||
indices_blob = indices.tobytes()
|
||||
uv_indices_blob = uv_indices.tobytes()
|
||||
|
||||
bin = vertices_blob + uvs_blob + indices_blob + uv_indices_blob
|
||||
|
||||
gltf = pygltflib.GLTF2(
|
||||
scene=0,
|
||||
scenes=[pygltflib.Scene(nodes=[0])],
|
||||
nodes=[pygltflib.Node(mesh=0)],
|
||||
meshes=[
|
||||
pygltflib.Mesh(
|
||||
primitives=[
|
||||
pygltflib.Primitive(
|
||||
attributes=pygltflib.Attributes(POSITION=0, TEXCOORD_0=1), indices=2
|
||||
)
|
||||
]
|
||||
)
|
||||
],
|
||||
accessors=[
|
||||
pygltflib.Accessor(
|
||||
bufferView=0,
|
||||
componentType=pygltflib.FLOAT,
|
||||
count=len(vertices),
|
||||
type=pygltflib.VEC3,
|
||||
max=vertices.max(axis=0).tolist(),
|
||||
min=vertices.min(axis=0).tolist(),
|
||||
),
|
||||
pygltflib.Accessor(
|
||||
bufferView=1,
|
||||
componentType=pygltflib.FLOAT,
|
||||
count=len(uvs),
|
||||
type=pygltflib.VEC2,
|
||||
max=uvs.max(axis=0).tolist(),
|
||||
min=uvs.min(axis=0).tolist(),
|
||||
),
|
||||
pygltflib.Accessor(
|
||||
bufferView=2,
|
||||
componentType=pygltflib.UNSIGNED_INT,
|
||||
count=len(indices),
|
||||
type=pygltflib.SCALAR,
|
||||
max=[int(indices.max())],
|
||||
min=[int(indices.min())],
|
||||
),
|
||||
pygltflib.Accessor(
|
||||
bufferView=3,
|
||||
componentType=pygltflib.UNSIGNED_INT,
|
||||
count=len(uv_indices),
|
||||
type=pygltflib.SCALAR,
|
||||
max=[int(uv_indices.max())],
|
||||
min=[int(uv_indices.min())],
|
||||
),
|
||||
],
|
||||
bufferViews=[
|
||||
pygltflib.BufferView(
|
||||
buffer=0,
|
||||
byteLength=len(vertices_blob),
|
||||
target=pygltflib.ARRAY_BUFFER,
|
||||
),
|
||||
pygltflib.BufferView(
|
||||
buffer=0,
|
||||
byteOffset=len(vertices_blob),
|
||||
byteLength=len(uvs_blob),
|
||||
target=pygltflib.ARRAY_BUFFER,
|
||||
),
|
||||
pygltflib.BufferView(
|
||||
buffer=0,
|
||||
byteOffset=len(vertices_blob) + len(uvs_blob),
|
||||
byteLength=len(indices_blob),
|
||||
target=pygltflib.ELEMENT_ARRAY_BUFFER,
|
||||
),
|
||||
pygltflib.BufferView(
|
||||
buffer=0,
|
||||
byteOffset=len(vertices_blob) + len(uvs_blob) + len(indices_blob),
|
||||
byteLength=len(uv_indices_blob),
|
||||
target=pygltflib.ELEMENT_ARRAY_BUFFER,
|
||||
),
|
||||
],
|
||||
buffers=[
|
||||
pygltflib.Buffer(
|
||||
byteLength=len(bin)
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
gltf.set_binary_blob(bin)
|
||||
|
||||
gltf.save(output_glb)
|
||||
print("OK")
|
||||
|
Ładowanie…
Reference in New Issue