GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
gsd_views.c
Go to the documentation of this file.
00001 
00019 #include <grass/config.h>
00020 
00021 #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
00022 #include <GL/gl.h>
00023 #include <GL/glu.h>
00024 #elif defined(OPENGL_AQUA)
00025 #include <OpenGL/gl.h>
00026 #include <OpenGL/glu.h>
00027 #endif
00028 
00029 #include <grass/gstypes.h>
00030 #include "math.h"
00031 
00040 int gsd_get_los(float (*vect)[3], short sx, short sy)
00041 {
00042     double fx, fy, fz, tx, ty, tz;
00043     GLdouble modelMatrix[16], projMatrix[16];
00044     GLint viewport[4];
00045 
00046     GS_ready_draw();
00047     glPushMatrix();
00048 
00049     gsd_do_scale(1);
00050     glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
00051     glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
00052     glGetIntegerv(GL_VIEWPORT, viewport);
00053     glPopMatrix();
00054 
00055     /* OGLXXX XXX I think this is backwards gluProject(XXX); */
00056     /* WAS: mapw(Vobj, sx, sy, &fx, &fy, &fz, &tx, &ty, &tz); */
00057     gluUnProject((GLdouble) sx, (GLdouble) sy, 0.0, modelMatrix,
00058                  projMatrix, viewport, &fx, &fy, &fz);
00059     gluUnProject((GLdouble) sx, (GLdouble) sy, 1.0, modelMatrix,
00060                  projMatrix, viewport, &tx, &ty, &tz);
00061     vect[FROM][X] = fx;
00062     vect[FROM][Y] = fy;
00063     vect[FROM][Z] = fz;
00064     vect[TO][X] = tx;
00065     vect[TO][Y] = ty;
00066     vect[TO][Z] = tz;
00067 
00068     /* DEBUG - should just be a dot */
00069     /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
00070     glDrawBuffer((1) ? GL_FRONT : GL_BACK);
00071     glPushMatrix();
00072     gsd_do_scale(1);
00073     gsd_linewidth(3);
00074     gsd_color_func(0x8888FF);
00075 
00076     /* OGLXXX for multiple, independent line segments: use GL_LINES */
00077     glBegin(GL_LINE_STRIP);
00078     glVertex3fv(vect[FROM]);
00079     glVertex3fv(vect[TO]);
00080     glEnd();
00081 
00082     gsd_linewidth(1);
00083     glPopMatrix();
00084 
00085     /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
00086     glDrawBuffer((0) ? GL_FRONT : GL_BACK);
00087 
00088     return (1);
00089 }
00090 
00091 #if 0
00092 
00100 void gsd_set_view(geoview * gv, geodisplay * gd)
00101 {
00102     double up[3];
00103     GLint mm;
00104 
00105     /* will expand when need to check for in focus, ortho, etc. */
00106 
00107     gsd_check_focus(gv);
00108     gsd_get_zup(gv, up);
00109 
00110     gd->aspect = GS_get_aspect();
00111 
00112     glGetIntegerv(GL_MATRIX_MODE, &mm);
00113     glMatrixMode(GL_PROJECTION);
00114     glLoadIdentity();
00115     gluPerspective((double).1 * (gv->fov), (double)gd->aspect,
00116                    (double)gd->nearclip, (double)gd->farclip);
00117 
00118     glMatrixMode(mm);
00119 
00120     glLoadIdentity();
00121 
00122     /* update twist parm */
00123     glRotatef((float)(gv->twist / 10.), 0.0, 0.0, 1.0);
00124 
00125     /* OGLXXX lookat: replace UPx with vector */
00126     gluLookAt((double)gv->from_to[FROM][X], (double)gv->from_to[FROM][Y],
00127               (double)gv->from_to[FROM][Z], (double)gv->from_to[TO][X],
00128               (double)gv->from_to[TO][Y], (double)gv->from_to[TO][Z],
00129               (double)up[X], (double)up[Y], (double)up[Z]);
00130 
00131     /* have to redefine clipping planes when view changes */
00132 
00133     gsd_update_cplanes();
00134 
00135     return;
00136 }
00137 #endif
00138 
00146 void gsd_set_view(geoview * gv, geodisplay * gd)
00147 {
00148     double up[3];
00149     float pos[3];
00150     int i;
00151     GLdouble modelMatrix[16];
00152     GLint mm;
00153 
00154     /* will expand when need to check for in focus, ortho, etc. */
00155 
00156     gsd_check_focus(gv);
00157     gsd_get_zup(gv, up);
00158 
00159     gd->aspect = GS_get_aspect();
00160 
00161     glGetIntegerv(GL_MATRIX_MODE, &mm);
00162     glMatrixMode(GL_PROJECTION);
00163     glLoadIdentity();
00164     gluPerspective((double).1 * (gv->fov), (double)gd->aspect,
00165                    (double)gd->nearclip, (double)gd->farclip);
00166 
00167     glMatrixMode(mm);
00168     
00169     glLoadIdentity();
00170 
00171     /* update twist parm */
00172     glRotatef((float)(gv->twist / 10.), 0.0, 0.0, 1.0);
00173 
00174     /* OGLXXX lookat: replace UPx with vector */
00175     gluLookAt((double)gv->from_to[FROM][X], (double)gv->from_to[FROM][Y],
00176               (double)gv->from_to[FROM][Z], (double)gv->from_to[TO][X],
00177               (double)gv->from_to[TO][Y], (double)gv->from_to[TO][Z],
00178               (double)up[X], (double)up[Y], (double)up[Z]);
00179               
00180     /* rotate to get rotation matrix and then save it*/
00181     if (gv->rotate.do_rot) {
00182 
00183         glPushMatrix();
00184         glLoadMatrixd(gv->rotate.rotMatrix);
00185 
00186         glRotated(gv->rotate.rot_angle, gv->rotate.rot_axes[0], 
00187                   gv->rotate.rot_axes[1], gv->rotate.rot_axes[2]);
00188         glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
00189 
00190         for (i = 0; i < 16; i++) {
00191             gv->rotate.rotMatrix[i] = modelMatrix[i];
00192         }
00193 
00194         glPopMatrix();
00195     }
00196     
00197     gs_get_datacenter(pos);
00198     gsd_surf2model(pos);
00199     /* translate rotation center to view center, rotate and translate back */
00200     glTranslatef(pos[0], pos[1], pos[2]);
00201     glMultMatrixd(gv->rotate.rotMatrix);
00202     glTranslatef(-pos[0], -pos[1], -pos[2]);
00203 
00204     /* have to redefine clipping planes when view changes */
00205 
00206     gsd_update_cplanes();
00207 
00208     return;
00209 }
00215 void gsd_check_focus(geoview * gv)
00216 {
00217     float zmax, zmin;
00218 
00219     GS_get_zrange(&zmin, &zmax, 0);
00220 
00221     if (gv->infocus) {
00222         GS_v3eq(gv->from_to[TO], gv->real_to);
00223         gv->from_to[TO][Z] -= zmin;
00224         GS_v3mult(gv->from_to[TO], gv->scale);
00225         gv->from_to[TO][Z] *= gv->vert_exag;
00226 
00227         GS_v3normalize(gv->from_to[FROM], gv->from_to[TO]);
00228     }
00229 
00230     return;
00231 }
00232 
00239 void gsd_get_zup(geoview * gv, double *up)
00240 {
00241     float alpha;
00242     float zup[3], fup[3];
00243 
00244     /* neg alpha OK since sin(-x) = -sin(x) */
00245     alpha =
00246         (2.0 * atan(1.0)) - acos(gv->from_to[FROM][Z] - gv->from_to[TO][Z]);
00247 
00248     zup[X] = gv->from_to[TO][X];
00249     zup[Y] = gv->from_to[TO][Y];
00250 
00251     if (sin(alpha)) {
00252         zup[Z] = gv->from_to[TO][Z] + 1 / sin(alpha);
00253     }
00254     else {
00255         zup[Z] = gv->from_to[FROM][Z] + 1.0;
00256     }
00257 
00258     GS_v3dir(gv->from_to[FROM], zup, fup);
00259 
00260     up[X] = fup[X];
00261     up[Y] = fup[Y];
00262     up[Z] = fup[Z];
00263 
00264     return;
00265 }
00266 
00274 int gsd_zup_twist(geoview * gv)
00275 {
00276     float fr_to[2][4];
00277     float look_theta, pi;
00278     float alpha, beta;
00279     float zup[3], yup[3], zupmag, yupmag;
00280 
00281     pi = 4.0 * atan(1.0);
00282 
00283     /* *************************************************************** */
00284     /* This block of code is used to keep pos z in the up direction,
00285      * correcting for SGI system default which is pos y in the up
00286      * direction.  Involves finding up vectors for both y up and
00287      * z up, then determining angle between them.  LatLon mode uses y as
00288      * up direction instead of z, so no correction necessary.  Next rewrite,
00289      * we should use y as up for all drawing.
00290      */
00291     GS_v3eq(fr_to[FROM], gv->from_to[FROM]);
00292     GS_v3eq(fr_to[TO], gv->from_to[TO]);
00293 
00294     /* neg alpha OK since sin(-x) = -sin(x) */
00295     alpha = pi / 2.0 - acos(fr_to[FROM][Z] - fr_to[TO][Z]);
00296 
00297     zup[X] = fr_to[TO][X];
00298     zup[Y] = fr_to[TO][Y];
00299 
00300     if (sin(alpha)) {
00301         zup[Z] = fr_to[TO][Z] + 1 / sin(alpha);
00302     }
00303     else {
00304         zup[Z] = fr_to[FROM][Z] + 1.0;
00305     }
00306 
00307     zupmag = GS_distance(fr_to[FROM], zup);
00308 
00309     yup[X] = fr_to[TO][X];
00310     yup[Z] = fr_to[TO][Z];
00311 
00312     /* neg beta OK since sin(-x) = -sin(x) */
00313     beta = pi / 2.0 - acos(fr_to[TO][Y] - fr_to[FROM][Y]);
00314 
00315     if (sin(beta)) {
00316         yup[Y] = fr_to[TO][Y] - 1 / sin(beta);
00317     }
00318     else {
00319         yup[Y] = fr_to[FROM][Y] + 1.0;
00320     }
00321 
00322     yupmag = GS_distance(fr_to[FROM], yup);
00323 
00324     look_theta = (1800.0 / pi) *
00325         acos(((zup[X] - fr_to[FROM][X]) * (yup[X] - fr_to[FROM][X])
00326               + (zup[Y] - fr_to[FROM][Y]) * (yup[Y] - fr_to[FROM][Y])
00327               + (zup[Z] - fr_to[FROM][Z]) * (yup[Z] - fr_to[FROM][Z])) /
00328              (zupmag * yupmag));
00329 
00330     if (fr_to[TO][X] - fr_to[FROM][X] < 0.0) {
00331         look_theta = -look_theta;
00332     }
00333 
00334     if (fr_to[TO][Z] - fr_to[FROM][Z] < 0.0) {
00335         /* looking down */
00336         if (fr_to[TO][Y] - fr_to[FROM][Y] < 0.0) {
00337             look_theta = 1800 - look_theta;
00338         }
00339     }
00340     else {
00341         /* looking up */
00342         if (fr_to[TO][Y] - fr_to[FROM][Y] > 0.0) {
00343             look_theta = 1800 - look_theta;
00344         }
00345     }
00346 
00347     return ((int)(gv->twist + 1800 + look_theta));
00348 }
00349 
00355 void gsd_do_scale(int doexag)
00356 {
00357     float sx, sy, sz;
00358     float min, max;
00359 
00360     GS_get_scale(&sx, &sy, &sz, doexag);
00361     gsd_scale(sx, sy, sz);
00362     GS_get_zrange(&min, &max, 0);
00363     gsd_translate(0.0, 0.0, -min);
00364 
00365     return;
00366 }
00367 
00373 void gsd_real2model(Point3 point)
00374 {
00375     float sx, sy, sz;
00376     float min, max, n, s, w, e;
00377 
00378     GS_get_region(&n, &s, &w, &e);
00379     GS_get_scale(&sx, &sy, &sz, 1);
00380     GS_get_zrange(&min, &max, 0);
00381     point[X] = (point[X] - w) * sx;
00382     point[Y] = (point[Y] - s) * sy;
00383     point[Z] = (point[Z] - min) * sz;
00384 
00385     return;
00386 }
00387 
00393 void gsd_model2real(Point3 point)
00394 {
00395     float sx, sy, sz;
00396     float min, max, n, s, w, e;
00397 
00398     GS_get_region(&n, &s, &w, &e);
00399     GS_get_scale(&sx, &sy, &sz, 1);
00400     GS_get_zrange(&min, &max, 0);
00401     point[X] = (sx ? point[X] / sx : 0.0) + w;
00402     point[Y] = (sy ? point[Y] / sy : 0.0) + s;
00403     point[Z] = (sz ? point[Z] / sz : 0.0) + min;
00404 
00405     return;
00406 }
00407 
00414 void gsd_model2surf(geosurf * gs, Point3 point)
00415 {
00416     float min, max, sx, sy, sz;
00417 
00418     /* so far, only one geographic "region" allowed, so origin of
00419        surface is same as origin of model space, but will need to provide 
00420        translations here to make up the difference, so not using gs yet */
00421 
00422     if (gs) {
00423         /* need to undo z scaling & translate */
00424         GS_get_scale(&sx, &sy, &sz, 1);
00425         GS_get_zrange(&min, &max, 0);
00426 
00427         point[Z] = (sz ? point[Z] / sz : 0.0) + min;
00428 
00429         /* need to unscale x & y */
00430         point[X] = (sx ? point[X] / sx : 0.0);
00431         point[Y] = (sy ? point[Y] / sy : 0.0);
00432     }
00433 
00434     return;
00435 }
00441 void gsd_surf2model(Point3 point)
00442 {
00443     float min, max, sx, sy, sz;
00444 
00445     /* need to undo z scaling & translate */
00446     GS_get_scale(&sx, &sy, &sz, 1);
00447     GS_get_zrange(&min, &max, 0);
00448 
00449     point[Z] = (sz ? (point[Z] - min) * sz : 0.0);
00450 
00451     /* need to unscale x & y */
00452     point[X] = (sx ? point[X] * sx : 0.0);
00453     point[Y] = (sy ? point[Y] * sy : 0.0);
00454 
00455 
00456     return;
00457 }
00464 void gsd_surf2real(geosurf * gs, Point3 point)
00465 {
00466     if (gs) {
00467         point[X] += gs->ox;
00468         point[Y] += gs->oy;
00469     }
00470 
00471     return;
00472 }
00473 
00480 void gsd_real2surf(geosurf * gs, Point3 point)
00481 {
00482     if (gs) {
00483         point[X] -= gs->ox;
00484         point[Y] -= gs->oy;
00485     }
00486 
00487     return;
00488 }