Hard Light Productions Forums

Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Topic started by: zookeeper on January 08, 2012, 08:34:15 am

Title: [CANCELED] Submodel prop to expand bbox to encompass children
Post by: zookeeper on January 08, 2012, 08:34:15 am
EDIT: This hasn't been necessary ever since PCS2 got the bounding box override controls.

I've found that quite often the bounding box of my detail-0 doesn't cover the whole ship (because of submodel subsystems), which is annoying because it causes the targeting brackets to get drawn wrong, and there's not always a good workaround available. This patch enables an $expanded_bbox submodel prop, which causes the game to re-calculate the bounding box for the submodel so that it fully encompasses all the submodel's children as well.

And before anyone states the obvious: of course it'd be better to have the feature in PCS2.

Code: [Select]
Index: model.h
===================================================================
--- model.h (revision 8188)
+++ model.h (working copy)
@@ -316,6 +316,7 @@
  char lod_name[MAX_NAME_LEN]; //FUBAR:  Name to be used for LOD naming comparison to preserve compatibility with older tables.  Only used on LOD0
  bool attach_thrusters; //zookeeper: If set and this submodel or any of its parents rotates, also rotates associated thrusters.
  float dumb_turn_rate;
+ bool expanded_bbox; //zookeeper: Expand the bounding box of this submodel to also encompass any child submodels.
 
  /* If you've got a better way to do this, please implement it! */
  void Reset( )
@@ -351,6 +352,7 @@
  rad = 0.f;
  lod_name[ 0 ] = '\0';
  attach_thrusters = false;
+ expanded_bbox = false;
 
  /* Compound types */
  memset( live_debris, 0, sizeof( live_debris ) );
Index: modelread.cpp
===================================================================
--- modelread.cpp (revision 8188)
+++ modelread.cpp (working copy)
@@ -930,7 +930,58 @@
  box[7].xyz.x = big_mn->xyz.x; box[7].xyz.y = big_mx->xyz.y; box[7].xyz.z = big_mx->xyz.z;
 }
 
+/**
+ * Returns the min and max points of a bounding box which would be big enough to
+ * encompass not only the given submodel itself, but all its children as well.
+ *
+ * @param *mins Output point (min)
+ * @param *maxs Output point (max)
+ * @param *pm The model we're interested in
+ * @param submodel_num Which submodel's min and max we want
+ */
+void submodel_calc_expanded_bound_box( vec3d *mins, vec3d *maxs, polymodel *pm, int submodel_num )
+{
+ vec3d min, max;
 
+ vm_vec_add(&min, &pm->submodel[submodel_num].min, &pm->submodel[submodel_num].offset);
+ vm_vec_add(&max, &pm->submodel[submodel_num].max, &pm->submodel[submodel_num].offset);
+
+ int child_submodel_num = pm->submodel[submodel_num].first_child;
+
+ if ( child_submodel_num == -1) {
+ *mins = min;
+ *maxs = max;
+
+ return;
+ }
+
+ while ( child_submodel_num != -1 ) {
+ vec3d child_min;
+ vec3d child_max;
+
+ submodel_calc_expanded_bound_box(&child_min, &child_max, pm, child_submodel_num);
+
+ vm_vec_add2(&child_min, &pm->submodel[submodel_num].offset);
+ vm_vec_add2(&child_max, &pm->submodel[submodel_num].offset);
+
+ min.xyz.x = MIN(min.xyz.x, child_min.xyz.x);
+ min.xyz.y = MIN(min.xyz.y, child_min.xyz.y);
+ min.xyz.z = MIN(min.xyz.z, child_min.xyz.z);
+ max.xyz.x = MAX(max.xyz.x, child_max.xyz.x);
+ max.xyz.y = MAX(max.xyz.y, child_max.xyz.y);
+ max.xyz.z = MAX(max.xyz.z, child_max.xyz.z);
+
+ child_submodel_num = pm->submodel[child_submodel_num].next_sibling;
+ }
+
+ vm_vec_sub2(&min, &pm->submodel[submodel_num].offset);
+ vm_vec_sub2(&max, &pm->submodel[submodel_num].offset);
+
+ *mins = min;
+ *maxs = max;
+}
+
+
 void parse_triggers(int &n_trig, queued_animation **triggers, char *props);
 
 
