Hard Light Productions Forums

Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Topic started by: zookeeper on January 16, 2012, 03:31:34 pm

Title: [Patch] $detail_sphere (committed)
Post by: zookeeper on January 16, 2012, 03:31:34 pm
I've always wanted this, so here goes. Just like $detail_box, but a sphere.

Code: [Select]
Index: model.h
===================================================================
--- model.h (revision 8255)
+++ model.h (working copy)
@@ -307,7 +307,9 @@
 
  vec3d render_box_min;
  vec3d render_box_max;
- int use_render_box; // 0==do nothing, 1==only render this object if you are inside the box, -1==only if your out
+ float render_sphere_radius;
+ int use_render_box; // 0==do nothing, 1==only render this object if you are inside the box, -1==only if you're outside
+ int use_render_sphere; // 0==do nothing, 1==only render this object if you are inside the sphere, -1==only if you're outside
  bool gun_rotation; // for animated weapon models
  bool no_collisions; // for $no_collisions property - kazan
  bool nocollide_this_only; //SUSHI: Like no_collisions, but not recursive. For the "replacement" collision model scheme.
@@ -340,7 +342,9 @@
  next_sibling = 0;
  num_details = 0;
  num_arcs = 0;
+ render_sphere_radius = 0;
  use_render_box = 0;
+ use_render_sphere = 0;
  gun_rotation = false;
  no_collisions = false;
  nocollide_this_only = false;
Index: modelinterp.cpp
===================================================================
--- modelinterp.cpp (revision 8255)
+++ modelinterp.cpp (working copy)
@@ -78,9 +78,10 @@
 static vertex **Interp_list = NULL;
 static int  Num_interp_list_verts_allocated = 0;
 
-static float Interp_box_scale = 1.0f;
+static float Interp_box_scale = 1.0f; // this is used to scale both detail boxes and spheres
 static vec3d Interp_render_box_min = ZERO_VECTOR;
 static vec3d Interp_render_box_max = ZERO_VECTOR;
+static float Interp_render_sphere_radius = 0.0f;
 
 // -------------------------------------------------------------------
 // lighting save stuff
@@ -361,6 +362,7 @@
  Interp_box_scale = 1.0f;
  Interp_render_box_min = vmd_zero_vector;
  Interp_render_box_max = vmd_zero_vector;
