def export_bounding_box(self, b_obj, block_parent): box_extends = self.calculate_box_extents(b_obj) n_bbox = types.create_ninode() block_parent.add_child(n_bbox) # set name, flags, translation, and radius n_bbox.name = "Bounding Box" n_bbox.flags = 4 trans = n_bbox.translation trans.x = (box_extends[0][0] + box_extends[0][1]) * 0.5 + b_obj.location[0] trans.y = (box_extends[1][0] + box_extends[1][1]) * 0.5 + b_obj.location[1] trans.z = (box_extends[2][0] + box_extends[2][1]) * 0.5 + b_obj.location[2] n_bbox.rotation.set_identity() n_bbox.has_bounding_box = True # Ninode's(n_bbox) behaves like a seperate mesh. # bounding_box center(n_bbox.bounding_box.trans) is relative to the bound_box n_bbox.bounding_box.translation.deepcopy(trans) n_bbox.bounding_box.rotation.set_identity() largest = self.calculate_largest_value(box_extends) radius = n_bbox.bounding_box.radius radius.x = largest[0] radius.y = largest[1] radius.z = largest[2]
def export_root_node(self, root_objects, filebase): """ Exports a nif's root node; use blender root if there is only one, else create a meta root """ # TODO [collsion] detect root collision -> root collision node (can be mesh or empty) # self.nif_export.collisionhelper.export_collision(b_obj, n_parent) # return None # done; stop here self.n_root = None # there is only one root object so that will be our final root if len(root_objects) == 1: b_obj = root_objects[0] self.export_node(b_obj, None) # there is more than one root object so we create a meta root else: NifLog.info("Created meta root because blender scene had multiple root objects") self.n_root = types.create_ninode() self.n_root.name = "Scene Root" for b_obj in root_objects: self.export_node(b_obj, self.n_root) # TODO [object] How dow we know we are selecting the right node in the case of multi-root? # making root block a fade node root_type = b_obj.niftools.rootnode if bpy.context.scene.niftools_scene.game in ('FALLOUT_3', 'SKYRIM') and root_type == 'BSFadeNode': NifLog.info("Making root block a BSFadeNode") fade_root_block = NifFormat.BSFadeNode().deepcopy(self.n_root) fade_root_block.replace_global_node(self.n_root, fade_root_block) self.n_root = fade_root_block # various extra datas object_property = ObjectDataProperty() object_property.export_bsxflags_upb(self.n_root, root_objects) object_property.export_inventory_marker(self.n_root, root_objects) object_property.export_weapon_location(self.n_root, b_obj) types.export_furniture_marker(self.n_root, filebase) return self.n_root
def export_collision(self, b_obj, n_parent): """Main function for adding collision object b_obj to a node. Returns True if this object is exported as a collision""" if b_obj.display_type != "BOUNDS": return if b_obj.name.lower().startswith('bsbound'): # add a bounding box self.bs_helper.export_bounds(b_obj, n_parent, bsbound=True) elif b_obj.name.lower().startswith("bounding box"): # Morrowind bounding box self.bs_helper.export_bounds(b_obj, n_parent, bsbound=False) if bpy.context.scene.niftools_scene.game in ('OBLIVION', 'FALLOUT_3', 'SKYRIM'): nodes = [n_parent] nodes.extend([ block for block in n_parent.children if block.name[:14] == 'collisiondummy' ]) for node in nodes: try: self.bhk_helper.export_collision_helper(b_obj, node) break except ValueError: # adding collision failed continue else: # all nodes failed so add new one node = types.create_ninode(b_obj) node.name = 'collisiondummy{:d}'.format(n_parent.num_children) if b_obj.niftools.flags != 0: node_flag_hex = hex(b_obj.niftools.flags) else: node_flag_hex = 0x000E # default node.flags = node_flag_hex n_parent.add_child(node) self.bhk_helper.export_collision_helper(b_obj, node) elif bpy.context.scene.niftools_scene.game in ('ZOO_TYCOON_2', ): self.bound_helper.export_nicollisiondata(b_obj, n_parent) else: NifLog.warn( f"Collisions not supported for game '{bpy.context.scene.niftools_scene.game}', skipped collision object '{b_obj.name}'" ) return True
def export_bone(self, b_obj, b_bone, n_parent_node): """Exports a bone and all of its children.""" # create a new nif block for this b_bone n_node = types.create_ninode(b_bone) n_node.name = block_store.get_full_name(b_bone) # link to nif parent node n_parent_node.add_child(n_node) self.export_bone_flags(b_bone, n_node) # rest pose math.set_object_matrix(b_bone, n_node) # per-bone animation self.transform_anim.export_transforms(n_node, b_obj, self.b_action, b_bone) # continue down the bone tree for b_child in b_bone.children: self.export_bone(b_obj, b_child, n_node)
def export_node(self, b_obj, n_parent): """Export a mesh/armature/empty object b_obj as child of n_parent. Export also all children of b_obj. :param n_parent: :param b_obj: """ if not b_obj: return None b_action = self.object_anim.get_active_action(b_obj) # can we export this b_obj? if b_obj.type not in self.export_types: return None if b_obj.type == 'MESH': if self.export_collision(b_obj, n_parent): return else: # -> mesh data. is_multimaterial = len(set([f.material_index for f in b_obj.data.polygons])) > 1 # determine if object tracks camera # nb normally, imported models will have tracking constraints on their parent empty # but users may create track_to constraints directly on objects, so keep it for now has_track = types.has_track(b_obj) # If this has children or animations or more than one material it gets wrapped in a purpose made NiNode. if not (b_action or b_obj.children or is_multimaterial or has_track): mesh = self.mesh_helper.export_tri_shapes(b_obj, n_parent, self.n_root, b_obj.name) if not self.n_root: self.n_root = mesh return mesh # set transform on trishapes rather than NiNodes for skinned meshes to fix an issue with clothing slots if b_obj.parent and b_obj.parent.type == 'ARMATURE' and b_action: # mesh with armature parent should not have animation! NifLog.warn(f"Mesh {b_obj.name} is skinned but also has object animation. " f"The nif format does not support this, ignoring object animation.") b_action = False # -> everything else (empty/armature) is a (more or less regular) node node = types.create_ninode(b_obj) # set parenting here so that it can be accessed if not self.n_root: self.n_root = node # make it child of its parent in the nif, if it has one if n_parent: n_parent.add_child(node) # and fill in this node's non-trivial values node.name = block_store.get_full_name(b_obj) self.set_node_flags(b_obj, node) math.set_object_matrix(b_obj, node) # export object animation self.transform_anim.export_transforms(node, b_obj, b_action) self.object_anim.export_visibility(node, b_action) # if it is a mesh, export the mesh as trishape children of this ninode if b_obj.type == 'MESH': return self.mesh_helper.export_tri_shapes(b_obj, node, self.n_root) # if it is an armature, export the bones as ninode children of this ninode elif b_obj.type == 'ARMATURE': self.armaturehelper.export_bones(b_obj, node) # export all children of this b_obj as children of this NiNode self.export_children(b_obj, node) return node