def gather_node(blender_object, export_settings): if not __filter_node(blender_object, export_settings): return None node = gltf2_io.Node( camera=__gather_camera(blender_object, export_settings), children=__gather_children(blender_object, export_settings), extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=__gather_mesh(blender_object, export_settings), name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=__gather_skin(blender_object, export_settings), translation=None, weights=__gather_weights(blender_object, export_settings) ) node.translation, node.rotation, node.scale = __gather_trans_rot_scale(blender_object, export_settings) if export_settings[gltf2_blender_export_keys.YUP]: if blender_object.type == 'LIGHT' and export_settings[gltf2_blender_export_keys.LIGHTS]: correction_node = __get_correction_node(blender_object, export_settings) correction_node.extensions = {"KHR_lights_punctual": node.extensions["KHR_lights_punctual"]} del node.extensions["KHR_lights_punctual"] node.children.append(correction_node) if blender_object.type == 'CAMERA' and export_settings[gltf2_blender_export_keys.CAMERAS]: correction_node = __get_correction_node(blender_object, export_settings) correction_node.camera = node.camera node.children.append(correction_node) node.camera = None return node
def gather_node(vnode, export_settings): blender_object = vnode.blender_object skin = __gather_skin(vnode, blender_object, export_settings) node = gltf2_io.Node( camera=__gather_camera(blender_object, export_settings), children=__gather_children(vnode, blender_object, export_settings), extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=__gather_mesh(vnode, blender_object, export_settings), name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=skin, translation=None, weights=__gather_weights(blender_object, export_settings) ) # If node mesh is skined, transforms should be ignored at import, so no need to set them here if node.skin is None: node.translation, node.rotation, node.scale = __gather_trans_rot_scale(vnode, export_settings) export_user_extensions('gather_node_hook', export_settings, node, blender_object) vnode.node = node if node.skin is not None: vnode.skin = skin return node
def __gather_joints(blender_object, export_settings): # the skeletal hierarchy groups below a 'root' joint # TODO: add transform? torso = gltf2_io.Node( camera=None, children=[], extensions={}, extras=None, matrix=[], mesh=None, name="Skeleton_" + blender_object.name, rotation=None, scale=None, skin=None, translation=None, weights=None ) # build the hierarchy of nodes out of the bones for blender_bone in blender_object.pose.bones: torso.children.append(gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)) # joints is a flat list containing all nodes belonging to the skin joints = [] def __collect_joints(node): joints.append(node) for child in node.children: __collect_joints(child) __collect_joints(torso) return joints
def gather_joint_vnode(vnode, export_settings): """ Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes. :param blender_bone: a blender PoseBone :param export_settings: the settings for this export :return: a glTF2 node (acting as a joint) """ vtree = export_settings['vtree'] blender_object = vtree.nodes[vnode].blender_object blender_bone = vtree.nodes[vnode].blender_bone mat = vtree.nodes[ vtree.nodes[vnode].parent_uuid].matrix_world.inverted_safe( ) @ vtree.nodes[vnode].matrix_world trans, rot, sca = mat.decompose() trans = __convert_swizzle_location(trans, export_settings) rot = __convert_swizzle_rotation(rot, export_settings) sca = __convert_swizzle_scale(sca, export_settings) translation, rotation, scale = (None, None, None) if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0: translation = [trans[0], trans[1], trans[2]] if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0: rotation = [rot[1], rot[2], rot[3], rot[0]] if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0: scale = [sca[0], sca[1], sca[2]] # traverse into children children = [] for bone_uuid in [ c for c in vtree.nodes[vnode].children if vtree.nodes[c].blender_type == gltf2_blender_gather_tree.VExportNode.BONE ]: children.append(gather_joint_vnode(bone_uuid, export_settings)) # finally add to the joints array containing all the joints in the hierarchy node = gltf2_io.Node(camera=None, children=children, extensions=None, extras=__gather_extras(blender_bone, export_settings), matrix=None, mesh=None, name=blender_bone.name, rotation=rotation, scale=scale, skin=None, translation=translation, weights=None) export_user_extensions('gather_joint_hook', export_settings, node, blender_bone) vtree.nodes[vnode].node = node return node
def __gather_node(blender_object, library, blender_scene, dupli_object_parent, export_settings): children = __gather_children(blender_object, blender_scene, export_settings) # If blender_scene is None, we are coming from animation export # Check to know if object is exported is already done, so we don't check # again if object is instanced in scene : this check was already done when exporting object itself if not __filter_node(blender_object, blender_scene, export_settings): if children: pass else: return None node = gltf2_io.Node( camera=__gather_camera(blender_object, export_settings), children=children, extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=__gather_mesh(blender_object, library, export_settings), name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=__gather_skin(blender_object, export_settings), translation=None, weights=__gather_weights(blender_object, export_settings)) node.__blender_data = ('OBJECT', blender_object) # If node mesh is skined, transforms should be ignored at import, so no need to set them here # if node.skin is None: # While its not needed by the gltf2 spec, MSFS might still want to see it node.translation, node.rotation, node.scale = __gather_trans_rot_scale( blender_object, export_settings) if export_settings[gltf2_blender_export_keys.YUP]: # Checking node.extensions is making sure that the type of lamp is managed, and will be exported if blender_object.type == 'LIGHT' and export_settings[ gltf2_blender_export_keys.LIGHTS] and node.extensions: correction_node = __get_correction_node(blender_object, export_settings) correction_node.extensions = { "KHR_lights_punctual": node.extensions["KHR_lights_punctual"] } del node.extensions["KHR_lights_punctual"] node.children.append(correction_node) if blender_object.type == 'CAMERA' and export_settings[ gltf2_blender_export_keys.CAMERAS]: correction_node = __get_correction_node(blender_object, export_settings) correction_node.camera = node.camera node.children.append(correction_node) node.camera = None export_user_extensions('gather_node_hook', export_settings, node, blender_object) return node
def gather_joint(blender_bone, export_settings): """ Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes :param blender_bone: a blender PoseBone :param export_settings: the settings for this export :return: a glTF2 node (acting as a joint) """ axis_basis_change = mathutils.Matrix.Identity(4) if export_settings['gltf_yup']: axis_basis_change = mathutils.Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) # extract bone transform if blender_bone.parent is None: correction_matrix_local = gltf2_blender_math.multiply( axis_basis_change, blender_bone.bone.matrix_local) else: correction_matrix_local = gltf2_blender_math.multiply( blender_bone.parent.bone.matrix_local.inverted(), blender_bone.bone.matrix_local) matrix_basis = blender_bone.matrix_basis if export_settings['gltf_bake_skins']: gltf2_io_debug.print_console("WARNING", "glTF bake skins not supported") # matrix_basis = blender_object.convert_space(blender_bone, blender_bone.matrix, from_space='POSE', # to_space='LOCAL') trans, rot, sca = gltf2_blender_extract.decompose_transition( gltf2_blender_math.multiply(correction_matrix_local, matrix_basis), 'JOINT', export_settings) translation, rotation, scale = (None, None, None) if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0: translation = [trans[0], trans[1], trans[2]] if rot[0] != 0.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 1.0: rotation = [rot[0], rot[1], rot[2], rot[3]] if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0: scale = [sca[0], sca[1], sca[2]] # traverse into children children = [] for bone in blender_bone.children: children.append(gather_joint(bone, export_settings)) # finally add to the joints array containing all the joints in the hierarchy return gltf2_io.Node(camera=None, children=children, extensions=None, extras=None, matrix=None, mesh=None, name=blender_bone.name, rotation=rotation, scale=scale, skin=None, translation=translation, weights=None)
def gather_joint(blender_object, blender_bone, export_settings): """ Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes. :param blender_bone: a blender PoseBone :param export_settings: the settings for this export :return: a glTF2 node (acting as a joint) """ axis_basis_change = mathutils.Matrix.Identity(4) if export_settings[gltf2_blender_export_keys.YUP]: axis_basis_change = mathutils.Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) # extract bone transform if blender_bone.parent is None: correction_matrix_local = gltf2_blender_math.multiply(axis_basis_change, blender_bone.bone.matrix_local) else: correction_matrix_local = gltf2_blender_math.multiply( blender_bone.parent.bone.matrix_local.inverted(), blender_bone.bone.matrix_local) matrix_basis = blender_bone.matrix_basis trans, rot, sca = gltf2_blender_extract.decompose_transition( gltf2_blender_math.multiply(correction_matrix_local, matrix_basis), export_settings) translation, rotation, scale = (None, None, None) if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0: translation = [trans[0], trans[1], trans[2]] if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0: rotation = [rot[1], rot[2], rot[3], rot[0]] if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0: scale = [sca[0], sca[1], sca[2]] # traverse into children children = [] if export_settings["gltf_def_bones"] is False: for bone in blender_bone.children: children.append(gather_joint(blender_object, bone, export_settings)) else: _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_bone.id_data) if blender_bone.name in children_.keys(): for bone in children_[blender_bone.name]: children.append(gather_joint(blender_object, blender_bone.id_data.pose.bones[bone], export_settings)) # finally add to the joints array containing all the joints in the hierarchy return gltf2_io.Node( camera=None, children=children, extensions=None, extras=__gather_extras(blender_bone, export_settings), matrix=None, mesh=None, name=blender_bone.name, rotation=rotation, scale=scale, skin=None, translation=translation, weights=None )
def gather_joint(blender_object, blender_bone, export_settings): """ Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes. :param blender_bone: a blender PoseBone :param export_settings: the settings for this export :return: a glTF2 node (acting as a joint) """ translation, rotation, scale = __gather_trans_rot_scale( blender_object, blender_bone, export_settings) # traverse into children children = [] if export_settings["gltf_def_bones"] is False: for bone in blender_bone.children: children.append(gather_joint(blender_object, bone, export_settings)) else: _, children_, _ = gltf2_blender_gather_skins.get_bone_tree( None, blender_bone.id_data) if blender_bone.name in children_.keys(): for bone in children_[blender_bone.name]: children.append( gather_joint(blender_object, blender_bone.id_data.pose.bones[bone], export_settings)) # finally add to the joints array containing all the joints in the hierarchy node = gltf2_io.Node(camera=None, children=children, extensions=None, extras=__gather_extras(blender_bone, export_settings), matrix=None, mesh=None, name=blender_bone.name, rotation=rotation, scale=scale, skin=None, translation=translation, weights=None) node.__blender_data = ('BONE', blender_object, blender_bone.name) export_user_extensions('gather_joint_hook', export_settings, node, blender_bone) return node
def __gather_node(blender_object, blender_scene, export_settings): # If blender_scene is None, we are coming from animation export # Check to know if object is exported is already done, so we don't check # again if object is instanced in scene : this check was already done when exporting object itself if not __filter_node(blender_object, blender_scene, export_settings): return None node = gltf2_io.Node( camera=__gather_camera(blender_object, export_settings), children=__gather_children(blender_object, blender_scene, export_settings), extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=__gather_mesh(blender_object, export_settings), name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=__gather_skin(blender_object, export_settings), translation=None, weights=__gather_weights(blender_object, export_settings)) # If node mesh is skined, transforms should be ignored at import, so no need to set them here if node.skin is None: node.translation, node.rotation, node.scale = __gather_trans_rot_scale( blender_object, export_settings) if export_settings[gltf2_blender_export_keys.YUP]: # Checking node.extensions is making sure that the type of lamp is managed, and will be exported if blender_object.type == 'LIGHT' and export_settings[ gltf2_blender_export_keys.LIGHTS] and node.extensions: correction_node = __get_correction_node(blender_object, export_settings) correction_node.extensions = { "KHR_lights_punctual": node.extensions["KHR_lights_punctual"] } del node.extensions["KHR_lights_punctual"] node.children.append(correction_node) if blender_object.type == 'CAMERA' and export_settings[ gltf2_blender_export_keys.CAMERAS]: correction_node = __get_correction_node(blender_object, export_settings) correction_node.camera = node.camera node.children.append(correction_node) node.camera = None return node
def __get_correction_node(blender_object, export_settings): correction_quaternion = gltf2_blender_extract.convert_swizzle_rotation( Quaternion((1.0, 0.0, 0.0), math.radians(-90.0)), export_settings) correction_quaternion = [ correction_quaternion[1], correction_quaternion[2], correction_quaternion[3], correction_quaternion[0] ] return gltf2_io.Node(camera=None, children=None, extensions=None, extras=None, matrix=None, mesh=None, name=blender_object.name + '_Orientation', rotation=correction_quaternion, scale=None, skin=None, translation=None, weights=None)
def gather_node(blender_object, export_settings): if not __filter_node(blender_object, export_settings): return None node = gltf2_io.Node( camera=__gather_camera(blender_object, export_settings), children=__gather_children(blender_object, export_settings), extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=__gather_mesh(blender_object, export_settings), name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=__gather_skin(blender_object, export_settings), translation=None, weights=__gather_weights(blender_object, export_settings)) node.translation, node.rotation, node.scale = __gather_trans_rot_scale( blender_object, export_settings) return node
def gather_joint(blender_object, blender_bone, export_settings): """ Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes. :param blender_bone: a blender PoseBone :param export_settings: the settings for this export :return: a glTF2 node (acting as a joint) """ axis_basis_change = mathutils.Matrix.Identity(4) if export_settings[gltf2_blender_export_keys.YUP]: axis_basis_change = mathutils.Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) # extract bone transform if blender_bone.parent is None: correction_matrix_local = axis_basis_change @ blender_bone.bone.matrix_local else: correction_matrix_local = ( blender_bone.parent.bone.matrix_local.inverted_safe() @ blender_bone.bone.matrix_local ) if (blender_bone.bone.use_inherit_rotation == False or blender_bone.bone.inherit_scale != "FULL") and blender_bone.parent != None: rest_mat = (blender_bone.parent.bone.matrix_local.inverted_safe() @ blender_bone.bone.matrix_local) matrix_basis = (rest_mat.inverted_safe() @ blender_bone.parent.matrix.inverted_safe() @ blender_bone.matrix) else: matrix_basis = blender_bone.matrix matrix_basis = blender_object.convert_space(pose_bone=blender_bone, matrix=matrix_basis, from_space='POSE', to_space='LOCAL') trans, rot, sca = (correction_matrix_local @ matrix_basis).decompose() translation, rotation, scale = (None, None, None) if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0: translation = [trans[0], trans[1], trans[2]] if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0: rotation = [rot[1], rot[2], rot[3], rot[0]] if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0: scale = [sca[0], sca[1], sca[2]] # traverse into children children = [] if export_settings["gltf_def_bones"] is False: for bone in blender_bone.children: children.append(gather_joint(blender_object, bone, export_settings)) else: _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_bone.id_data) if blender_bone.name in children_.keys(): for bone in children_[blender_bone.name]: children.append(gather_joint(blender_object, blender_bone.id_data.pose.bones[bone], export_settings)) # finally add to the joints array containing all the joints in the hierarchy node = gltf2_io.Node( camera=None, children=children, extensions=None, extras=__gather_extras(blender_bone, export_settings), matrix=None, mesh=None, name=blender_bone.name, rotation=rotation, scale=scale, skin=None, translation=translation, weights=None ) export_user_extensions('gather_joint_hook', export_settings, node, blender_bone) return node
def __gather_node(blender_object, library, blender_scene, dupli_object_parent, export_settings): children = __gather_children(blender_object, blender_scene, export_settings) camera = None mesh = None skin = None weights = None # If blender_scene is None, we are coming from animation export # Check to know if object is exported is already done, so we don't check # again if object is instanced in scene : this check was already done when exporting object itself if not __filter_node(blender_object, blender_scene, export_settings): if children: # This node should be filtered out, but has un-filtered children present. # So, export this node, excluding its camera, mesh, skin, and weights. # The transformations and animations on this node will have visible effects on children. pass else: # This node is filtered out, and has no un-filtered children or descendants. return None else: # This node is being fully exported. camera = __gather_camera(blender_object, export_settings) mesh = __gather_mesh(blender_object, library, export_settings) skin = __gather_skin(blender_object, export_settings) weights = __gather_weights(blender_object, export_settings) node = gltf2_io.Node( camera=camera, children=children, extensions=__gather_extensions(blender_object, export_settings), extras=__gather_extras(blender_object, export_settings), matrix=__gather_matrix(blender_object, export_settings), mesh=mesh, name=__gather_name(blender_object, export_settings), rotation=None, scale=None, skin=skin, translation=None, weights=weights) # If node mesh is skined, transforms should be ignored at import, so no need to set them here if node.skin is None: node.translation, node.rotation, node.scale = __gather_trans_rot_scale( blender_object, export_settings) if export_settings[gltf2_blender_export_keys.YUP]: # Checking node.extensions is making sure that the type of lamp is managed, and will be exported if blender_object.type == 'LIGHT' and export_settings[ gltf2_blender_export_keys.LIGHTS] and node.extensions: correction_node = __get_correction_node(blender_object, export_settings) correction_node.extensions = { "KHR_lights_punctual": node.extensions["KHR_lights_punctual"] } del node.extensions["KHR_lights_punctual"] node.children.append(correction_node) if blender_object.type == 'CAMERA' and export_settings[ gltf2_blender_export_keys.CAMERAS]: correction_node = __get_correction_node(blender_object, export_settings) correction_node.camera = node.camera node.children.append(correction_node) node.camera = None export_user_extensions('gather_node_hook', export_settings, node, blender_object) return node
def add_neutral_bones(self): for n in [ n for n in self.nodes.values() if n.armature is not None and n.blender_type == VExportNode. OBJECT and hasattr(self.nodes[n.armature], "need_neutral_bone") ]: #all skin meshes objects where neutral bone is needed # First add a new node axis_basis_change = Matrix.Identity(4) if self.export_settings[gltf2_blender_export_keys.YUP]: axis_basis_change = Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) trans, rot, sca = axis_basis_change.decompose() translation, rotation, scale = (None, None, None) if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0: translation = [trans[0], trans[1], trans[2]] if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0: rotation = [rot[1], rot[2], rot[3], rot[0]] if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0: scale = [sca[0], sca[1], sca[2]] neutral_bone = gltf2_io.Node(camera=None, children=None, extensions=None, extras=None, matrix=None, mesh=None, name='neutral_bone', rotation=rotation, scale=scale, skin=None, translation=translation, weights=None) # Add it to child list of armature self.nodes[n.armature].node.children.append(neutral_bone) # Add it to joint list n.node.skin.joints.append(neutral_bone) # Need to add an InverseBindMatrix array = BinaryData.decode_accessor_internal( n.node.skin.inverse_bind_matrices) axis_basis_change = Matrix.Identity(4) if self.export_settings[gltf2_blender_export_keys.YUP]: axis_basis_change = Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) inverse_bind_matrix = (axis_basis_change @ self.nodes[ n.armature].matrix_world_armature).inverted_safe() matrix = [] for column in range(0, 4): for row in range(0, 4): matrix.append(inverse_bind_matrix[row][column]) array = np.append(array, np.array([matrix]), axis=0) binary_data = gltf2_io_binary_data.BinaryData.from_list( array.flatten(), gltf2_io_constants.ComponentType.Float) n.node.skin.inverse_bind_matrices = gltf2_blender_gather_accessors.gather_accessor( binary_data, gltf2_io_constants.ComponentType.Float, len(array.flatten()) // gltf2_io_constants.DataType.num_elements( gltf2_io_constants.DataType.Mat4), None, None, gltf2_io_constants.DataType.Mat4, self.export_settings)