gsd_views.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*!
  2. \file lib/ogsf/gsd_views.c
  3. \brief OGSF library - manipulating views (lower level functions)
  4. GRASS OpenGL gsurf OGSF Library
  5. (C) 1999-2008 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Bill Brown USACERL (January 1993)
  11. \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
  12. */
  13. #include <grass/config.h>
  14. #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
  15. #include <GL/gl.h>
  16. #include <GL/glu.h>
  17. #elif defined(OPENGL_AQUA)
  18. #include <OpenGL/gl.h>
  19. #include <OpenGL/glu.h>
  20. #endif
  21. #include <grass/ogsf.h>
  22. #include "math.h"
  23. /*!
  24. \brief ADD
  25. \param vect
  26. \param sx, sy screen coordinates
  27. \return 1
  28. */
  29. int gsd_get_los(float (*vect)[3], short sx, short sy)
  30. {
  31. double fx, fy, fz, tx, ty, tz;
  32. GLdouble modelMatrix[16], projMatrix[16];
  33. GLint viewport[4];
  34. GS_ready_draw();
  35. glPushMatrix();
  36. gsd_do_scale(1);
  37. glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
  38. glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
  39. glGetIntegerv(GL_VIEWPORT, viewport);
  40. glPopMatrix();
  41. /* OGLXXX XXX I think this is backwards gluProject(XXX); */
  42. /* WAS: mapw(Vobj, sx, sy, &fx, &fy, &fz, &tx, &ty, &tz); */
  43. gluUnProject((GLdouble) sx, (GLdouble) sy, 0.0, modelMatrix,
  44. projMatrix, viewport, &fx, &fy, &fz);
  45. gluUnProject((GLdouble) sx, (GLdouble) sy, 1.0, modelMatrix,
  46. projMatrix, viewport, &tx, &ty, &tz);
  47. vect[FROM][X] = fx;
  48. vect[FROM][Y] = fy;
  49. vect[FROM][Z] = fz;
  50. vect[TO][X] = tx;
  51. vect[TO][Y] = ty;
  52. vect[TO][Z] = tz;
  53. /* DEBUG - should just be a dot */
  54. /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
  55. glDrawBuffer((1) ? GL_FRONT : GL_BACK);
  56. glPushMatrix();
  57. gsd_do_scale(1);
  58. gsd_linewidth(3);
  59. gsd_color_func(0x8888FF);
  60. /* OGLXXX for multiple, independent line segments: use GL_LINES */
  61. glBegin(GL_LINE_STRIP);
  62. glVertex3fv(vect[FROM]);
  63. glVertex3fv(vect[TO]);
  64. glEnd();
  65. gsd_linewidth(1);
  66. glPopMatrix();
  67. /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
  68. glDrawBuffer((0) ? GL_FRONT : GL_BACK);
  69. return (1);
  70. }
  71. #if 0
  72. /*!
  73. \brief Set view
  74. Establishes viewing & projection matrices
  75. \param gv view (geoview)
  76. \param dp display (geodisplay)
  77. */
  78. void gsd_set_view(geoview * gv, geodisplay * gd)
  79. {
  80. double up[3];
  81. GLint mm;
  82. /* will expand when need to check for in focus, ortho, etc. */
  83. gsd_check_focus(gv);
  84. gsd_get_zup(gv, up);
  85. gd->aspect = GS_get_aspect();
  86. glGetIntegerv(GL_MATRIX_MODE, &mm);
  87. glMatrixMode(GL_PROJECTION);
  88. glLoadIdentity();
  89. gluPerspective((double).1 * (gv->fov), (double)gd->aspect,
  90. (double)gd->nearclip, (double)gd->farclip);
  91. glMatrixMode(mm);
  92. glLoadIdentity();
  93. /* update twist parm */
  94. glRotatef((float)(gv->twist / 10.), 0.0, 0.0, 1.0);
  95. /* OGLXXX lookat: replace UPx with vector */
  96. gluLookAt((double)gv->from_to[FROM][X], (double)gv->from_to[FROM][Y],
  97. (double)gv->from_to[FROM][Z], (double)gv->from_to[TO][X],
  98. (double)gv->from_to[TO][Y], (double)gv->from_to[TO][Z],
  99. (double)up[X], (double)up[Y], (double)up[Z]);
  100. /* have to redefine clipping planes when view changes */
  101. gsd_update_cplanes();
  102. return;
  103. }
  104. #endif
  105. /*!
  106. \brief Set view
  107. Establishes viewing & projection matrices
  108. \param gv view (geoview)
  109. \param dp display (geodisplay)
  110. */
  111. void gsd_set_view(geoview * gv, geodisplay * gd)
  112. {
  113. double up[3];
  114. float pos[3];
  115. int i;
  116. GLdouble modelMatrix[16];
  117. GLint mm;
  118. /* will expand when need to check for in focus, ortho, etc. */
  119. gsd_check_focus(gv);
  120. gsd_get_zup(gv, up);
  121. gd->aspect = GS_get_aspect();
  122. glGetIntegerv(GL_MATRIX_MODE, &mm);
  123. glMatrixMode(GL_PROJECTION);
  124. glLoadIdentity();
  125. gluPerspective((double).1 * (gv->fov), (double)gd->aspect,
  126. (double)gd->nearclip, (double)gd->farclip);
  127. glMatrixMode(mm);
  128. glLoadIdentity();
  129. /* update twist parm */
  130. glRotatef((float)(gv->twist / 10.), 0.0, 0.0, 1.0);
  131. /* OGLXXX lookat: replace UPx with vector */
  132. gluLookAt((double)gv->from_to[FROM][X], (double)gv->from_to[FROM][Y],
  133. (double)gv->from_to[FROM][Z], (double)gv->from_to[TO][X],
  134. (double)gv->from_to[TO][Y], (double)gv->from_to[TO][Z],
  135. (double)up[X], (double)up[Y], (double)up[Z]);
  136. /* rotate to get rotation matrix and then save it*/
  137. if (gv->rotate.do_rot) {
  138. glPushMatrix();
  139. glLoadMatrixd(gv->rotate.rotMatrix);
  140. glRotated(gv->rotate.rot_angle, gv->rotate.rot_axes[0],
  141. gv->rotate.rot_axes[1], gv->rotate.rot_axes[2]);
  142. glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
  143. for (i = 0; i < 16; i++) {
  144. gv->rotate.rotMatrix[i] = modelMatrix[i];
  145. }
  146. glPopMatrix();
  147. }
  148. gs_get_datacenter(pos);
  149. gsd_surf2model(pos);
  150. /* translate rotation center to view center, rotate and translate back */
  151. glTranslatef(pos[0], pos[1], pos[2]);
  152. glMultMatrixd(gv->rotate.rotMatrix);
  153. glTranslatef(-pos[0], -pos[1], -pos[2]);
  154. /* have to redefine clipping planes when view changes */
  155. gsd_update_cplanes();
  156. return;
  157. }
  158. /*!
  159. \brief Check focus
  160. \param gv view (geoview)
  161. */
  162. void gsd_check_focus(geoview * gv)
  163. {
  164. float zmax, zmin;
  165. GS_get_zrange(&zmin, &zmax, 0);
  166. if (gv->infocus) {
  167. GS_v3eq(gv->from_to[TO], gv->real_to);
  168. gv->from_to[TO][Z] -= zmin;
  169. GS_v3mult(gv->from_to[TO], gv->scale);
  170. gv->from_to[TO][Z] *= gv->vert_exag;
  171. GS_v3normalize(gv->from_to[FROM], gv->from_to[TO]);
  172. }
  173. return;
  174. }
  175. /*!
  176. \brief Get z-up vector (z-direction)
  177. \param gv view (geoview)
  178. \param up up vector
  179. */
  180. void gsd_get_zup(geoview * gv, double *up)
  181. {
  182. float alpha;
  183. float zup[3], fup[3];
  184. /* neg alpha OK since sin(-x) = -sin(x) */
  185. alpha =
  186. (2.0 * atan(1.0)) - acos(gv->from_to[FROM][Z] - gv->from_to[TO][Z]);
  187. zup[X] = gv->from_to[TO][X];
  188. zup[Y] = gv->from_to[TO][Y];
  189. if (sin(alpha)) {
  190. zup[Z] = gv->from_to[TO][Z] + 1 / sin(alpha);
  191. }
  192. else {
  193. zup[Z] = gv->from_to[FROM][Z] + 1.0;
  194. }
  195. GS_v3dir(gv->from_to[FROM], zup, fup);
  196. up[X] = fup[X];
  197. up[Y] = fup[Y];
  198. up[Z] = fup[Z];
  199. return;
  200. }
  201. /*!
  202. \brief ADD
  203. \param gv view (geoview)
  204. \return ?
  205. */
  206. int gsd_zup_twist(geoview * gv)
  207. {
  208. float fr_to[2][4];
  209. float look_theta, pi;
  210. float alpha, beta;
  211. float zup[3], yup[3], zupmag, yupmag;
  212. pi = 4.0 * atan(1.0);
  213. /* *************************************************************** */
  214. /* This block of code is used to keep pos z in the up direction,
  215. * correcting for SGI system default which is pos y in the up
  216. * direction. Involves finding up vectors for both y up and
  217. * z up, then determining angle between them. LatLon mode uses y as
  218. * up direction instead of z, so no correction necessary. Next rewrite,
  219. * we should use y as up for all drawing.
  220. */
  221. GS_v3eq(fr_to[FROM], gv->from_to[FROM]);
  222. GS_v3eq(fr_to[TO], gv->from_to[TO]);
  223. /* neg alpha OK since sin(-x) = -sin(x) */
  224. alpha = pi / 2.0 - acos(fr_to[FROM][Z] - fr_to[TO][Z]);
  225. zup[X] = fr_to[TO][X];
  226. zup[Y] = fr_to[TO][Y];
  227. if (sin(alpha)) {
  228. zup[Z] = fr_to[TO][Z] + 1 / sin(alpha);
  229. }
  230. else {
  231. zup[Z] = fr_to[FROM][Z] + 1.0;
  232. }
  233. zupmag = GS_distance(fr_to[FROM], zup);
  234. yup[X] = fr_to[TO][X];
  235. yup[Z] = fr_to[TO][Z];
  236. /* neg beta OK since sin(-x) = -sin(x) */
  237. beta = pi / 2.0 - acos(fr_to[TO][Y] - fr_to[FROM][Y]);
  238. if (sin(beta)) {
  239. yup[Y] = fr_to[TO][Y] - 1 / sin(beta);
  240. }
  241. else {
  242. yup[Y] = fr_to[FROM][Y] + 1.0;
  243. }
  244. yupmag = GS_distance(fr_to[FROM], yup);
  245. look_theta = (1800.0 / pi) *
  246. acos(((zup[X] - fr_to[FROM][X]) * (yup[X] - fr_to[FROM][X])
  247. + (zup[Y] - fr_to[FROM][Y]) * (yup[Y] - fr_to[FROM][Y])
  248. + (zup[Z] - fr_to[FROM][Z]) * (yup[Z] - fr_to[FROM][Z])) /
  249. (zupmag * yupmag));
  250. if (fr_to[TO][X] - fr_to[FROM][X] < 0.0) {
  251. look_theta = -look_theta;
  252. }
  253. if (fr_to[TO][Z] - fr_to[FROM][Z] < 0.0) {
  254. /* looking down */
  255. if (fr_to[TO][Y] - fr_to[FROM][Y] < 0.0) {
  256. look_theta = 1800 - look_theta;
  257. }
  258. }
  259. else {
  260. /* looking up */
  261. if (fr_to[TO][Y] - fr_to[FROM][Y] > 0.0) {
  262. look_theta = 1800 - look_theta;
  263. }
  264. }
  265. return ((int)(gv->twist + 1800 + look_theta));
  266. }
  267. /*!
  268. \brief Set current scale
  269. \param doexag use z-exaggeration
  270. */
  271. void gsd_do_scale(int doexag)
  272. {
  273. float sx, sy, sz;
  274. float min, max;
  275. GS_get_scale(&sx, &sy, &sz, doexag);
  276. gsd_scale(sx, sy, sz);
  277. GS_get_zrange(&min, &max, 0);
  278. gsd_translate(0.0, 0.0, -min);
  279. return;
  280. }
  281. /*!
  282. \brief Convert real to model coordinates
  283. \param point[in,out] 3d point (Point3)
  284. */
  285. void gsd_real2model(Point3 point)
  286. {
  287. float sx, sy, sz;
  288. float min, max, n, s, w, e;
  289. GS_get_region(&n, &s, &w, &e);
  290. GS_get_scale(&sx, &sy, &sz, 1);
  291. GS_get_zrange(&min, &max, 0);
  292. point[X] = (point[X] - w) * sx;
  293. point[Y] = (point[Y] - s) * sy;
  294. point[Z] = (point[Z] - min) * sz;
  295. return;
  296. }
  297. /*!
  298. \brief Convert model to real coordinates
  299. \param point[in,out] 3d point (x,y,z)
  300. */
  301. void gsd_model2real(Point3 point)
  302. {
  303. float sx, sy, sz;
  304. float min, max, n, s, w, e;
  305. GS_get_region(&n, &s, &w, &e);
  306. GS_get_scale(&sx, &sy, &sz, 1);
  307. GS_get_zrange(&min, &max, 0);
  308. point[X] = (sx ? point[X] / sx : 0.0) + w;
  309. point[Y] = (sy ? point[Y] / sy : 0.0) + s;
  310. point[Z] = (sz ? point[Z] / sz : 0.0) + min;
  311. return;
  312. }
  313. /*!
  314. \brief Convert model to surface coordinates
  315. \param gs surface (geosurf)
  316. \param point 3d point (Point3)
  317. */
  318. void gsd_model2surf(geosurf * gs, Point3 point)
  319. {
  320. float min, max, sx, sy, sz;
  321. /* so far, only one geographic "region" allowed, so origin of
  322. surface is same as origin of model space, but will need to provide
  323. translations here to make up the difference, so not using gs yet */
  324. if (gs) {
  325. /* need to undo z scaling & translate */
  326. GS_get_scale(&sx, &sy, &sz, 1);
  327. GS_get_zrange(&min, &max, 0);
  328. point[Z] = (sz ? point[Z] / sz : 0.0) + min;
  329. /* need to unscale x & y */
  330. point[X] = (sx ? point[X] / sx : 0.0);
  331. point[Y] = (sy ? point[Y] / sy : 0.0);
  332. }
  333. return;
  334. }
  335. /*!
  336. \brief Convert surface to model coordinates
  337. \param point 3d point (Point3)
  338. */
  339. void gsd_surf2model(Point3 point)
  340. {
  341. float min, max, sx, sy, sz;
  342. /* need to undo z scaling & translate */
  343. GS_get_scale(&sx, &sy, &sz, 1);
  344. GS_get_zrange(&min, &max, 0);
  345. point[Z] = (sz ? (point[Z] - min) * sz : 0.0);
  346. /* need to unscale x & y */
  347. point[X] = (sx ? point[X] * sx : 0.0);
  348. point[Y] = (sy ? point[Y] * sy : 0.0);
  349. return;
  350. }
  351. /*!
  352. \brief Convert surface to real coordinates
  353. \param gs surface (geosurf)
  354. \param[in,out] point 3d point (Point3)
  355. */
  356. void gsd_surf2real(geosurf * gs, Point3 point)
  357. {
  358. if (gs) {
  359. point[X] += gs->ox;
  360. point[Y] += gs->oy;
  361. }
  362. return;
  363. }
  364. /*!
  365. \brief Convert real to surface coordinates
  366. \param gs surface (geosurf)
  367. \param[in,out] point 3d point (Point3)
  368. */
  369. void gsd_real2surf(geosurf * gs, Point3 point)
  370. {
  371. if (gs) {
  372. point[X] -= gs->ox;
  373. point[Y] -= gs->oy;
  374. }
  375. return;
  376. }