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)
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
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)
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