change_view.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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 dafault 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 data nviz data
  66. \param x_pos,y_pos x,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 data nviz data
  112. \param height height value (world coordinates)
  113. \return 1
  114. */
  115. int Nviz_set_viewpoint_height(double height)
  116. {
  117. float from[3];
  118. G_debug(1, "Nviz_set_viewpoint_height(): value = %f", height);
  119. GS_get_from_real(from);
  120. if (height != from[Z]) {
  121. from[Z] = height;
  122. GS_moveto_real(from);
  123. /*
  124. normalize (from);
  125. GS_setlight_position(1, from[X], from[Y], from[Z], 0);
  126. */
  127. /* Nviz_draw_quick(data); */
  128. }
  129. return 1;
  130. }
  131. void Nviz_get_viewpoint_height(double *height)
  132. {
  133. float from[3];
  134. G_debug(1, "Nviz_get_viewpoint_height():");
  135. GS_get_from_real(from);
  136. *height = from[Z];
  137. }
  138. /*!
  139. \brief Change viewpoint perspective (field of view)
  140. \param data nviz data
  141. \param persp perspective value (0-100, in degrees)
  142. \return 1
  143. */
  144. int Nviz_set_viewpoint_persp(int persp)
  145. {
  146. int fov;
  147. G_debug(1, "Nviz_set_viewpoint_persp(): value = %d", persp);
  148. fov = (int)(10 * persp);
  149. GS_set_fov(fov);
  150. /* Nviz_draw_quick(data); */
  151. return 1;
  152. }
  153. /*!
  154. \brief Change viewpoint twist
  155. \param data nviz data
  156. \param persp twist value (-180-180, in degrees)
  157. \return 1
  158. */
  159. int Nviz_set_viewpoint_twist(int twist)
  160. {
  161. G_debug(1, "Nviz_set_viewpoint_twist(): value = %d", twist);
  162. GS_set_twist(10 * twist);
  163. /* Nviz_draw_quick(data); */
  164. return 1;
  165. }
  166. /*!
  167. \brief Change z-exag value
  168. \param data nviz data
  169. \param exag exag value
  170. \return 1
  171. */
  172. int Nviz_change_exag(nv_data * data, double exag)
  173. {
  174. double temp;
  175. G_debug(1, "Nviz_change_exag(): value = %f", exag);
  176. temp = GS_global_exag();
  177. if (exag != temp) {
  178. GS_set_global_exag(exag);
  179. Nviz_update_ranges(data);
  180. /* Nviz_draw_quick(data); */
  181. }
  182. return 1;
  183. }
  184. /*!
  185. \brief Change focused point
  186. \param sx,sy screen coordinates
  187. \return 1
  188. */
  189. int Nviz_look_here(double sx, double sy)
  190. {
  191. G_debug(1, "Nviz_look_here(): screen coordinates = %f %f", sx, sy);
  192. GS_look_here(sx, sy);
  193. return 1;
  194. }
  195. /*!
  196. \brief Get current modelview matrix
  197. */
  198. void Nviz_get_modelview(double *modelMatrix)
  199. {
  200. glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
  201. }
  202. /*!
  203. \brief Set rotation parameters
  204. Rotate scene by given parameters related to mouse drag event
  205. (difference from current state).
  206. Coordinates determine the second point of rotation axis,
  207. the first point is (0, 0, 0).
  208. \param angle angle
  209. \param x,y,z axis coordinate
  210. */
  211. void Nviz_set_rotation(double angle, double x, double y, double z)
  212. {
  213. G_debug(3, "Nviz_set_rotation(): angle = %f, x = %f, y = %f, z = %f", angle, x, y, z);
  214. GS_set_rotation(angle, x, y, z);
  215. }
  216. /*!
  217. \brief Stop scene rotation
  218. */
  219. void Nviz_unset_rotation(void)
  220. {
  221. GS_unset_rotation();
  222. }
  223. /*!
  224. \brief Stop scene rotation
  225. */
  226. void Nviz_init_rotation(void)
  227. {
  228. GS_init_rotation();
  229. }
  230. /*!
  231. \brief Fly through the scene
  232. Computes parameters needed for moving scene.
  233. Changes viewpoint and viewdir.
  234. Based on visualization/nviz/src/togl_flythrough.c and simplified.
  235. \param fly_info values computed from mouse movement
  236. \param scale rate of movement
  237. \param lateral type of movement
  238. */
  239. void Nviz_flythrough(nv_data *data, float *fly_info, int *scale, int lateral)
  240. {
  241. float dir[3], from[4], cur_from[4], cur_dir[4];
  242. float speed, h, p, sh, ch, sp, cp;
  243. float diff_x, diff_y, diff_z;
  244. float quasi_zero;
  245. quasi_zero = 0.0001;
  246. GS_get_from(cur_from);
  247. GS_get_viewdir(cur_dir);
  248. p = asin(cur_dir[Z]);
  249. h = atan2(- cur_dir[X], - cur_dir[Y]);
  250. speed = scale[0] * fly_info[0];
  251. h += scale[1] * fly_info[1]; /* change heading */
  252. if (!lateral) /* in case of "lateral" doesn't change pitch */
  253. p -= scale[1] * fly_info[2];
  254. h = fmod(h + M_PI, 2 * M_PI) - M_PI;
  255. sh = sin(h);
  256. ch = cos(h);
  257. sp = sin(p);
  258. cp = cos(p);
  259. dir[X] = -sh * cp;
  260. dir[Y] = -ch * cp;
  261. dir[Z] = sp;
  262. if (lateral) {
  263. from[X] = cur_from[X] + speed * dir[Y];
  264. from[Y] = cur_from[Y] - speed * dir[X];
  265. from[Z] = cur_from[Z] + scale[0] * fly_info[2];
  266. }
  267. else {
  268. from[X] = cur_from[X] + speed * dir[X];
  269. from[Y] = cur_from[Y] + speed * dir[Y];
  270. /* not sure how this should behave (change Z coord or not ?)*/
  271. from[Z] = cur_from[Z]; /* + speed * dir[Z]*/
  272. }
  273. diff_x = fabs(cur_dir[X] - dir[X]);
  274. diff_y = fabs(cur_dir[Y] - dir[Y]);
  275. diff_z = fabs(cur_dir[Z] - dir[Z]);
  276. if ( /* something has changed */
  277. (diff_x > quasi_zero) || (diff_y > quasi_zero) ||
  278. (diff_z > quasi_zero) || (cur_from[X] != from[X]) ||
  279. (cur_from[Y] != from[Y]) || (cur_from[Z] != from[Z])
  280. ) {
  281. GS_moveto(from);
  282. GS_set_viewdir(dir); /* calls gsd_set_view */
  283. }
  284. }