|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
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 }