kopia lustrzana https://github.com/OpenDroneMap/ODM
Single primitive rendering with textures
rodzic
cda8f227b1
commit
7be182b6d5
230
opendm/gltf.py
230
opendm/gltf.py
|
@ -62,11 +62,6 @@ def load_obj(obj_path, _info=print):
|
||||||
cv, ct = map(int, c.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))
|
faces[current_material].append((av - 1, bv - 1, cv - 1, at - 1, bt - 1, ct - 1))
|
||||||
|
|
||||||
if len(vertices) > len(uvs):
|
|
||||||
# Pad with empty UV coordinates
|
|
||||||
add_uvs = len(vertices) - len(uvs)
|
|
||||||
uvs += [[0,0]] * add_uvs
|
|
||||||
|
|
||||||
obj['vertices'] = np.array(vertices, dtype=np.float32)
|
obj['vertices'] = np.array(vertices, dtype=np.float32)
|
||||||
obj['uvs'] = np.array(uvs, dtype=np.float32)
|
obj['uvs'] = np.array(uvs, dtype=np.float32)
|
||||||
obj['normals'] = np.array(normals, dtype=np.float32)
|
obj['normals'] = np.array(normals, dtype=np.float32)
|
||||||
|
@ -96,142 +91,143 @@ def load_mtl(mtl_file, obj_base_path, _info=print):
|
||||||
_info("Loading %s" % map_kd_filename)
|
_info("Loading %s" % map_kd_filename)
|
||||||
|
|
||||||
with MemoryFile() as memfile:
|
with MemoryFile() as memfile:
|
||||||
with rasterio.open(map_kd, 'r') as r:
|
with rasterio.open(map_kd, 'r') as src:
|
||||||
mats[current_mtl] = r.read()
|
data = src.read()
|
||||||
# TODO: copy code from export-rgb (webodm)
|
with memfile.open(driver='JPEG', jpeg_quality=90, count=3, width=src.width, height=src.height, dtype=rasterio.dtypes.uint8) as dst:
|
||||||
|
for b in range(1, min(3, src.count) + 1):
|
||||||
|
# TODO: convert if uint16 or float
|
||||||
|
dst.write(data[b - 1], b)
|
||||||
|
memfile.seek(0)
|
||||||
|
mats[current_mtl] = memfile.read()
|
||||||
return mats
|
return mats
|
||||||
|
|
||||||
|
def paddedBuffer(buf, boundary):
|
||||||
|
r = len(buf) % boundary
|
||||||
|
if r == 0:
|
||||||
|
return buf
|
||||||
|
pad = boundary - r
|
||||||
|
return buf + b'\x00' * pad
|
||||||
|
|
||||||
def obj2glb(input_obj, output_glb, _info=print):
|
def obj2glb(input_obj, output_glb, _info=print):
|
||||||
|
_info("Converting %s --> %s" % (input_obj, output_glb))
|
||||||
obj = load_obj(input_obj, _info=_info)
|
obj = load_obj(input_obj, _info=_info)
|
||||||
|
|
||||||
vertices = obj['vertices']
|
vertices = obj['vertices']
|
||||||
uvs = obj['uvs']
|
uvs = obj['uvs']
|
||||||
|
# Flip Y
|
||||||
|
uvs = (([0, 1] - (uvs * [0, 1])) + uvs * [1, 0]).astype(np.float32)
|
||||||
normals = obj['normals']
|
normals = obj['normals']
|
||||||
|
|
||||||
vertices_blob = vertices.tobytes()
|
binary = b''
|
||||||
uvs_blob = uvs.tobytes()
|
accessors = []
|
||||||
|
bufferViews = []
|
||||||
|
primitives = []
|
||||||
|
materials = []
|
||||||
|
textures = []
|
||||||
|
images = []
|
||||||
|
|
||||||
faces = obj['faces']['material0000']
|
bufOffset = 0
|
||||||
material = obj['materials']['material0000']
|
def addBufferView(buf, target=None):
|
||||||
print(material.shape)
|
nonlocal bufferViews, bufOffset
|
||||||
print(material.)
|
bufferViews += [pygltflib.BufferView(
|
||||||
exit(1)
|
buffer=0,
|
||||||
# TODO: all faces
|
byteOffset=bufOffset,
|
||||||
|
byteLength=len(buf),
|
||||||
|
target=target,
|
||||||
|
)]
|
||||||
|
bufOffset += len(buf)
|
||||||
|
return len(bufferViews) - 1
|
||||||
|
|
||||||
faces = np.array(faces, dtype=np.uint32)
|
for material in obj['faces'].keys():
|
||||||
|
faces = obj['faces'][material]
|
||||||
|
texture_blob = paddedBuffer(obj['materials'][material], 4)
|
||||||
|
|
||||||
indices = faces[:,0:3].flatten()
|
faces = np.array(faces, dtype=np.uint32)
|
||||||
uv_indices = faces[:,3:6].flatten()
|
|
||||||
|
|
||||||
if faces.shape[1] == 9:
|
prim_vertices = vertices[faces[:,0:3].flatten()]
|
||||||
normal_indices = faces[:,6:9].flatten()
|
prim_uvs = uvs[faces[:,3:6].flatten()]
|
||||||
else:
|
|
||||||
normal_indices = None
|
|
||||||
|
|
||||||
#faces_blob = faces.tobytes()
|
if faces.shape[1] == 9:
|
||||||
|
prim_normals = normals[faces[:,6:9].flatten()]
|
||||||
|
normals_blob = prim_normals.tobytes()
|
||||||
|
else:
|
||||||
|
prim_normals = None
|
||||||
|
normals_blob = None
|
||||||
|
|
||||||
indices_blob = indices.tobytes()
|
vertices_blob = prim_vertices.tobytes()
|
||||||
uv_indices_blob = uv_indices.tobytes()
|
uvs_blob = prim_uvs.tobytes()
|
||||||
|
|
||||||
binary = vertices_blob + uvs_blob + indices_blob + uv_indices_blob
|
binary += vertices_blob + uvs_blob
|
||||||
|
if normals_blob is not None:
|
||||||
|
binary += normals_blob
|
||||||
|
binary += texture_blob
|
||||||
|
|
||||||
|
verticesBufferView = addBufferView(vertices_blob, pygltflib.ARRAY_BUFFER)
|
||||||
|
uvsBufferView = addBufferView(uvs_blob, pygltflib.ARRAY_BUFFER)
|
||||||
|
if normals_blob is not None:
|
||||||
|
normalsBufferView = addBufferView(normals_blob, pygltflib.ARRAY_BUFFER)
|
||||||
|
textureBufferView = addBufferView(texture_blob)
|
||||||
|
|
||||||
|
accessors += [
|
||||||
|
pygltflib.Accessor(
|
||||||
|
bufferView=verticesBufferView,
|
||||||
|
componentType=pygltflib.FLOAT,
|
||||||
|
count=len(prim_vertices),
|
||||||
|
type=pygltflib.VEC3,
|
||||||
|
max=prim_vertices.max(axis=0).tolist(),
|
||||||
|
min=prim_vertices.min(axis=0).tolist(),
|
||||||
|
),
|
||||||
|
pygltflib.Accessor(
|
||||||
|
bufferView=uvsBufferView,
|
||||||
|
componentType=pygltflib.FLOAT,
|
||||||
|
count=len(prim_uvs),
|
||||||
|
type=pygltflib.VEC2,
|
||||||
|
max=prim_uvs.max(axis=0).tolist(),
|
||||||
|
min=prim_uvs.min(axis=0).tolist(),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
if prim_normals is not None:
|
||||||
|
accessors += [
|
||||||
|
pygltflib.Accessor(
|
||||||
|
bufferView=normalsBufferView,
|
||||||
|
componentType=pygltflib.FLOAT,
|
||||||
|
count=len(prim_normals),
|
||||||
|
type=pygltflib.VEC3,
|
||||||
|
max=prim_normals.max(axis=0).tolist(),
|
||||||
|
min=prim_normals.min(axis=0).tolist(),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
images += [pygltflib.Image(bufferView=textureBufferView, mimeType="image/jpeg")]
|
||||||
|
textures += [pygltflib.Texture(source=len(images) - 1, sampler=0)]
|
||||||
|
materials += [pygltflib.Material(pbrMetallicRoughness=pygltflib.PbrMetallicRoughness(baseColorTexture=pygltflib.TextureInfo(index=0), metallicFactor=0, roughnessFactor=1),
|
||||||
|
alphaMode=pygltflib.MASK)]
|
||||||
|
primitives += [pygltflib.Primitive(
|
||||||
|
attributes=pygltflib.Attributes(POSITION=verticesBufferView, TEXCOORD_0=uvsBufferView), material=len(materials) - 1
|
||||||
|
)]
|
||||||
|
if len(primitives) == 2:
|
||||||
|
break
|
||||||
|
|
||||||
gltf = pygltflib.GLTF2(
|
gltf = pygltflib.GLTF2(
|
||||||
scene=0,
|
scene=0,
|
||||||
scenes=[pygltflib.Scene(nodes=[0])],
|
scenes=[pygltflib.Scene(nodes=[0])],
|
||||||
nodes=[pygltflib.Node(mesh=0)],
|
nodes=[pygltflib.Node(mesh=0)],
|
||||||
meshes=[
|
meshes=[pygltflib.Mesh(
|
||||||
pygltflib.Mesh(
|
primitives=primitives
|
||||||
primitives=[
|
)],
|
||||||
pygltflib.Primitive(
|
materials=materials,
|
||||||
attributes=pygltflib.Attributes(POSITION=0, TEXCOORD_0=1), indices=2, material=0
|
textures=textures,
|
||||||
)
|
samplers=[pygltflib.Sampler(magFilter=pygltflib.LINEAR, minFilter=pygltflib.LINEAR)],
|
||||||
]
|
images=images,
|
||||||
)
|
accessors=accessors,
|
||||||
],
|
bufferViews=bufferViews,
|
||||||
materials=[
|
buffers=[pygltflib.Buffer(byteLength=len(binary))],
|
||||||
|
|
||||||
],
|
|
||||||
textures=[
|
|
||||||
pygltflib.Texture(source=0, sampler=0)
|
|
||||||
],
|
|
||||||
images=[
|
|
||||||
pygltflib.Image(bufferView=0, mimeType="image/png") # TODO: use JPG
|
|
||||||
],
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
pygltflib.BufferView(
|
|
||||||
buffer=0,
|
|
||||||
byteOffset=len(vertices_blob) + len(uvs_blob) + len(indices_blob) + len(uv_indices_blob),
|
|
||||||
byteLength=len(texture_blob),
|
|
||||||
target=pygltflib.ARRAY_BUFFER
|
|
||||||
)
|
|
||||||
],
|
|
||||||
buffers=[
|
|
||||||
pygltflib.Buffer(
|
|
||||||
byteLength=len(binary)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
gltf.set_binary_blob(binary)
|
gltf.set_binary_blob(binary)
|
||||||
|
|
||||||
|
_info("Writing...")
|
||||||
gltf.save(output_glb)
|
gltf.save(output_glb)
|
||||||
print("OK")
|
_info("Wrote %s" % output_glb)
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue