Created
September 12, 2022 00:01
-
-
Save ranjian0/3aa0ebeb54c2075ea5408828235b29ba to your computer and use it in GitHub Desktop.
Blender Extract Unique Indices from GLTF export
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Blender's GLTF exporter does some splitting of blender verts based on loops i.e in my case a mesh with 386 verts ends up with | |
441 verts after gltf export. | |
As explained at https://blender.stackexchange.com/questions/167372/gltf-export-has-twice-the-vertices-it-should | |
glTF is a last mile format and stores mesh data in a "Ready to load on GPU" state. | |
This script basically predetermines how the export will split the vertices and produces all the vertex | |
indices that will exist in the final gltf data. | |
XXX Caution | |
This script only considers the influence of the UVs (which is unique to my use case). If you are exporting other attributes such as | |
normals and tangents please add the necessary `dot_fields` and `dot` data as has been done at | |
https://git.blender.org/gitweb/gitweb.cgi/blender-addons.git/blob/HEAD:/io_scene_gltf2/blender/exp/gltf2_blender_extract.py in the | |
`extract_primitives` function. | |
""" | |
import bpy | |
import bmesh | |
import numpy as np | |
def get_gltf_export_indices(obj): | |
def __get_uvs(blender_mesh, uv_i): | |
layer = blender_mesh.uv_layers[uv_i] | |
uvs = np.empty(len(blender_mesh.loops) * 2, dtype=np.float32) | |
layer.data.foreach_get('uv', uvs) | |
uvs = uvs.reshape(len(blender_mesh.loops), 2) | |
# Blender UV space -> glTF UV space | |
# u,v -> u,1-v | |
uvs[:, 1] *= -1 | |
uvs[:, 1] += 1 | |
return uvs | |
# Get the active mesh | |
me = obj.data | |
tex_coord_max = len(me.uv_layers) | |
dot_fields = [('vertex_index', np.uint32)] | |
for uv_i in range(tex_coord_max): | |
dot_fields += [('uv%dx' % uv_i, np.float32), ('uv%dy' % uv_i, np.float32)] | |
dots = np.empty(len(me.loops), dtype=np.dtype(dot_fields)) | |
vidxs = np.empty(len(me.loops)) | |
me.loops.foreach_get('vertex_index', vidxs) | |
dots['vertex_index'] = vidxs | |
del vidxs | |
for uv_i in range(tex_coord_max): | |
uvs = __get_uvs(me, uv_i) | |
dots['uv%dx' % uv_i] = uvs[:, 0] | |
dots['uv%dy' % uv_i] = uvs[:, 1] | |
del uvs | |
# Calculate triangles and sort them into primitives. | |
me.calc_loop_triangles() | |
loop_indices = np.empty(len(me.loop_triangles) * 3, dtype=np.uint32) | |
me.loop_triangles.foreach_get('loops', loop_indices) | |
prim_indices = {} # maps material index to TRIANGLES-style indices into dots | |
# Bucket by material index. | |
tri_material_idxs = np.empty(len(me.loop_triangles), dtype=np.uint32) | |
me.loop_triangles.foreach_get('material_index', tri_material_idxs) | |
loop_material_idxs = np.repeat(tri_material_idxs, 3) # material index for every loop | |
unique_material_idxs = np.unique(tri_material_idxs) | |
del tri_material_idxs | |
for material_idx in unique_material_idxs: | |
prim_indices[material_idx] = loop_indices[loop_material_idxs == material_idx] | |
prim_dots = dots[prim_indices[0]] | |
prim_dots, indices = np.unique(prim_dots, return_inverse=True) | |
result = [d[0] for d in prim_dots] | |
return result | |
get_gltf_export_indices(bpy.context.object) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment