Author Topic: Patch [committed]: fixes to subsystem position finding code  (Read 2042 times)

0 Members and 1 Guest are viewing this topic.

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Patch [committed]: fixes to subsystem position finding code
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.

Code: [Select]
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;
« Last Edit: December 02, 2011, 01:02:35 am by zookeeper »

 

Offline Goober5000

  • HLP Loremaster
  • Moderator
  • 214
    • Goober5000 Productions
Re: Patch: fixes to subsystem position finding code
Interesting... how does this differ from the original function?

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Patch: fixes to subsystem position finding code
Interesting... how does this differ from the original function?

Well, all the changes here are related to finding the real submodel position when rotations of parent submodels are taken into account, which is something the old get_subsystem_world_pos and get_subsystem_pos functions didn't do. And quite a few places in the code still don't, for example some of the dockpoint-related code.

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Patch: fixes to subsystem position finding code
you got plans on doing something like this for orientations as well? say you need to convert your rotational frame of reference from subobject local to world or ship-local frame of reference and vise versa, of a subobject with an arbitrary hierarchy path. for example find an objects position in a turrets frame of reference with the turret being several layers deep in the hierarchy (even when parent orientations are not fixed). hell you could even use this kinda thing to do ik for complex animation.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Patch: fixes to subsystem position finding code
you got plans on doing something like this for orientations as well? say you need to convert your rotational frame of reference from subobject local to world or ship-local frame of reference and vise versa, of a subobject with an arbitrary hierarchy path. for example find an objects position in a turrets frame of reference with the turret being several layers deep in the hierarchy (even when parent orientations are not fixed). hell you could even use this kinda thing to do ik for complex animation.

Not really since I doubt I'm going to need it for anything myself. The find_submodel_instance_point_normal function does something along those lines, but it only deals in normals, not matrices. It shouldn't be hard to adapt find_submodel_instance_point to calculate the matrix representing the orientation, instead of the position.

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Patch: fixes to subsystem position finding code
it might actually be faster to transform a pair of perpendicular normals up or down the hierarchy chain to avoid having to do a lot of matrix multiplications (instead doing matrix-vector operations), and then use them to build a matrix. i think its 33% faster, seeing that a matrix-vector operation only uses a third of the math of a 3x3 matrix multiplication.
« Last Edit: November 28, 2011, 06:56:11 pm by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Patch: fixes to subsystem position finding code
I keep hearing about quaternion rotations somewhere... think my hearing's going out though.

Oh! Is it possible to use OpenGL to make the GPU do the rotations? I know there's a built-in function, but I don't know if its one of the ones that can be performed by the GPU and the result returned to the program.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Patch: fixes to subsystem position finding code
not sure about quaternions. i tried using them but never got the hang of it. of course your modern fpu is fast enough to brute force it with matrix multiplication. normal transforms are faster i guess. i have a headache now.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Patch: fixes to subsystem position finding code
Well, I doubt these bits of code take more than a very negligible amount of CPU time anyway, so does it really matter? None of the matrix calculations which I've added are performed on submodels/subsystems which always remain in a static position, in case you're worried about that.

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Patch: fixes to subsystem position finding code
if your subobject chain is static and non-animated its probably better to have identity matrices all around (and transform data is tossed at import anyway) so you only need to consider matrices on submodels with dynamic orientations. even with transform (such as submodels with fvec and uvec defined, or an object with an initial position animation) if nothing in the chain ever rotates, you could essentially bake matrix for each child submodel at model load. every subobject's matrix could be directly used to convert from model to submodels space and vise versa with no regard for other submodels (conversion from submodel to world space just requires multiplying in the ship orientation).

of course when anything is dynamic, such as a turret on an animated object, this does not work. as soon as you get a submodel in the chain that moves (not-static matrix), you need to multiply its matrix in. you can treat chains of static (even relative to a moving parent) objects as a single object, in which case the parent would have a rotation in its matrix, and the other 2 would be identity, and you would only need to worry about offsets. a worst case scenario is where every object in the chain is animated and you need to consider every matrix (this is of course rare, but should be supported for some potential animation goodness).

i should point out that hierarchy can only be 5 levels deep right now, it can be bumped by changing a define but im not sure what that does to performance. a 2-part turret for example can only ever have 2 objects between it and the hull (hull->object1->object2->base->arms) and stay in the limit. its not very common to have more than 3 levels deep, and then only in case of a 2 part turret, and 2 levels for physical subsystems. animation is really the only reason to use a deep hierarchy, and the only reason to do complex frame of reference conversions (and of course turrets). so long as yout turret on a tentical fires from the right point in space, who really cares :P
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Patch: fixes to subsystem position finding code
Committed by Wanderer in r8054, with one bugfix.

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: Patch: fixes to subsystem position finding code
Oh! Is it possible to use OpenGL to make the GPU do the rotations? I know there's a built-in function, but I don't know if its one of the ones that can be performed by the GPU and the result returned to the program.

Actually, the matrix transform operations are deprecated (as of GL 3, I think?) and they were never GPU to begin with.

Edit: referring to functions such as: glTranslate, glRotate, glScale, etc.