diff --git a/bms_blender_plugin/common/bounding_box.py b/bms_blender_plugin/common/bounding_box.py index c698ce3..995a6c3 100644 --- a/bms_blender_plugin/common/bounding_box.py +++ b/bms_blender_plugin/common/bounding_box.py @@ -1,5 +1,3 @@ -from enum import Enum -from mathutils import Vector from bms_blender_plugin.common.coordinates import vector_to_bms_coords class BoundingBox: diff --git a/bms_blender_plugin/exporter/bml_output.py b/bms_blender_plugin/exporter/bml_output.py index 00bf563..6009127 100644 --- a/bms_blender_plugin/exporter/bml_output.py +++ b/bms_blender_plugin/exporter/bml_output.py @@ -2,7 +2,6 @@ import math import bpy -from mathutils import Vector from bms_blender_plugin.common.blender_types import BlenderNodeType, LodItem from bms_blender_plugin.common.export_settings import ExportSettings @@ -10,12 +9,14 @@ get_bml_type, ) from bms_blender_plugin.exporter.export_hotspots import export_hotspots +from bms_blender_plugin.common.bounding_box import BoundingBox from bms_blender_plugin.exporter.export_lods import ( export_lods, ) from bms_blender_plugin.exporter.export_materials import ( export_materials, ) from bms_blender_plugin.exporter.export_parent_dat import get_slots, export_parent_dat +from bms_blender_plugin.exporter.export_bounding_boxes import export_bounding_boxes def export_bml(context, lods, file_directory, file_prefix, export_settings: ExportSettings): @@ -42,28 +43,28 @@ def export_bml(context, lods, file_directory, file_prefix, export_settings: Expo print(f"unit scaling factor: {scale_factor}") - bounding_box_1_coords = Vector((0, 0, 0)) - bounding_box_2_coords = Vector((0, 0, 0)) - - # try to find the bounding box - we take the first one we get - for obj in context.scene.objects: - if get_bml_type(obj) == BlenderNodeType.BBOX: - max_x, min_x, max_y, min_y, max_z, min_z = (0,)*6 - # find the min and max coordinates of the 8 vertices - for corner in obj.data.vertices: - max_x = max(corner.co.x, max_x) - min_x = min(corner.co.x, min_x) - max_y = max(corner.co.y, max_y) - min_y = min(corner.co.y, min_y) - max_z = max(corner.co.z, max_z) - min_z = min(corner.co.z, min_z) - - bounding_box_1_coords = Vector((max_x, max_y, max_z)) - bounding_box_2_coords = Vector((min_x, min_y, min_z)) - - bounding_box_1_coords *= scale_factor - bounding_box_2_coords *= scale_factor - break + """ + Bounding Box handling. + A complex model can have more than one bounding box, for example an Aircraft Model usually has fuselage, + wing, rudder and radar hitboxes defined by separate bounding boxes. + As far as I know we don't care about identifying each particular bounding box with an identity key. + Here we will iterate over all bounding boxes and construct the min and max vertex positions + We will then take the first BBox and extract it's coordinates for the Parent.dat file. + The remaining hitboxes can be exported to a separate file, but we need to do further work to integrate these into the + AC.txtpb files. + """ + + # Gather all bounding boxes into an array of bounding_box objects. + BBox_Array = [BoundingBox(obj) for obj in context.scene.objects if get_bml_type(obj) == BlenderNodeType.BBOX] + """ + Get the first bounding box min and max coordinates. A bit arbitrary at this point, + but in instances of a single bbox, no harm and I suspect that these will be in named order. + Scale appropriately + """ + bounding_box_1_min_coords = BBox_Array[0].min_bms_vertex + bounding_box_1_max_coords = BBox_Array[0].max_bms_vertex + bounding_box_1_min_coords *= scale_factor + bounding_box_1_max_coords *= scale_factor # we have to call export_lods even if we don't want to export models # because it will return materials and hotspots @@ -94,8 +95,8 @@ def export_bml(context, lods, file_directory, file_prefix, export_settings: Expo context, file_directory, file_prefix, - bounding_box_1_coords, - bounding_box_2_coords, + bounding_box_1_min_coords, + bounding_box_1_max_coords, scale_factor, number_of_texture_sets, get_slots(context.scene), @@ -105,6 +106,11 @@ def export_bml(context, lods, file_directory, file_prefix, export_settings: Expo if export_settings.export_hotspots: export_hotspots(all_hotspots, file_directory) + # If there is more than one bounding box defined, output all to a file. + if len(BBox_Array) > 1: + export_bounding_boxes(BBox_Array, file_directory) + + elapsed = datetime.datetime.now() - start_time elapsed_minutes = divmod(elapsed.total_seconds(), 60) @@ -113,5 +119,6 @@ def export_bml(context, lods, file_directory, file_prefix, export_settings: Expo f"{math.trunc(elapsed_minutes[0])}m {round(elapsed_minutes[1],2)}s" ) + print(success_message) return success_message, all_exported_bmls diff --git a/bms_blender_plugin/exporter/export_bounding_boxes.py b/bms_blender_plugin/exporter/export_bounding_boxes.py index 6b49597..e7a7e07 100644 --- a/bms_blender_plugin/exporter/export_bounding_boxes.py +++ b/bms_blender_plugin/exporter/export_bounding_boxes.py @@ -1,4 +1,3 @@ -import operator import os def export_bounding_boxes(bounding_boxes, file_directory): diff --git a/bms_blender_plugin/exporter/export_parent_dat.py b/bms_blender_plugin/exporter/export_parent_dat.py index 2b135eb..752ea9c 100644 --- a/bms_blender_plugin/exporter/export_parent_dat.py +++ b/bms_blender_plugin/exporter/export_parent_dat.py @@ -62,8 +62,8 @@ def export_parent_dat( context, file_directory: str, file_prefix: str, - bounding_box_1_coords, - bounding_box_2_coords, + bounding_box_1_min_coords, + bounding_box_1_max_coords, scale_factor, number_of_texture_sets, slot_list, @@ -72,9 +72,6 @@ def export_parent_dat( """Exports the Parent.dat as a file""" parent_dat_filepath = os.path.join(file_directory, "Parent.dat") - bounding_box_1_coords = to_bms_coords(bounding_box_1_coords) - bounding_box_2_coords = to_bms_coords(bounding_box_2_coords) - # note: the "Switches" and "Dofs" config in the Parent.dat don't actually amount to the number of DOFs/switches but # to the highest dof_number in the model highest_switch_number, highest_dof_number = get_highest_switch_and_dof_number( @@ -89,10 +86,11 @@ def export_parent_dat( with open(parent_dat_filepath, "w") as parent_dat_file: str_output = ( + f"// Dimensions = bounding_sphere_radius bbox_min_x bbox_max_x bbox_min_y bbox_max_y bbox_min_z bbox_max_z\n" f"Dimensions = {round(bounding_sphere_radius, 6)} " - f"{round(bounding_box_1_coords.x, 6):.6f} {round(bounding_box_2_coords.x, 6):.6f} " - f"{round(bounding_box_1_coords.y, 6):.6f} {round(bounding_box_2_coords.y, 6):.6f} " - f"{round(bounding_box_1_coords.z, 6):.6f} {round(bounding_box_2_coords.z, 6):.6f}\n" + f"{round(bounding_box_1_min_coords.x, 6):.6f} {round(bounding_box_1_max_coords.x, 6):.6f} " + f"{round(bounding_box_1_min_coords.y, 6):.6f} {round(bounding_box_1_max_coords.y, 6):.6f} " + f"{round(bounding_box_1_min_coords.z, 6):.6f} {round(bounding_box_1_max_coords.z, 6):.6f}\n" f"TextureSets = {number_of_texture_sets}\n" f"Switches = {highest_switch_number}\n" f"Dofs = {highest_dof_number}\n" diff --git a/docs/Manual/MANUAL.md b/docs/Manual/MANUAL.md index 9e3e410..f786336 100644 --- a/docs/Manual/MANUAL.md +++ b/docs/Manual/MANUAL.md @@ -373,16 +373,16 @@ The data definition of racks is located in the ```BmsRack.dat``` (not part of th Falcon uses bounding box dimensions in order to set the objects hitbox. In order to create a bounding box, Go to the "Add" panel, then "Falcon BMS", then "Bounding Box" (alternatively, you can use the BMS Tools Panel). A bounding box will be added to the scene and automatically fitted to the geometry of the currently active collection. The bounding box can be moved and scaled. -The bounding box is only required once per scene. +Multiple bounding boxes can be added to each scene, but only one is required. ![Bounding Box](Bounding_Box.png) > ⚠️ The bounding box rotation is constrained since Falcon only implements bounding boxes aligned with X/Y/Z Axis. *Do not* force a rotation on the bounding box. When applying a bounding box to your model, think about how the in-game hitbox should be. i.e. for an aircraft hangar the bounding box should only be the roof, since planes have the option to taxi into them. -The bounding box will be exported into the ```Parent.dat``` file, and will populate the "dimensions" line. -> ℹ️ BMS aircraft can have multiple additional bounding boxes. Those are defined in the \.dat (ACDATA). Their export is not yet implemented. +The first bounding box will be exported into the ```Parent.dat``` file, and will populate the "dimensions" line. If more than one bounding box exists in the model, bounding box data will also be exported to bounding_boxes.txtpb +This additional data will still need to be integrated into the \Data\Sim\Acdata\.txtpb file by the user, but should be formatted by the plugin to make this process easier.