change_view.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*!
  2. \file lib/nviz/change_view.c
  3. \brief Nviz library -- Change view settings
  4. Based on visualization/nviz/src/change_view.c
  5. (C) 2008, 2010 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
  9. */
  10. #include <math.h>
  11. #include <grass/glocale.h>
  12. #include <grass/nviz.h>
  13. /*!
  14. \brief GL canvas resized
  15. \param width window width
  16. \param height window height
  17. \return 1 on success
  18. \return 0 on failure (window resized by default to 20x20 px)
  19. */
  20. int Nviz_resize_window(int width, int height)
  21. {
  22. int ret;
  23. ret = 1;
  24. if (width < 1 || height < 1) {
  25. width = 20;
  26. height = 20;
  27. ret = 0;
  28. }
  29. G_debug(1, "Nviz_resize_window(): width = %d height = %d", width, height);
  30. GS_set_viewport(0, width, 0, height);
  31. /* GS_clear(0x0000FF); causes red flash - debug only */
  32. GS_set_draw(GSD_BACK);
  33. GS_ready_draw();
  34. GS_alldraw_wire();
  35. GS_done_draw();
  36. return ret;
  37. }
  38. /*!
  39. \brief Update ranges
  40. Call whenever a new surface is added, deleted, or exag changes
  41. \return 1
  42. */
  43. int Nviz_update_ranges(nv_data * dc)
  44. {
  45. float zmin, zmax, exag;
  46. GS_get_longdim(&(dc->xyrange));
  47. dc->zrange = 0.;
  48. /* Zrange is based on a minimum of Longdim */
  49. if (GS_global_exag()) {
  50. exag = GS_global_exag();
  51. dc->zrange = dc->xyrange / exag;
  52. }
  53. else {
  54. exag = 1.0;
  55. }
  56. GS_get_zrange_nz(&zmin, &zmax); /* actual */
  57. zmax = zmin + (3. * dc->xyrange / exag);
  58. zmin = zmin - (2. * dc->xyrange / exag);
  59. if ((zmax - zmin) > dc->zrange)
  60. dc->zrange = zmax - zmin;
  61. return 1;
  62. }
  63. /*!
  64. \brief Change position of view
  65. \param x_pos x position (model coordinates)
  66. \param y_pos y position (model coordinates)
  67. \return 1
  68. */
  69. int Nviz_set_viewpoint_position(double x_pos, double y_pos)
  70. {
  71. float xpos, ypos, from[3];
  72. float tempx, tempy;
  73. xpos = x_pos;
  74. xpos = (xpos < 0) ? 0 : (xpos > 1.0) ? 1.0 : xpos;
  75. ypos = 1.0 - y_pos;
  76. ypos = (ypos < 0) ? 0 : (ypos > 1.0) ? 1.0 : ypos;
  77. if (x_pos < 0.0 || x_pos > 1.0 || y_pos < 0.0 || y_pos > 1.0) {
  78. G_debug(3, "Invalid view position coordinates, using %f,%f",
  79. xpos, 1.0 - ypos);
  80. }
  81. G_debug(1, "Nviz_set_viewpoint_position(): x = %f y = %f", x_pos, y_pos);
  82. GS_get_from(from);
  83. tempx = xpos * RANGE - RANGE_OFFSET;
  84. tempy = ypos * RANGE - RANGE_OFFSET;
  85. if ((from[X] != tempx) || (from[Y] != tempy)) {
  86. from[X] = tempx;
  87. from[Y] = tempy;
  88. GS_moveto(from);
  89. /* Nviz_draw_quick(data); */
  90. }
  91. return 1;
  92. }
  93. void Nviz_get_viewpoint_position(double *x_pos, double *y_pos)
  94. {
  95. float from[3];
  96. double xpos, ypos;
  97. GS_get_from(from);
  98. xpos = (from[X] + RANGE_OFFSET) / RANGE;
  99. ypos = (from[Y] + RANGE_OFFSET) / RANGE;
  100. *x_pos = xpos;
  101. *x_pos = (*x_pos < 0) ? 0 : (*x_pos > 1.0) ? 1.0 : *x_pos;
  102. *y_pos = 1.0 - ypos;
  103. *y_pos = (*y_pos < 0) ? 0 : (*y_pos > 1.0) ? 1.0 : *y_pos;
  104. if (xpos < 0.0 || xpos > 1.0 || ypos < 0.0 || ypos > 1.0) {
  105. G_debug(3, "Invalid view position coordinates, using %f,%f",
  106. *x_pos, 1.0 - *y_pos);
  107. }
  108. }
  109. /*!
  110. \brief Change viewpoint height
  111. \param height height value (world coordinates)
  112. \return 1
  113. */
  114. int Nviz_set_viewpoint_height(double height)
  115. {
  116. float from[3];
  117. G_debug(1, "Nviz_set_viewpoint_height(): value = %f", height);
  118. GS_get_from_real(from);
  119. if (height != from[Z]) {
  120. from[Z] = height;
  121. GS_moveto_real(from);
  122. /*
  123. normalize (from);
  124. GS_setlight_position(1, from[X], from[Y], from[Z], 0);
  125. */
  126. /* Nviz_draw_quick(data); */
  127. }
  128. return 1;
  129. }
  130. void Nviz_get_viewpoint_height(double *height)
  131. {
  132. float from[3];
  133. G_debug(1, "Nviz_get_viewpoint_height():");
  134. GS_get_from_real(from);
  135. *height = from[Z];
  136. }
  137. /*!
  138. \brief Change viewpoint perspective (field of view)
  139. \param persp perspective value (0-100, in degrees)
  140. \return 1
  141. */
  142. int Nviz_set_viewpoint_persp(int persp)
  143. {
  144. int fov;
  145. G_debug(1, "Nviz_set_viewpoint_persp(): value = %d", persp);
  146. fov = (int)(10 * persp);
  147. GS_set_fov(fov);
  148. /* Nviz_draw_quick(data); */
  149. return 1;
  150. }
  151. /*!
  152. \brief Change viewpoint twist
  153. \param twist persp twist value (-180-180, in degrees)
  154. \return 1
  155. */
  156. int Nviz_set_viewpoint_twist(int twist)
  157. {
  158. G_debug(1, "Nviz_set_viewpoint_twist(): value = %d", twist);
  159. GS_set_twist(10 * twist);
  160. /* Nviz_draw_quick(data); */
  161. return 1;
  162. }
  163. /*!
  164. \brief Change z-exag value
  165. \param data nviz data
  166. \param exag exag value
  167. \return 1
  168. */
  169. int Nviz_change_exag(nv_data * data, double exag)
  170. {
  171. double temp;
  172. G_debug(1, "Nviz_change_exag(): value = %f", exag);
  173. temp = GS_global_exag();
  174. if (exag != temp) {
  175. GS_set_global_exag(exag);
  176. Nviz_update_ranges(data);
  177. /* Nviz_draw_quick(data); */
  178. }
  179. return 1;
  180. }
  181. /*!
  182. \brief Change focused point
  183. \param sx,sy screen coordinates
  184. \return 1
  185. */
  186. int Nviz_look_here(double sx, double sy)
  187. {
  188. G_debug(1, "Nviz_look_here(): screen coordinates = %f %f", sx, sy);
  189. GS_look_here(sx, sy);
  190. return 1;
  191. }
  192. /*!
  193. \brief Get current modelview matrix
  194. */
  195. void Nviz_get_modelview(double *modelMatrix)
  196. {
  197. glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
  198. }
  199. /*!
  200. \brief Set rotation parameters
  201. Rotate scene by given parameters related to mouse drag event
  202. (difference from current state).
  203. Coordinates determine the second point of rotation axis,
  204. the first point is (0, 0, 0).
  205. \param angle angle
  206. \param x,y,z axis coordinate
  207. */
  208. void Nviz_set_rotation(double angle, double x, double y, double z)
  209. {
  210. G_debug(3, "Nviz_set_rotation(): angle = %f, x = %f, y = %f, z = %f", angle, x, y, z);
  211. GS_set_rotation(angle, x, y, z);
  212. }
  213. /*!
  214. \brief Stop scene rotation
  215. */
  216. void Nviz_unset_rotation(void)
  217. {
  218. GS_unset_rotation();
  219. }
  220. /*!
  221. \brief Stop scene rotation
  222. */
  223. void Nviz_init_rotation(void)
  224. {
  225. GS_init_rotation();
  226. }
  227. /*!
  228. \brief Fly through the scene
  229. Computes parameters needed for moving scene.
  230. Changes viewpoint and viewdir.
  231. Based on visualization/nviz/src/togl_flythrough.c and simplified.
  232. \param data nviz data
  233. \param fly_info values computed from mouse movement
  234. \param scale rate of movement
  235. \param lateral type of movement
  236. */
  237. void Nviz_flythrough(nv_data *data, float *fly_info, int *scale, int lateral)
  238. {
  239. float dir[3], from[4], cur_from[4], cur_dir[4];
  240. float speed, h, p, sh, ch, sp, cp;
  241. float diff_x, diff_y, diff_z;
  242. float quasi_zero;
  243. quasi_zero = 0.0001;
  244. GS_get_from(cur_from);
  245. GS_get_viewdir(cur_dir);
  246. p = asin(cur_dir[Z]);
  247. h = atan2(- cur_dir[X], - cur_dir[Y]);
  248. speed = scale[0] * fly_info[0];
  249. h += scale[1] * fly_info[1]; /* change heading */
  250. if (!lateral) /* in case of "lateral" doesn't change pitch */
  251. p -= scale[1] * fly_info[2];
  252. h = fmod(h + M_PI, 2 * M_PI) - M_PI;
  253. sh = sin(h);
  254. ch = cos(h);
  255. sp = sin(p);
  256. cp = cos(p);
  257. dir[X] = -sh * cp;
  258. dir[Y] = -ch * cp;
  259. dir[Z] = sp;
  260. if (lateral) {
  261. from[X] = cur_from[X] + speed * dir[Y];
  262. from[Y] = cur_from[Y] - speed * dir[X];
  263. from[Z] = cur_from[Z] + scale[0] * fly_info[2];
  264. }
  265. else {
  266. from[X] = cur_from[X] + speed * dir[X];
  267. from[Y] = cur_from[Y] + speed * dir[Y];
  268. /* not sure how this should behave (change Z coord or not ?)*/
  269. from[Z] = cur_from[Z]; /* + speed * dir[Z]*/
  270. }
  271. diff_x = fabs(cur_dir[X] - dir[X]);
  272. diff_y = fabs(cur_dir[Y] - dir[Y]);
  273. diff_z = fabs(cur_dir[Z] - dir[Z]);
  274. if ( /* something has changed */
  275. (diff_x > quasi_zero) || (diff_y > quasi_zero) ||
  276. (diff_z > quasi_zero) || (cur_from[X] != from[X]) ||
  277. (cur_from[Y] != from[Y]) || (cur_from[Z] != from[Z])
  278. ) {
  279. GS_moveto(from);
  280. GS_set_viewdir(dir); /* calls gsd_set_view */
  281. }
  282. }