EquirectangularToFovBase.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // EquirectangularToFovBase.cpp
  2. #include "EquirectangularToFovBase.h"
  3. #include "Types.h"
  4. #include "Util.h"
  5. #include "../arffHelper/ArffUtil.h"
  6. #include <iostream>
  7. #include <cstdlib>
  8. #include <string>
  9. #include <algorithm>
  10. #include <cassert>
  11. #define PI 3.14159265
  12. #define EPSILON 0.001
  13. using namespace std;
  14. const char *c_horHeadAttName = "x_head";
  15. const char *c_verHeadAttName = "y_head";
  16. const char *c_tiltHeadAttName = "angle_deg_head";
  17. const char *c_fovWidthDegName = "fov_width_deg";
  18. const char *c_fovHeightDegName = "fov_height_deg";
  19. const char *c_fovWidthPxName = "fov_width_px";
  20. const char *c_fovHeightPxName = "fov_height_px";
  21. // PUBLIC:
  22. EquirectangularToFovBase::EquirectangularToFovBase(Arff* pArff)
  23. {
  24. if (pArff == NULL)
  25. {
  26. cout << "ERROR: you provided NULL pointer. Could not initialize." << endl;
  27. exit(-1);
  28. }
  29. m_pArff = pArff;
  30. bool res = ArffUtil::GetTXYCindex(m_pArff, m_timeInd, m_xInd, m_yInd, m_confInd);
  31. if (!res)
  32. {
  33. cout << "ERROR: could not find time or x or y or confidence in the provided ARFF file." << endl;
  34. exit(-1);
  35. }
  36. // get experiment values
  37. res = true;
  38. res &= m_pArff->GetAttIndex(c_horHeadAttName, m_horHeadInd);
  39. res &= m_pArff->GetAttIndex(c_verHeadAttName, m_verHeadInd);
  40. res &= m_pArff->GetAttIndex(c_tiltHeadAttName, m_tiltHeadInd);
  41. if (!res)
  42. {
  43. cout << "ERROR: could not find " << c_horHeadAttName << " or " << c_verHeadAttName << " or " << c_tiltHeadAttName << " in the provided ARFF file." << endl;
  44. exit(-1);
  45. }
  46. string value;
  47. if(!m_pArff->GetMetadata(c_fovWidthDegName, value))
  48. {
  49. cout << "ERROR: METADATA " << c_fovWidthDegName << " is missing" << endl;
  50. exit(-1);
  51. }
  52. m_fovWidthDeg = stod(value);
  53. if (!m_pArff->GetMetadata(c_fovHeightDegName, value))
  54. {
  55. cout << "ERROR: METADATA " << c_fovHeightDegName << " is missing" << endl;
  56. exit(-1);
  57. }
  58. m_fovHeightDeg = stod(value);
  59. if (!m_pArff->GetMetadata(c_fovWidthPxName, value))
  60. {
  61. cout << "ERROR: METADATA " << c_fovWidthPxName << " is missing" << endl;
  62. exit(-1);
  63. }
  64. m_fovWidthPx = stoi(value);
  65. if (!m_pArff->GetMetadata(c_fovHeightPxName, value))
  66. {
  67. cout << "ERROR: METADATA " << c_fovHeightPxName << " is missing" << endl;
  68. exit(-1);
  69. }
  70. m_fovHeightPx = stoi(value);
  71. }
  72. /*virtual*/ EquirectangularToFovBase::~EquirectangularToFovBase()
  73. {
  74. }
  75. // PROTECTED:
  76. void EquirectangularToFovBase::EquirectangularToSpherical(unsigned int xEq, unsigned int yEq, unsigned int widthPx, unsigned int heightPx, double *horRads, double *verRads)
  77. {
  78. *horRads = (xEq * 2.0 * PI) / widthPx;
  79. *verRads = (yEq * PI) / heightPx;
  80. }
  81. void EquirectangularToFovBase::SphericalToEquirectangular(double horRads, double verRads, unsigned int widthPx, unsigned int heightPx, unsigned int *xEq, unsigned int *yEq)
  82. {
  83. int x = (int)((horRads / (2.0 * PI)) * widthPx + 0.5); // round double to closer int
  84. int y = (int)((verRads / PI) * heightPx + 0.5);
  85. // make sure returned values are within the video
  86. if (y < 0)
  87. {
  88. y = -y;
  89. x += widthPx / 2;
  90. }
  91. if (y >= (int)heightPx)
  92. {
  93. y = 2 * heightPx - y - 1;
  94. x += widthPx / 2;
  95. }
  96. *yEq = (unsigned int) y;
  97. if (x < 0)
  98. x = widthPx + x - 1;
  99. else if (x >= (int)widthPx)
  100. x -= widthPx;
  101. *xEq = (unsigned int) x;
  102. }
  103. void EquirectangularToFovBase::SphericalToCartesian(double horRads, double verRads, Vec3 *cart)
  104. {
  105. cart->x = sin(verRads)*cos(horRads);
  106. cart->y = cos(verRads);
  107. cart->z = sin(verRads)*sin(horRads);
  108. }
  109. void EquirectangularToFovBase::CartesianToSpherical(Vec3 cart, double *horRads, double *verRads)
  110. {
  111. *horRads = atan2(cart.z, cart.x);
  112. *verRads = acos(cart.y);
  113. }
  114. void EquirectangularToFovBase::GetHeadPos(long int time, double *x, double *y, double *tilt)
  115. {
  116. unsigned int ind = ArffUtil::FindPosition(m_pArff, m_timeInd, time);
  117. GetHeadPos(ind, x, y, tilt);
  118. }
  119. void EquirectangularToFovBase::GetHeadPos(unsigned int ind, double *x, double *y, double *tilt)
  120. {
  121. *x = (*m_pArff)[ind][m_horHeadInd];
  122. *y = (*m_pArff)[ind][m_verHeadInd];
  123. *tilt = (*m_pArff)[ind][m_tiltHeadInd];
  124. }
  125. void EquirectangularToFovBase::GetEyePos(unsigned int ind, double *x, double *y)
  126. {
  127. *x = (*m_pArff)[ind][m_xInd];
  128. *y = (*m_pArff)[ind][m_yInd];
  129. }
  130. Matrix33 EquirectangularToFovBase::HeadToVideoRotation(Vec3 head, double headTiltRads, Vec3 video)
  131. {
  132. Matrix33 headToRef = YZXrotation(head, -headTiltRads);
  133. Matrix33 videoToRef = YZXrotation(video, 0);
  134. Matrix33 ret = videoToRef*Transpose(headToRef);
  135. return ret;
  136. }
  137. Matrix33 EquirectangularToFovBase::YZXrotation(Vec3 vec, double tiltRads)
  138. {
  139. // we follow the Trait-Bryan angles with Y-Z'-X" intrinsic rotations
  140. double theta = asin(vec.y);
  141. double psi = 0;
  142. if (abs(theta) < PI/2.0 - 0.01)
  143. psi = atan2(vec.z, vec.x);
  144. /*
  145. Matrix33 Yrot;
  146. Yrot.mat[0][0] = cos(psi);
  147. Yrot.mat[0][1] = 0;
  148. Yrot.mat[0][2] = sin(psi);
  149. Yrot.mat[1][0] = 0;
  150. Yrot.mat[1][1] = 1;
  151. Yrot.mat[1][2] = 0;
  152. Yrot.mat[2][0] = -sin(psi);
  153. Yrot.mat[2][1] = 0;
  154. Yrot.mat[2][2] = cos(psi);
  155. Matrix33 Zrot;
  156. Zrot.mat[0][0] = cos(theta);
  157. Zrot.mat[0][1] = -sin(theta);
  158. Zrot.mat[0][2] = 0;
  159. Zrot.mat[1][0] = sin(theta);
  160. Zrot.mat[1][1] = cos(theta);
  161. Zrot.mat[1][2] = 0;
  162. Zrot.mat[2][0] = 0;
  163. Zrot.mat[2][1] = 0;
  164. Zrot.mat[2][2] = 1;
  165. Matrix33 Xrot;
  166. Xrot.mat[0][0] = 1;
  167. Xrot.mat[0][1] = 0;
  168. Xrot.mat[0][2] = 0;
  169. Xrot.mat[1][0] = 0;
  170. Xrot.mat[1][1] = cos(tiltRads);
  171. Xrot.mat[1][2] = -sin(tiltRads);
  172. Xrot.mat[2][0] = 0;
  173. Xrot.mat[2][1] = sin(tiltRads);
  174. Xrot.mat[2][2] = cos(tiltRads);
  175. Matrix33 ret = Xrot*Zrot*Yrot;
  176. */
  177. Matrix33 ret;
  178. ret.mat[0][0] = cos(theta)*cos(psi);
  179. ret.mat[0][1] = -sin(theta);
  180. ret.mat[0][2] = cos(theta)*sin(psi);
  181. ret.mat[1][0] = cos(tiltRads)*sin(theta)*cos(psi) + sin(tiltRads)*sin(psi);
  182. ret.mat[1][1] = cos(tiltRads)*cos(theta);
  183. ret.mat[1][2] = cos(tiltRads)*sin(theta)*sin(psi) - sin(tiltRads)*cos(psi);
  184. ret.mat[2][0] = sin(tiltRads)*sin(theta)*cos(psi) - cos(tiltRads)*sin(psi);
  185. ret.mat[2][1] = sin(tiltRads)*cos(theta);
  186. ret.mat[2][2] = sin(tiltRads)*sin(theta)*sin(psi) + cos(tiltRads)*cos(psi);
  187. return ret;
  188. }