Beispiel #1
0
    def create_object(self, progress: ProgressReport,
                      collection: bpy.types.Collection,
                      manager: import_manager.ImportManager)->None:
        # create object
        if self.gltf_node.mesh != -1:
            self.blender_object = bpy.data.objects.new(
                self.name, manager.meshes[self.gltf_node.mesh][0])
        else:
            # empty
            self.blender_object = bpy.data.objects.new(self.name, None)
            self.blender_object.empty_display_size = 0.1
            # self.blender_object.empty_draw_type = 'PLAIN_AXES'
        collection.objects.link(self.blender_object)
        self.blender_object.select_set("SELECT")

        self.blender_object['js'] = json.dumps(self.gltf_node.js, indent=2)

        # parent
        if self.parent:
            self.blender_object.parent = self.parent.blender_object

        if self.gltf_node.translation:
            self.blender_object.location = manager.mod_v(
                self.gltf_node.translation)

        if self.gltf_node.rotation:
            r = self.gltf_node.rotation
            q = mathutils.Quaternion((r[3], r[0], r[1], r[2]))
            with tmp_mode(self.blender_object, 'QUATERNION'):
                self.blender_object.rotation_quaternion = manager.mod_q(q)

        if self.gltf_node.scale:
            s = self.gltf_node.scale
            self.blender_object.scale = (s[0], s[2], s[1])

        if self.gltf_node.matrix:
            m = self.gltf_node.matrix
            matrix = mathutils.Matrix((
                (m[0], m[4], m[8], m[12]),
                (m[1], m[5], m[9], m[13]),
                (m[2], m[6], m[10], m[14]),
                (m[3], m[7], m[11], m[15])
            ))
            t, q, s = matrix.decompose()
            self.blender_object.location = manager.mod_v(t)
            with tmp_mode(self.blender_object, 'QUATERNION'):
                self.blender_object.rotation_quaternion = manager.mod_q(q)
            self.blender_object.scale = (s[0], s[2], s[1])

        progress.step()

        for child in self.children:
            child.create_object(progress, collection, manager)
Beispiel #2
0
def _create_mesh(
        progress: ProgressReport, manager: ImportManager, mesh: gltftypes.Mesh
) -> Tuple[bpy.types.Mesh, gltf_buffer.VertexBuffer]:
    blender_mesh = bpy.data.meshes.new(mesh.name)
    materials = [manager.materials[prim.material] for prim in mesh.primitives]
    for m in materials:
        blender_mesh.materials.append(m)

    attributes = gltf_buffer.VertexBuffer(manager, mesh)

    blender_mesh.vertices.add(len(attributes.pos) / 3)
    blender_mesh.vertices.foreach_set("co", attributes.pos)
    blender_mesh.vertices.foreach_set("normal", attributes.nom)

    blender_mesh.loops.add(len(attributes.indices))
    blender_mesh.loops.foreach_set("vertex_index", attributes.indices)

    triangle_count = int(len(attributes.indices) / 3)
    blender_mesh.polygons.add(triangle_count)
    starts = [i * 3 for i in range(triangle_count)]
    blender_mesh.polygons.foreach_set("loop_start", starts)
    total = [3 for _ in range(triangle_count)]
    blender_mesh.polygons.foreach_set("loop_total", total)

    blen_uvs = blender_mesh.uv_layers.new()
    for blen_poly in blender_mesh.polygons:
        blen_poly.use_smooth = True
        blen_poly.material_index = attributes.get_submesh_from_face(
            blen_poly.index)
        for lidx in blen_poly.loop_indices:
            index = attributes.indices[lidx]
            # vertex uv to face uv
            uv = attributes.uv[index]
            blen_uvs.data[lidx].uv = (uv.x, uv.y)  # vertical flip uv

    # *Very* important to not remove lnors here!
    blender_mesh.validate(clean_customdata=False)
    blender_mesh.update()

    progress.step()
    return blender_mesh, attributes