+ Interp_render_sphere_radius = 0.0f;
 }
 
 /**
@@ -4290,7 +4292,19 @@
  return -1;
 }
 
+inline int in_sphere(vec3d *center, float radius)
+{
+ vec3d point;
 
+ vm_vec_sub(&point, &View_position, center);
+
+ if ( vm_vec_dist(&point, center) <= radius )
+ return 1;
+ else
+ return -1;
+}
+
+
 void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
 {
  int i;
@@ -4318,7 +4332,7 @@
  Interp_thrust_scale_subobj = 0;
  }
 
- // if using detail boxes, check that we are valid for the range
+ // if using detail boxes or spheres, check that we are valid for the range
  if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_box ) {
  vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
  vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
@@ -4326,7 +4340,13 @@
  if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
  return;
  }
+ if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
+ Interp_render_sphere_radius = model->render_sphere_radius * Interp_box_scale;
 
+ if ( (-model->use_render_sphere + in_sphere(&model->offset, Interp_render_sphere_radius)) )
+ return;
+ }
+
  // Get submodel rotation data and use submodel orientation matrix
  // to put together a matrix describing the final orientation of
  // the submodel relative to its parent
@@ -4408,7 +4428,7 @@
 
  bsp_info *model = &pm->submodel[mn];
 
- // if using detail boxes, check that we are valid for the range
+ // if using detail boxes or spheres, check that we are valid for the range
  if ( !is_child && !(Interp_flags & MR_FULL_DETAIL) && model->use_render_box ) {
  vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
  vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
@@ -4416,7 +4436,13 @@
  if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
  return;
  }
+ if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
+ Interp_render_sphere_radius = model->render_sphere_radius * Interp_box_scale;
 
+ if ( (-model->use_render_sphere + in_sphere(&model->offset, Interp_render_sphere_radius)) )
+ return;
+ }
+
  vec3d scale;
 
  if (Interp_thrust_scale_subobj) {
Index: modelread.cpp
===================================================================
--- modelread.cpp (revision 8255)
+++ modelread.cpp (working copy)
@@ -1352,6 +1352,20 @@
  }
  }
 
+ if ( (p = strstr(props, "$detail_sphere:")) != NULL ) {
+ p += 15;
+ while (*p == ' ') p++;
+ pm->submodel[n].use_render_sphere = atoi(p);
+
+ if ( (p = strstr(props, "$radius:")) != NULL ) {
+ p += 8;
+ while (*p == ' ') p++;
+ pm->submodel[n].render_sphere_radius = (float)strtod(p, (char **)NULL);
+ } else {
+ pm->submodel[n].render_sphere_radius = pm->submodel[n].rad;
+ }
+ }
+
  // Added for new handling of turret orientation - KeldorKatarn
  matrix *orient = &pm->submodel[n].orientation;
 

Example:
Code: [Select]
$detail_sphere: 1
$radius: 1200

Will commit sometime soon if no problems are found.
Title: Re: [Patch] $detail_sphere
Post by: The E on January 16, 2012, 03:33:07 pm
Yesssssss, please.
Title: Re: [Patch] $detail_sphere
Post by: Valathil on January 16, 2012, 03:37:26 pm
i think what you meant was just vm_vec_dist(&View_postion, center) and remove the vm_vec_sub in you in_sphere function

Also the parameter you pass to that function model->offset is just an offset from the model center and not the actual coordinates of the ship in world space.
1) why not use the center of the submodel in question?
2) you have to get the real position of the object your rendering in worldspace and add the submodel offset to it.

DISREGARD THAT [REDACTED]

IRC may be a little relaxed, but let's try and keep this PG-13 please? thanks.
Title: Re: [Patch] $detail_sphere
Post by: zookeeper on January 26, 2012, 08:28:07 am
Committed, finally. For a long time I thought it didn't work right because the detail sphere always kicked in at a distance different than the one indicated by the target distance (shown in the targeting box and next to the targeting brackets), until I realized that the target distance shown is not the distance to the target's center, but to the nearest point on its bounding box. :rolleyes:

This is the final patch:

Code: [Select]
Index: model.h
===================================================================
--- model.h (revision 8375)
+++ model.h (working copy)
@@ -307,7 +307,9 @@
 
  vec3d render_box_min;
  vec3d render_box_max;
- int use_render_box; // 0==do nothing, 1==only render this object if you are inside the box, -1==only if your out
+ float render_sphere_radius;
+ int use_render_box; // 0==do nothing, 1==only render this object if you are inside the box, -1==only if you're outside
+ int use_render_sphere; // 0==do nothing, 1==only render this object if you are inside the sphere, -1==only if you're outside
  bool gun_rotation; // for animated weapon models
  bool no_collisions; // for $no_collisions property - kazan
  bool nocollide_this_only; //SUSHI: Like no_collisions, but not recursive. For the "replacement" collision model scheme.
@@ -340,7 +342,9 @@
  next_sibling = 0;
  num_details = 0;
  num_arcs = 0;
+ render_sphere_radius = 0;
  use_render_box = 0;
+ use_render_sphere = 0;
  gun_rotation = false;
  no_collisions = false;
  nocollide_this_only = false;
Index: modelinterp.cpp
===================================================================
--- modelinterp.cpp (revision 8375)
+++ modelinterp.cpp (working copy)
@@ -78,9 +78,10 @@
 static vertex **Interp_list = NULL;
 static int  Num_interp_list_verts_allocated = 0;
 
-static float Interp_box_scale = 1.0f;
+static float Interp_box_scale = 1.0f; // this is used to scale both detail boxes and spheres
 static vec3d Interp_render_box_min = ZERO_VECTOR;
 static vec3d Interp_render_box_max = ZERO_VECTOR;
+static float Interp_render_sphere_radius = 0.0f;
 
 // -------------------------------------------------------------------
 // lighting save stuff
@@ -361,6 +362,7 @@
  Interp_box_scale = 1.0f;
  Interp_render_box_min = vmd_zero_vector;
  Interp_render_box_max = vmd_zero_vector;
+ Interp_render_sphere_radius = 0.0f;
 }
 
 /**
@@ -4290,7 +4292,19 @@
  return -1;
 }
 
+inline int in_sphere(vec3d *pos, float radius)
+{
+ vec3d point;
 
+ vm_vec_sub(&point, &View_position, pos);
+
+ if ( vm_vec_dist(&point, pos) <= radius )
+ return 1;
+ else
+ return -1;
+}
+
+
 void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
 {
  int i;
@@ -4318,7 +4332,7 @@
  Interp_thrust_scale_subobj = 0;
  }
 
- // if using detail boxes, check that we are valid for the range
+ // if using detail boxes or spheres, check that we are valid for the range
  if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_box ) {
  vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
  vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
@@ -4326,7 +4340,13 @@
  if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
  return;
  }
+ if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
+ Interp_render_sphere_radius = model->render_sphere_radius * Interp_box_scale;
 
+ if ( (-model->use_render_sphere + in_sphere(&model->offset, Interp_render_sphere_radius)) )
+ return;
+ }
+
  // Get submodel rotation data and use submodel orientation matrix
  // to put together a matrix describing the final orientation of
  // the submodel relative to its parent
@@ -4408,7 +4428,7 @@
 
  bsp_info *model = &pm->submodel[mn];
 
- // if using detail boxes, check that we are valid for the range
+ // if using detail boxes or spheres, check that we are valid for the range
  if ( !is_child && !(Interp_flags & MR_FULL_DETAIL) && model->use_render_box ) {
  vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
  vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
@@ -4416,7 +4436,13 @@
  if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
  return;
  }
+ if ( !is_child && !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
+ Interp_render_sphere_radius = model->render_sphere_radius * Interp_box_scale;
 
+ if ( (-model->use_render_sphere + in_sphere(&model->offset, Interp_render_sphere_radius)) )
+ return;
+ }
+
  vec3d scale;
 
  if (Interp_thrust_scale_subobj) {
Index: modelread.cpp
===================================================================
--- modelread.cpp (revision 8375)
+++ modelread.cpp (working copy)
@@ -1352,6 +1352,20 @@
  }
  }
 
+ if ( (p = strstr(props, "$detail_sphere:")) != NULL ) {
+ p += 15;
+ while (*p == ' ') p++;
+ pm->submodel[n].use_render_sphere = atoi(p);
+
+ if ( (p = strstr(props, "$radius:")) != NULL ) {
+ p += 8;
+ while (*p == ' ') p++;
+ pm->submodel[n].render_sphere_radius = (float)strtod(p, (char **)NULL);
+ } else {
+ pm->submodel[n].render_sphere_radius = pm->submodel[n].rad;
+ }
+ }
+
  // Added for new handling of turret orientation - KeldorKatarn
  matrix *orient = &pm->submodel[n].orientation;
 
Title: Re: [Patch] $detail_sphere (committed)
Post by: Bobboau on January 28, 2012, 01:24:13 pm
heh... I could have sworn I had implemented this myself along with the boxes.
Title: Re: [Patch] $detail_sphere (committed)
Post by: Nuke on January 28, 2012, 08:11:35 pm
will this support inside/outside behavior like boxes?
Title: Re: [Patch] $detail_sphere (committed)
Post by: zookeeper on January 29, 2012, 03:23:59 am
will this support inside/outside behavior like boxes?

Yep. Works exactly like boxes.
Title: Re: [Patch] $detail_sphere (committed)
Post by: JGZinv on January 29, 2012, 12:56:39 pm
What benefit do spheres have over cubes?
Title: Re: [Patch] $detail_sphere (committed)
Post by: zookeeper on January 29, 2012, 01:31:12 pm
What benefit do spheres have over cubes?

Well, they're simpler in that you only need to specify one value rather than six. And often enough you want something to pop in or out of view when you're within a certain distance of it rather than within an imaginary box surrounding it.
Title: Re: [Patch] $detail_sphere (committed)
Post by: Valathil on January 29, 2012, 02:31:11 pm
What benefit do spheres have over cubes?

THEY'RE ROUND
Title: Re: [Patch] $detail_sphere (committed)
Post by: Nuke on January 29, 2012, 07:57:45 pm
any way to do a version with 2 parameters where an object is visible if the viewpoint is inside one sphere but outside another?

see i want to be able to do large (enough to cover the entire playable area), super-high detailed terrain maps. because the way lod-ing works, you cant have some subobjects at detail0, others at detail1 and so on, so detail boxes would need to be used. terrain's detail0 would use a dummy object, with invisible and no collide. it would have a number of subobjects, all square and arranged in a grid. these would be medium detail, textured invisible and would serve as a collision terrain. below that you would have a series of progressively higher detail (with no collide) and would use detail spheres to decide which gets used. as it stands i would need to use dummy objects to transition the detail meshes, and the number of detail levels depends on instance depth (which is 5), this limits me to 3 levels of detal.

detail0 (dummy, no-collide)
 |
 grid-x-y (invisible, collision mesh)
  |
  lod0 (visible in smallest radius value)
  dummy ("visible" outside smallest radius, invisible dummy object)
   |
   lod1 (visible in medium radius value)
   dummy ("visible" outside medium radius, invisible dummy object)
    |
    lod2 (always visible)

if i could have a version that lets me say an object is visible if its inside one radius and invisible outside the other, i could arrange my detail meshes as siblings, letting me do as many as i want to allow smoother transitions.
detail0 (dummy, no-collide)
 |
 grid-x-y (invisible, collision mesh)
  |
  lod0 (visible inside 1st (closest) radius)
  lod1 (visible between 2nd and 3rd radius
  lod2 (visible between 3rd and 4th radius
  lod3 (visible between 4th and 5th radius
  lod4 (visible outside 5th radius)

this allows me more lods per grid square. and better transitions between detail levels. id be capped by whatever subobject limit is in place (and wont be wasting it on dummy objects), which ultimately determines the resolution of the grid and number of lods.