diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2018-11-24 18:28:33 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2018-11-24 18:28:33 +0300 |
commit | b1f2133fa2849da272e9d8404f371220226ddaf1 (patch) | |
tree | 25db56e0f2211bd1059fe0e04e78430a6156e021 /io_scene_gltf2/blender/imp/gltf2_blender_mesh.py | |
parent | 8959f1798cfc86924493347304118c61bd5c7f7a (diff) |
Initial commit of glTF 2.0 importer/exporter
Official Khronos Group Blender glTF 2.0 importer and exporter.
glTF specification: https://github.com/KhronosGroup/glTF
The upstream repository can be found here:
https://github.com/KhronosGroup/glTF-Blender-IO
Reviewed By: Bastien, Campbell
Differential Revision: https://developer.blender.org/D3929
Diffstat (limited to 'io_scene_gltf2/blender/imp/gltf2_blender_mesh.py')
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_mesh.py | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py new file mode 100755 index 00000000..88396455 --- /dev/null +++ b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py @@ -0,0 +1,158 @@ +# Copyright 2018 The glTF-Blender-IO authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import bpy +import bmesh + +from .gltf2_blender_primitive import BlenderPrimitive +from ...io.imp.gltf2_io_binary import BinaryData +from ..com.gltf2_blender_conversion import loc_gltf_to_blender + + +class BlenderMesh(): + """Blender Mesh.""" + def __new__(cls, *args, **kwargs): + raise RuntimeError("%s should not be instantiated" % cls) + + @staticmethod + def create(gltf, mesh_idx, node_idx, parent): + """Mesh creation.""" + pymesh = gltf.data.meshes[mesh_idx] + + # Geometry + if pymesh.name: + mesh_name = pymesh.name + else: + mesh_name = "Mesh_" + str(mesh_idx) + + mesh = bpy.data.meshes.new(mesh_name) + verts = [] + edges = [] + faces = [] + for prim in pymesh.primitives: + verts, edges, faces = BlenderPrimitive.create(gltf, prim, verts, edges, faces) + + mesh.from_pydata(verts, edges, faces) + mesh.validate() + + pymesh.blender_name = mesh.name + + return mesh + + @staticmethod + def set_mesh(gltf, pymesh, mesh, obj): + """Set all data after mesh creation.""" + # Normals + offset = 0 + for prim in pymesh.primitives: + offset = BlenderPrimitive.set_normals(gltf, prim, mesh, offset) + + mesh.update() + + # manage UV + offset = 0 + for prim in pymesh.primitives: + offset = BlenderPrimitive.set_UV(gltf, prim, obj, mesh, offset) + + mesh.update() + + # Object and UV are now created, we can set UVMap into material + for prim in pymesh.primitives: + BlenderPrimitive.set_UV_in_mat(gltf, prim, obj) + + # Assign materials to mesh + offset = 0 + cpt_index_mat = 0 + bm = bmesh.new() + bm.from_mesh(obj.data) + bm.faces.ensure_lookup_table() + for prim in pymesh.primitives: + offset, cpt_index_mat = BlenderPrimitive.assign_material(gltf, prim, obj, bm, offset, cpt_index_mat) + + bm.to_mesh(obj.data) + bm.free() + + # Create shapekeys if needed + max_shape_to_create = 0 + for prim in pymesh.primitives: + if prim.targets: + if len(prim.targets) > max_shape_to_create: + max_shape_to_create = len(prim.targets) + + # Create basis shape key + if max_shape_to_create > 0: + obj.shape_key_add(name="Basis") + + for i in range(max_shape_to_create): + + obj.shape_key_add(name="target_" + str(i)) + + offset_idx = 0 + for prim in pymesh.primitives: + if prim.targets is None: + continue + if i >= len(prim.targets): + continue + + bm = bmesh.new() + bm.from_mesh(mesh) + + shape_layer = bm.verts.layers.shape[i + 1] + + pos = BinaryData.get_data_from_accessor(gltf, prim.targets[i]['POSITION']) + + for vert in bm.verts: + if vert.index not in range(offset_idx, offset_idx + prim.vertices_length): + continue + + shape = vert[shape_layer] + + co = loc_gltf_to_blender(list(pos[vert.index - offset_idx])) + shape.x = obj.data.vertices[vert.index].co.x + co[0] + shape.y = obj.data.vertices[vert.index].co.y + co[1] + shape.z = obj.data.vertices[vert.index].co.z + co[2] + + bm.to_mesh(obj.data) + bm.free() + offset_idx += prim.vertices_length + + # set default weights for shape keys, and names + if pymesh.weights is not None: + for i in range(max_shape_to_create): + if i < len(pymesh.weights): + obj.data.shape_keys.key_blocks[i + 1].value = pymesh.weights[i] + if gltf.data.accessors[pymesh.primitives[0].targets[i]['POSITION']].name is not None: + obj.data.shape_keys.key_blocks[i + 1].name = \ + gltf.data.accessors[pymesh.primitives[0].targets[i]['POSITION']].name + + # Apply vertex color. + vertex_color = None + offset = 0 + for prim in pymesh.primitives: + if 'COLOR_0' in prim.attributes.keys(): + # Create vertex color, once only per object + if vertex_color is None: + vertex_color = obj.data.vertex_colors.new("COLOR_0") + + color_data = BinaryData.get_data_from_accessor(gltf, prim.attributes['COLOR_0']) + + for poly in mesh.polygons: + for loop_idx in range(poly.loop_start, poly.loop_start + poly.loop_total): + vert_idx = mesh.loops[loop_idx].vertex_index + if vert_idx in range(offset, offset + prim.vertices_length): + cpt_idx = vert_idx - offset + vertex_color.data[loop_idx].color = color_data[cpt_idx][0:3] + # TODO : no alpha in vertex color + offset = offset + prim.vertices_length + |