Beispiel #3
0
def load_objects(context, progress: ProgressReport,
                 manager: ImportManager) -> Tuple[List[Node], Node]:
    progress.enter_substeps(len(manager.gltf.nodes) + 1, "Loading objects...")

    # collection
    view_layer = context.view_layer
    if view_layer.collections.active:
        collection = view_layer.collections.active.collection
    else:
        collection = context.scene.master_collection.new()
        view_layer.collections.link(collection)

    # setup
    nodes = [
        Node(i, gltf_node) for i, gltf_node in enumerate(manager.gltf.nodes)
    ]

    # set parents
    for gltf_node, node in zip(manager.gltf.nodes, nodes):
        for child_index in gltf_node.children:
            child = nodes[child_index]
            node.children.append(child)
            child.parent = node

    progress.step()

    # check root
    roots = [node for node in enumerate(nodes) if not node[1].parent]
    if len(roots) != 1:
        root = Node(len(nodes), gltftypes.Node({'name': '__root__'}))
        for _, node in roots:
            root.children.append(node)
            node.parent = root
    else:
        root = nodes[0]
    root.create_object(progress, collection, manager)

    def get_root(skin: gltftypes.Skin) -> Optional[Node]:

        root = None

        for joint in skin.joints:
            node = nodes[joint]
            if not root:
                root = node
            else:
                if node in root.get_ancestors():
                    root = node

        return root

    # create armatures
    root_skin = gltftypes.Skin({'name': 'skin'})

    for skin in manager.gltf.skins:
        for joint in skin.joints:
            if joint not in root_skin.joints:
                root_skin.joints.append(joint)
    skeleton = get_root(root_skin)

    if skeleton:
        skeleton.create_armature(context, collection, view_layer, root_skin)

    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    progress.leave_substeps()
    return (nodes, root)
Beispiel #4
0
def _create_material(progress: ProgressReport, manager: ImportManager,
                     material: gltftypes.Material) -> bpy.types.Material:
    blender_material = bpy.data.materials.new(material.name)
    blender_material['js'] = json.dumps(material.js, indent=2)

    blender_material.use_nodes = True
    tree = blender_material.node_tree

    tree.nodes.remove(tree.nodes['Principled BSDF'])

    getLogger('').disabled = True
    groups = blender_groupnode_io.import_groups(gltf_pbr_node.groups)
    getLogger('').disabled = False

    bsdf = tree.nodes.new('ShaderNodeGroup')
    bsdf.node_tree = groups['glTF Metallic Roughness']

    tree.links.new(bsdf.outputs['Shader'],
                   tree.nodes['Material Output'].inputs['Surface'])

    def create_image_node(texture_index: int):
        # uv => tex
        image_node = tree.nodes.new(type='ShaderNodeTexImage')
        image_node.image = manager.textures[texture_index]
        tree.links.new(
            tree.nodes.new('ShaderNodeTexCoord').outputs['UV'],
            image_node.inputs['Vector'])
        return image_node

    def bsdf_link_image(texture_index: int, input_name: str):
        texture = create_image_node(texture_index)
        tree.links.new(texture.outputs["Color"], bsdf.inputs[input_name])

    if material.normalTexture:
        bsdf_link_image(material.normalTexture.index, 'Normal')

    if material.occlusionTexture:
        bsdf_link_image(material.occlusionTexture.index, 'Occlusion')

    if material.emissiveTexture:
        bsdf_link_image(material.emissiveTexture.index, 'Emissive')

    pbr = material.pbrMetallicRoughness
    if pbr:
        if pbr.baseColorTexture and pbr.baseColorFactor:
            # mix
            mix = tree.nodes.new(type='ShaderNodeMixRGB')
            mix.blend_type = 'MULTIPLY'
            mix.inputs[2].default_value = pbr.baseColorFactor

        elif pbr.baseColorTexture:
            bsdf_link_image(pbr.baseColorTexture.index, 'BaseColor')
        else:
            # factor
            pass

        if pbr.metallicRoughnessTexture:
            bsdf_link_image(pbr.metallicRoughnessTexture.index,
                            'MetallicRoughness')

    progress.step()
    return blender_material