@@ -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
857869matrix *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
0 commit comments