This makes some functions correctly return the actual current position of a subsystem. It introduces two functions in modelread which should work as the universal ways of getting a submodel's current position, and similarly turns ship:get_subsystem_pos into a function which should work as the universal way of getting the position of a subsystem.
Index: hud/hudtarget.cpp
===================================================================
--- hud/hudtarget.cpp (revision 8050)
+++ hud/hudtarget.cpp (working copy)
@@ -45,6 +45,7 @@
#include "network/multi.h"
#include "graphics/font.h"
#include "network/multiutil.h"
+#include "model/model.h"
// If any of these bits in the ship->flags are set, ignore this ship when targetting
int TARGET_SHIP_IGNORE_FLAGS = (SF_EXPLODED|SF_DEPART_WARP|SF_DYING|SF_ARRIVING_STAGE_1|SF_HIDDEN_FROM_SENSORS);
@@ -4334,17 +4335,11 @@
}
// --------------------------------------------------------------------------------
-// get_subsystem_world_pos() returns the world position for a given subobject on a ship
+// get_subsystem_world_pos() returns the world position for a given subsystem on a ship
//
vec3d* get_subsystem_world_pos(object* parent_obj, ship_subsys* subsys, vec3d* world_pos)
{
- if (subsys == NULL) {
- *world_pos = parent_obj->pos;
- return world_pos;
- }
-
- vm_vec_unrotate(world_pos, &subsys->system_info->pnt, &parent_obj->orient);
- vm_vec_add2(world_pos, &parent_obj->pos);
+ get_subsystem_pos(world_pos, parent_obj, subsys);
return world_pos;
}
Index: model/model.h
===================================================================
--- model/model.h (revision 8050)
+++ model/model.h (working copy)
@@ -858,7 +858,9 @@
void world_find_model_instance_point(vec3d *out, vec3d *world_pt, polymodel *pm, polymodel_instance *pmi, int submodel_num, matrix *orient, vec3d *pos);
+extern void find_submodel_instance_point(vec3d *outpnt, object *ship_obj, int submodel_num);
extern void find_submodel_instance_point_normal(vec3d *outpnt, vec3d *outnorm, object *ship_obj, int submodel_num, vec3d *submodel_pnt, vec3d *submodel_norm);
+extern void find_submodel_instance_world_point(vec3d *outpnt, object *ship_obj, int submodel_num);
// Given a polygon model index, find a list of rotating submodels to be used for collision
void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp);
Index: model/modelread.cpp
===================================================================
--- model/modelread.cpp (revision 8050)
+++ model/modelread.cpp (working copy)
@@ -3842,10 +3842,53 @@
}
/**
- * Finds the current location and rotation of a submodel point, taking into account the
- * rotations of the submodel and any parent submodels it might have.
+ * Finds the current location of a submodel (in the ship's frame of reference),
+ * taking into account the rotations of any parent submodels it might have.
*
* @param *outpnt Output point
+ * @param *ship_obj Ship object
+ * @param submodel_num The number of the submodel we're interested in
+ */
+void find_submodel_instance_point(vec3d *outpnt, object *ship_obj, int submodel_num)
+{
+ Assert(ship_obj->type == OBJ_SHIP);
+
+ vm_vec_zero(outpnt);
+ matrix submodel_instance_matrix, rotation_matrix, inv_orientation;
+
+ polymodel_instance *pmi = model_get_instance(Ships[ship_obj->instance].model_instance_num);
+ polymodel *pm = model_get(Ship_info[Ships[ship_obj->instance].ship_info_index].model_num);
+
+ int mn = submodel_num;
+ while ( (mn >= 0) && (pm->submodel[mn].parent >= 0) ) {
+ vec3d offset = pm->submodel[mn].offset;
+
+ int parent_mn = pm->submodel[mn].parent;
+
+ if (pm->submodel[parent_mn].can_move) {
+ rotation_matrix = pm->submodel[parent_mn].orientation;
+ vm_rotate_matrix_by_angles(&rotation_matrix, &pmi->submodel[parent_mn].angs);
+
+ vm_copy_transpose_matrix(&inv_orientation, &pm->submodel[parent_mn].orientation);
+
+ vm_matrix_x_matrix(&submodel_instance_matrix, &rotation_matrix, &inv_orientation);
+
+ vec3d tvec = offset;
+ vm_vec_unrotate(&offset, &tvec, &submodel_instance_matrix);
+ }
+
+ vm_vec_add2(outpnt, &offset);
+
+ mn = parent_mn;
+ }
+}
+
+/**
+ * Finds the current location and rotation (in the ship's frame of reference) of
+ * a submodel point, taking into account the rotations of the submodel and any
+ * parent submodels it might have.
+ *
+ * @param *outpnt Output point
* @param *outnorm Output normal
* @param *ship_obj Ship object
* @param submodel_num The number of the submodel we're interested in
@@ -3903,10 +3946,28 @@
vm_vec_add2(outpnt, &offset);
- mn = pm->submodel[mn].parent;
+ mn = parent_model_num;
}
}
+/**
+ * Finds the current world location of a submodel, taking into account the
+ * rotations of any parent submodels it might have.
+ *
+ * @param *outpnt Output point
+ * @param *ship_obj Ship object
+ * @param submodel_num The number of the submodel we're interested in
+ */
+void find_submodel_instance_world_point(vec3d *outpnt, object *ship_obj, int submodel_num)
+{
+ vec3d loc_pnt;
+
+ find_submodel_instance_point(&loc_pnt, ship_obj, submodel_num);
+
+ vm_vec_unrotate(outpnt, &loc_pnt, &ship_obj->orient);
+ vm_vec_add(outpnt, &loc_pnt, &ship_obj->pos);
+}
+
// Verify rotating submodel has corresponding ship subsystem -- info in which to store rotation angle
int rotating_submodel_has_ship_subsys(int submodel, ship *shipp)
{
Index: ship/ship.cpp
===================================================================
--- ship/ship.cpp (revision 8050)
+++ ship/ship.cpp (working copy)
@@ -11509,30 +11509,28 @@
return 1;
}
-// Note: This is not a general purpose routine.
-// It is specifically used for targeting.
-// It only returns a subsystem position if it has shields.
-// Return true/false for subsystem found/not found.
-// Stuff vector *pos with absolute position.
+// Finds the world position of a subsystem.
+// Return true/false for subsystem found/not found.
+// Stuff vector *pos with absolute position.
// subsysp is a pointer to the subsystem.
int get_subsystem_pos(vec3d *pos, object *objp, ship_subsys *subsysp)
{
- model_subsystem *psub;
- vec3d pnt;
- ship *shipp;
+ if (subsysp == NULL) {
+ *pos = objp->pos;
+ return 0;
+ }
- Assert(objp->type == OBJ_SHIP);
- shipp = &Ships[objp->instance];
+ model_subsystem *mss = subsysp->system_info;
- Assert ( subsysp != NULL );
+ if (mss->subobj_num == -1) {
+ // If it's a special point subsys, we can use its offset directly
- psub = subsysp->system_info;
+ vm_vec_unrotate(pos, &subsysp->system_info->pnt, &objp->orient);
+ vm_vec_add2(pos, &objp->pos);
+ } else {
+ // Submodel subsystems may require a more complicated calculation
- vm_vec_unrotate(&pnt, &psub->pnt, &objp->orient);
- vm_vec_add2(&pnt, &objp->pos);
-
- if ( pos ){
- *pos = pnt;
+ find_submodel_instance_world_point(pos, objp, mss->subobj_num);
}
return 1;