Skip to content

Commit db69cb8

Browse files
authored
Merge pull request #7157 from Baezon/uvec-dominant-frame-of-ref
Uvec dominant frame of ref for submodels
2 parents 5f11096 + e803d8a commit db69cb8

3 files changed

Lines changed: 162 additions & 20 deletions

File tree

code/math/vecmat.cpp

Lines changed: 138 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -832,26 +832,38 @@ void vm_vector_2_matrix_gen_vectors(matrix *m)
832832
}
833833
}
834834

835-
matrix *vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
835+
/**
836+
* @brief Generates a matrix from a normalized uvec.
837+
*
838+
* @param[in,out] matrix The matrix to generate
839+
*
840+
* @details The matrix's uvec is used to generate the fvec and rvec
841+
*
842+
* @sa vm_vector_2_matrix_uvec(), vm_vector_2_matrix_uvec_norm()
843+
*/
844+
void vm_vector_2_matrix_gen_vectors_uvec(matrix* m)
836845
{
837-
vec3d fvec_norm;
838-
vm_vec_copy_normalize(&fvec_norm, fvec);
839-
fvec = &fvec_norm;
846+
vec3d* xvec = &m->vec.rvec;
847+
vec3d* yvec = &m->vec.uvec;
848+
vec3d* zvec = &m->vec.fvec;
840849

841-
vec3d uvec_norm;
842-
if (uvec != nullptr) {
843-
vm_vec_copy_normalize(&uvec_norm, uvec);
844-
uvec = &uvec_norm;
845-
}
850+
if ((yvec->xyz.x == 0.0f) && (yvec->xyz.z == 0.0f)) { // vec is straight up or down
851+
m->vec.rvec.xyz.x = 1.0f;
852+
m->vec.fvec.xyz.z = (yvec->xyz.y > 0.0f) ? 1.0f : -1.0f;
846853

847-
vec3d rvec_norm;
848-
if (rvec != nullptr) {
849-
vm_vec_copy_normalize(&rvec_norm, rvec);
850-
rvec = &rvec_norm;
854+
m->vec.rvec.xyz.y = m->vec.rvec.xyz.z = m->vec.fvec.xyz.x = m->vec.fvec.xyz.y = 0.0f;
851855
}
856+
else { //not straight up or down
852857

853-
// Call the actuall function for normalized vectors
854-
return vm_vector_2_matrix_norm(m, fvec, uvec, rvec);
858+
xvec->xyz.x = yvec->xyz.y;
859+
xvec->xyz.y = 0.0f;
860+
xvec->xyz.z = -yvec->xyz.x;
861+
862+
vm_vec_normalize(xvec);
863+
864+
vm_vec_cross(zvec, xvec, yvec);
865+
866+
}
855867
}
856868

857869
matrix *vm_vector_2_matrix_norm(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
@@ -915,6 +927,117 @@ matrix *vm_vector_2_matrix_norm(matrix *m, const vec3d *fvec, const vec3d *uvec,
915927
return m;
916928
}
917929

930+
matrix* vm_vector_2_matrix_uvec_norm(matrix* m, const vec3d* fvec, const vec3d* uvec, const vec3d* rvec)
931+
{
932+
933+
// sanity
934+
Assertion(fvec == nullptr || vm_vec_is_normalized(fvec), "if fvec is provided, it must be normalized!");
935+
Assertion(uvec == nullptr || vm_vec_is_normalized(uvec), "if uvec is provided, it must be normalized!");
936+
Assertion(rvec == nullptr || vm_vec_is_normalized(rvec), "if rvec is provided, it must be normalized!");
937+
Assertion(fvec != nullptr || uvec != nullptr, "vm_vector_2_matrix_uvec_norm requires one of fvec or uvec!");
938+
939+
matrix temp = vmd_identity_matrix;
940+
941+
vec3d* xvec = &temp.vec.rvec;
942+
vec3d* yvec = &temp.vec.uvec;
943+
vec3d* zvec = &temp.vec.fvec;
944+
945+
if (uvec != nullptr) { // use up vec as the 'primary'
946+
*yvec = *uvec;
947+
if (rvec == nullptr && fvec == nullptr) { //only up vec
948+
vm_vector_2_matrix_gen_vectors_uvec(&temp);
949+
}
950+
else if (fvec != nullptr){ //use fwd vec
951+
*zvec = *fvec;
952+
953+
vm_vec_cross(xvec, yvec, zvec);
954+
955+
//normalize new perpendicular vector
956+
vm_vec_normalize(xvec);
957+
958+
//now recompute fwd vector, in case it wasn't entirely perpendiclar
959+
vm_vec_cross(zvec, xvec, yvec);
960+
} else { // else use rvec
961+
*xvec = *rvec;
962+
963+
vm_vec_cross(zvec, xvec, yvec);
964+
965+
//normalize new perpendicular vector
966+
vm_vec_normalize(zvec);
967+
968+
//now recompute right vector, in case it wasn't entirely perpendiclar
969+
vm_vec_cross(xvec, yvec, zvec);
970+
}
971+
}
972+
else if (fvec != nullptr) { //use fwd vec as the 'primary'
973+
*zvec = *fvec;
974+
975+
if (rvec != nullptr) { // use rvec
976+
vm_vec_cross(yvec, zvec, xvec);
977+
978+
//normalize new perpendicular vector
979+
vm_vec_normalize(yvec);
980+
981+
//now recompute right vector, in case it wasn't entirely perpendiclar
982+
vm_vec_cross(xvec, yvec, zvec);
983+
} else { // only fwd vec
984+
vm_vector_2_matrix_gen_vectors(&temp);
985+
}
986+
}
987+
988+
// Copy the computed values into the output parameter
989+
*m = temp;
990+
return m;
991+
}
992+
993+
matrix *vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
994+
{
995+
vec3d fvec_norm;
996+
if (fvec != nullptr) {
997+
vm_vec_copy_normalize(&fvec_norm, fvec);
998+
fvec = &fvec_norm;
999+
}
1000+
1001+
vec3d uvec_norm;
1002+
if (uvec != nullptr) {
1003+
vm_vec_copy_normalize(&uvec_norm, uvec);
1004+
uvec = &uvec_norm;
1005+
}
1006+
1007+
vec3d rvec_norm;
1008+
if (rvec != nullptr) {
1009+
vm_vec_copy_normalize(&rvec_norm, rvec);
1010+
rvec = &rvec_norm;
1011+
}
1012+
1013+
// Call the actuall function for normalized vectors
1014+
return vm_vector_2_matrix_norm(m, fvec, uvec, rvec);
1015+
}
1016+
1017+
matrix* vm_vector_2_matrix_uvec(matrix* m, const vec3d* fvec, const vec3d* uvec, const vec3d* rvec)
1018+
{
1019+
vec3d fvec_norm;
1020+
if (fvec != nullptr) {
1021+
vm_vec_copy_normalize(&fvec_norm, fvec);
1022+
fvec = &fvec_norm;
1023+
}
1024+
1025+
vec3d uvec_norm;
1026+
if (uvec != nullptr) {
1027+
vm_vec_copy_normalize(&uvec_norm, uvec);
1028+
uvec = &uvec_norm;
1029+
}
1030+
1031+
vec3d rvec_norm;
1032+
if (rvec != nullptr) {
1033+
vm_vec_copy_normalize(&rvec_norm, rvec);
1034+
rvec = &rvec_norm;
1035+
}
1036+
1037+
// Call the actuall function for normalized vectors
1038+
return vm_vector_2_matrix_uvec_norm(m, fvec, uvec, rvec);
1039+
}
1040+
9181041

9191042
// rotates a vector through a matrix, writes to *dest and returns the pointer
9201043
// if m is a rotation matrix it will preserve the length of *src, so normalised vectors will remain normalised

code/math/vecmat.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,25 @@ matrix *vm_vec_ang_2_matrix(matrix *m, const vec3d *v, float a);
307307
matrix *vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec = nullptr, const vec3d *rvec = nullptr);
308308

309309

310+
/**
311+
* @brief Generates a matrix from one or more vectors
312+
*
313+
* @param[out] matrix The generated matrix. Does not need to be an Identity matrix
314+
* @param[in] fvec Vector referencing the forward direction (optional)
315+
* @param[in] uvec Vector referencing the up direction (Optional)
316+
* @param[in] rvec Vector referencing the right-hand direction (Optional)
317+
*
318+
* @returns Pointer to the generated matrix
319+
*
320+
* @note THIS FUCNTION SHOULD ONLY BE USED BY MODEL READING
321+
* in all other situations, the 'forward dominant' version vm_vector_2_matrix should be used
322+
* @note All vectors are optional, but at least one of fvec and uvec must be provided
323+
*
324+
* @sa vm_vector_2_matrix_uvec_norm
325+
*/
326+
matrix* vm_vector_2_matrix_uvec(matrix* m, const vec3d* fvec = nullptr, const vec3d* uvec = nullptr, const vec3d* rvec = nullptr);
327+
328+
310329
/**
311330
* @brief Generates a matrix from one or more normalized vectors
312331
*

code/model/modelread.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,18 +2086,18 @@ modelread_status read_model_file_no_subsys(polymodel * pm, const char* filename,
20862086
}
20872087
}
20882088

2089-
// make a matrix if we have at least the fvec
2090-
if (has_fvec)
2089+
// make a matrix if we have at least the fvec or uvec
2090+
if (has_fvec || has_uvec)
20912091
{
2092-
vm_vector_2_matrix(&sm->frame_of_reference, &fvec, has_uvec ? &uvec : nullptr, has_rvec ? &rvec : nullptr);
2092+
vm_vector_2_matrix_uvec(&sm->frame_of_reference, has_fvec ? &fvec : nullptr, has_uvec ? &uvec : nullptr, has_rvec ? &rvec : nullptr);
20932093

20942094
// if the look_at_offset is still the default value (hasn't been set by submodel properties), assume that
20952095
// by specifying the submodel orientation matrix we are also specifying the "looking" direction
20962096
if (sm->look_at_offset == -1.0f)
20972097
sm->look_at_offset = 0.0f;
20982098
}
2099-
else if (has_uvec || has_rvec)
2100-
Warning(LOCATION, "Improper custom orientation matrix for subsystem %s; you must define an $fvec", sm->name);
2099+
else if (has_rvec)
2100+
Warning(LOCATION, "Improper custom orientation matrix for subsystem %s; you must define an $fvec or $uvec", sm->name);
21012101
}
21022102

21032103
{

0 commit comments

Comments
 (0)