@@ -1322,6 +1373,11 @@
  else
  pm->submodel[n].attach_thrusters = false;
 
+ if (strstr(props, "$expanded_bbox") != NULL )
+ pm->submodel[n].expanded_bbox = true;
+ else
+ pm->submodel[n].expanded_bbox = false;
+
  if ( (p = strstr(props, "$detail_box:")) != NULL ) {
  p += 12;
  while (*p == ' ') p++;
@@ -2448,6 +2504,16 @@
 
  create_family_tree(pm);
 
+ // Give an expanded bounding box to any submodel which wants one
+ for (int i=0; i<pm->n_models; i++ ) {
+ if ( pm->submodel[i].expanded_bbox ) {
+ vec3d min, max;
+
+ submodel_calc_expanded_bound_box(&min, &max, pm, i);
+ model_calc_bound_box(pm->submodel[i].bounding_box, &min, &max);
+ }
+ }
+
  // maybe generate vertex buffers
  create_vertex_buffer(pm);
 

EDIT: Note that this does not even try to account for rotating subsystems.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: zookeeper on January 12, 2012, 12:46:23 pm
Oops, submodels which weren't at 0,0,0 weren't handled right. Updated the patch.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: Nuke on January 12, 2012, 02:44:33 pm
does this let you specify the size of the bbox just tells the game to recompute? i know sometimes i want to set the bounding box a little bit bigger so that collision detection is handled better for animated objects.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: zookeeper on January 12, 2012, 03:26:13 pm
does this let you specify the size of the bbox just tells the game to recompute? i know sometimes i want to set the bounding box a little bit bigger so that collision detection is handled better for animated objects.
Nope, it just recomputes the box.

However, before I wrote this I also implemented a submodel prop with which you could override the bbox dimensions, but that seemed so unwieldy that I didn't even save it. It would be trivial to rewrite it though, so if it's really really needed I can do that.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: Nuke on January 12, 2012, 04:11:48 pm
there are other ways to get around problems like that, the obvious way is with a big invisible box and no collide invisible. manually editing the bbox is a somewhat confusing operation, and an unnecessarily large bbox will be a bigger target for collisions (requiring additional collision testing), i think id rather have the box resized by the engine. just need a slightly different algorithm to determine the box size. perhaps a property for animated subobjects.

i figure there's probably a way to compute the bbox for an object that rotates about any number of axes. for a 2d example, find the bbox corner that is furthest from the submodel's center on any given plane and get its distance. then if you were to draw a circle about the center at of the model at that radius. then create a new bbox that can encompass that circle (the box would be square for the most part), then any possible rotation about the planes normal will result in the rotated submodel fitting into that box. the bounding box dimensions parallel to the plane axis could just be left as is. this is probably adequate for most flat rotations (anything about a single orthogonal axis). if necessary, the resulting box would be expanded to encompass children.

rotations on arbitrary axes or multiple orthogonal axes would only be slightly more complex. just figure out the bbox for each plane and use the largest dimentions for each axis from the 3 results. this results in a cube shaped box that should encompass all possible rotations. again expand to include children. also when processing the bounding boxes, it helps to expand children first, and then make sure the bounding boxes for the parents can contain them. this also allows for chains of animated objects to have proper collision detection.

you could probably also include some information about possible rotation ranges and use that to come up with the smallest box possible, but i dont know an algorithm for that.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: zookeeper on January 12, 2012, 04:15:32 pm
there are other ways to get around problems like that, the obvious way is with a big invisible box and no collide invisible. manually editing the bbox is a somewhat confusing operation, and an unnecessarily large bbox will be a bigger target for collisions (requiring additional collision testing), i think id rather have the box resized by the engine.

Invisible non-collideable boxes are all nice and good as long as you don't use for example the wireframe targeting view, or care for the new ship tech animations in the loadout screen; the box is going to show up at those places (I'm not sure if there are any others) and look a bit silly.
Title: Re: [patch] Submodel prop to expand bbox to encompass children
Post by: Nuke on January 12, 2012, 04:22:04 pm
yea its somewhat of a dirty hack to use an invisible box in that way. something id rather like to avoid.