gpligc/src/GLexplorer.cpp

5910 lines
134 KiB
C++

/*
* (c) 2002-2016 Hannes Krueger
* This file is part of the GPLIGC/ogie package
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
/*
if compiled with -DWITH_OSMESA, the mesa offscreen rendering is included
-> changed to autoconf -> HAVE_LIBOSMESA
if compiled with -DONLY_OSMESA, only osmesa will work. all interactive
features will be disabled, and therefore no GLUT or X11 is needed.
--> however for text some glut functions are used....
*/
// all platforms include gl.h (except OSX)
#ifndef __OSX__
#include <GL/gl.h>
// glut not needed for ONLY_OSMESA
// actually ONLY_OSMESA shouldnt be used any longer
// #ifndef ONLY_OSMESA
#include <GL/glut.h>
#include <GL/glu.h>
// #endif
#else
// OSX here....
// #ifndef ONLY_OSMESA
#include <GLUT/glut.h>
// #endif
#include <OpenGL/gl.h>
#define __MACOSX__
#endif
#ifdef FREEGLUT
#include <GL/freeglut_ext.h>
#endif
#ifndef GLUT_VERSION
// this is the value from GL/freeglut_ext.h. If we dont have freeglut, we need to define it here
#define GLUT_VERSION 0x01FC
#endif
#include "oconfig.h"
#include "config.h"
#ifdef HAVE_LIBOSMESA
//#include <GL/glu.h>
#include <GL/osmesa.h>
//#include "osmesa.h"
#endif
#ifndef __WIN32__
#ifndef __OSX__
// #ifndef ONLY_OSMESA
#include <GL/glx.h>
// #endif
#endif
#endif
// just for version info
#ifdef HAVE_LIBGPS
#include "libgpsmm.h"
#endif
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <jpeglib.h>
// do we need this ?
#ifndef __WIN32__
#include <csignal>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
#include <sys/time.h>
#include <string>
#include <vector>
#include "GLexplorer.h"
#include "flightdata.h"
#include "ego.h"
#include "landscape.h"
#include "cmdline.h"
#include "map.h"
#include "oglexfunc.h"
#include "airspc.h"
#include "projection.h"
//#include "sysinfo.h"
#include "points.h"
// windows hasn't GLX and Mesa
#ifdef __WIN32__
#define NOGLX
//#include <strings.h>
//#undef WITH_OSMESA
#endif
// #ifdef __OSX__
// #define NOGLX
// #undef WITH_OSMESA
// #endif
// configure hasn't found glXCreatePbuffer
#ifndef HAVE_GLXPBUFFER
#define NOGLX
#endif
// no unix, no GLX, Mesa
#ifndef __unix__
#define NOGLX
//#undef WITH_MESA
#endif
#ifndef M_PI
#define M_PI 3.141592654
#endif
using namespace std;
//const string rcsid_GLexplorer_cpp =
// "$Id: GLexplorer.cpp 3 2014-07-31 09:59:20Z kruegerh $";
//const string rcsid_GLexplorer_h = GLEXPLORER_H;
//Global stuff
Flightdata fd; //flightdata object
//needs to be global! (see keyPressed callback function...)
Airspace air; //airspaces....
Projection proj; //projection
Points lifts;
Points waypoints;
gengetopt_args_info args_info;
gpligc_ipc_block ipc_block;
Ego ego(0, 0, 0, 0, 0, 0); //initialize ego
GLuint flightdata_displ_list; //the display_lists
GLuint landscape_displ_list; //
GLuint airspace_displ_list;
//GLuint lifts_displ_list;
Config conf; //configuration stuff (initialized with compiled-in defaults, see constructor)
// defaults can be overridden by 1. configfile and 2.cmdline
int lastmx = 0; //last mouseposition
int lastmy = 0;
int rightbuttonstate = GLUT_UP;
int middlebuttonstate = GLUT_UP;
int leftbuttonstate = GLUT_UP;
//bool cntrlstate = false;
bool MENUPOPPED = false; //menu hasnt popped or disappeared soon.
bool MENUCHANGED = false; //menu has to be changed!
bool MENUSTATE = false;
bool HELP = false; //flag for help-display
bool INFO = false; // flag for info-display
bool MOUSEWARPED = false; // Mouse warped indicator. Will be set when the mouse pointer
// is forcefully re-centered by the program.
/*
bool SHIFTKEY = false;
bool CNTRLKEY = false;
bool ALTKEY = false;
*/
int window = -3992; // GLUT window number (3992 to check if its changed (=window created))
vector<float>fps(10); // used to smooth framerate
int movie_repeat_counter=0;
#ifndef __WIN32__
#ifndef ONLY_OSMESA
// GPLIGC communication... if SIGUSR1 received, reread shared mem block
void SIGUSR1Handler(int sig)
{
if (sig == SIGUSR1) {
int shm_id;
key_t key;
key = ftok(conf.getIGCFileName().c_str(), 76);
//cout << "key : " << key << endl;
shm_id = shmget(key, sizeof(gpligc_ipc_block), 0);
if (shm_id != -1) {
char *data;
char *data_dest;
data_dest = (char *) &ipc_block;
data = (char *) shmat(shm_id, (void *) 0, 0);
//copy shm segment to the ipc_block struct... (low-level)
for (int _z = 0;
_z < (int) sizeof(gpligc_ipc_block); _z++) {
data_dest[_z] = data[_z];
}
shmdt(data);
//cout << "Inhalt: " << ipc_block.marker_pos << endl;
fd.setmarkerpos(ipc_block.marker_pos);
if (conf.FOLLOW.get()) {
update_locked_pos();
}
if (conf.MARKER_RANGE.get()) {
GenFlightList();
}
}
/*
if (conf.VERBOSE.get()) {
cout << "SIGUSR1 received... Size of shared mem block:"
<< sizeof(gpligc_ipc_block) << " shmid:"<< shm_id <<endl;
}
*/
glutPostRedisplay();
}
}
void update_shmem(void) {
ipc_block.marker_pos = fd.getmarker();
//cout << "openGLIGCexplorer: " << fd.getmarker();
int shm_id;
key_t key;
key = ftok(conf.getIGCFileName().c_str(), 76);
//cout << "key : " << key << endl;
shm_id = shmget(key, sizeof(gpligc_ipc_block), 0);
if (shm_id != -1) {
char *data;
char *data_src;
data_src = (char *) &ipc_block;
data = (char *) shmat(shm_id, (void *) 0, 0);
//copy the ipc_block struct to shm-segment... (low-level)
for (int _z = 0;
_z < (int) sizeof(gpligc_ipc_block); _z++) {
data[_z] = data_src[_z];
}
shmdt(data);
}
//cout << "update_shmem called... sending SIGUSR2 to GPLIGC" << endl;
// this is now deactivated....
//if (args_info.parent_pid_given) {
// kill(args_info.parent_pid_arg, SIGUSR2);
//}
}
#endif
#endif
#ifndef ONLY_OSMESA
int menIdMain, menIdMapSet, menIdStereo, menIdColormap, menIdColormap_sea,
menIdFSColormap, menIdFSMode, menIdAirspaceType;
void menuMain(int val)
{
// this is needed for glutChangeToMenuEntry (which is done in current menu),
// if this is called from keypressed function and current menu is other than menuMain
// glutSetMenu(menIdMain); // we dont changeToMenuEntry any more, here
MENUPOPPED=true;
switch (val) {
case 1:
conf.MAP.toggle();
GenLandscapeList();
GenFlightList(); //?
glutPostRedisplay();
MENUCHANGED= true;
// if (conf.MAP.get()) {
// glutChangeToMenuEntry(1, "Maps off", 1);
// } else {
// glutChangeToMenuEntry(1, "Maps on", 1);
// }
break;
case 2:
conf.MODULATE.toggle();
if (conf.MAP.get()) {
GenLandscapeList();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.MODULATE.get()) {
// glutChangeToMenuEntry(2, "Colored maps off", 2);
// } else {
// glutChangeToMenuEntry(2, "Colored maps on", 2);
// }
break;
case 11:
if (conf.DEM.get()) {
conf.LANDSCAPE.toggle();
GenFlightList();
GenLandscapeList();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.LANDSCAPE.get()) {
// glutChangeToMenuEntry(5, "Terrain off", 11);
// } else {
// glutChangeToMenuEntry(5, "Terrain on", 11);
// }
break;
case 12:
conf.FOG.toggle();
//GenFlightList();
InitGL(conf.getwidth(), conf.getheight());
glutPostRedisplay();
MENUCHANGED= true;
// if (conf.FOG.get()) {
// glutChangeToMenuEntry(8, "Haze off", 12);
// } else {
// glutChangeToMenuEntry(8, "Haze on", 12);
// }
break;
case 13:
if (conf.getAirspaceFileName() != "not available") {
conf.AIRSPACE.toggle();
GenAirspaceList();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.AIRSPACE.get()) {
// glutChangeToMenuEntry(9, "Airspace off", 13);
// } else {
// glutChangeToMenuEntry(9, "Airspace on", 13);
// }
break;
case 21:
if (conf.FLIGHT.get()) {
conf.CURTAIN.toggle();
GenFlightList();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.CURTAIN.get()) {
// glutChangeToMenuEntry(14, "Curtain off", 21);
// } else {
// glutChangeToMenuEntry(14, "Curtain on", 21);
// }
break;
case 31:
if (conf.FLIGHT.get()) {
conf.MARKER.toggle();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.MARKER.get()) {
// glutChangeToMenuEntry(16, "Marker off", 31);
// } else {
// glutChangeToMenuEntry(16, "Marker on", 31);
// }
break;
case 32:
conf.INFO.toggle();
glutPostRedisplay();
MENUCHANGED= true;
// if (conf.INFO.get()) {
// glutChangeToMenuEntry(17, "Info off", 32);
// } else {
// glutChangeToMenuEntry(17, "Info on", 32);
// }
break;
case 33:
if (conf.FLIGHT.get()) {
if (conf.FOLLOW.get()) {
ego.setdx(0);
ego.setdy(0);
ego.setdz(0);
} else {
update_diff_pos();
}
conf.FOLLOW.toggle();
}
MENUCHANGED= true;
// if (conf.FOLLOW.get()) {
// glutChangeToMenuEntry(18, "Follow mode off", 33);
// } else {
// glutChangeToMenuEntry(18, "Follow mode on", 33);
// }
break;
case 34:
if (conf.FLIGHT.get()) {
conf.MARKER_RANGE.toggle();
GenFlightList();
glutPostRedisplay();
}
MENUCHANGED= true;
// if (conf.MARKER_RANGE.get()) {
// glutChangeToMenuEntry(19, "Range off", 34);
// } else {
// // glutChangeToMenuEntry(19, "Range on", 34);
// }
break;
case 35:
// makes no sense without flight
//if (conf.FLIGHT.get()) {
conf.FLYING.toggle();
//}
if (conf.FLYING.get() || conf.JOYSTICK.get() || conf.GPSD.get()) {
glutIdleFunc(&IdleFunc);
} else {
glutIdleFunc(NULL);
}
glutPostRedisplay();
MENUCHANGED= true;
// if (conf.FLYING.get()) {
// glutChangeToMenuEntry(20, "Movie off", 35);
// } else {
// glutChangeToMenuEntry(20, "Movie on", 35);
// }
break;
case 36:
conf.JOYSTICK.toggle();
if (conf.FLYING.get() || conf.JOYSTICK.get() || conf.GPSD.get() ) {
glutIdleFunc(&IdleFunc);
} else {
glutIdleFunc(NULL);
}
MENUCHANGED= true;
if (conf.JOYSTICK.get()) {
glutJoystickFunc(joystick,0);
// glutChangeToMenuEntry(21,"Joystick off", 36);
} else {
glutJoystickFunc(NULL,0);
// glutChangeToMenuEntry(21,"Joystick on", 36);
}
break;
case 41:
conf.ORTHOVIEW.toggle();
GenFlightList();
InitGL(conf.getwidth(), conf.getheight()); //???
glutPostRedisplay();
MENUCHANGED= true;
// if (conf.ORTHOVIEW.get()) {
// glutChangeToMenuEntry(23, "3D perspectivic view",
// 41);
// } else {
// glutChangeToMenuEntry(23, "2D orthographic view",
// 41);
// }
break;
case 97:
HELP = true; INFO=false;
glutPostRedisplay();
break;
case 98:
INFO = true; HELP=false;
glutPostRedisplay();
break;
case 99:
Ende(0);
break;
}
}
// recreate/update menus!
void menuRecreate()
{
if (conf.DEBUG.get())
cout << " re-creating menus"<< endl;
glutSetMenu(menIdAirspaceType);
if (conf.AIRSPACE_P.get()) {
glutChangeToMenuEntry(1, "Prohibited D off", 1);
} else {
glutChangeToMenuEntry(1, "Prohibited P on", 1);
}
if (conf.AIRSPACE_R.get()) {
glutChangeToMenuEntry(2, "Restricted R off", 2); //2
} else {
glutChangeToMenuEntry(2, "Restricted R on", 2);
}
if (conf.AIRSPACE_Q.get()) {
glutChangeToMenuEntry(3, "Danger Q off", 3); //3
} else {
glutChangeToMenuEntry(3, "Danger Q on", 3);
}
if (conf.AIRSPACE_C.get()) {
glutChangeToMenuEntry(4, "Class C off", 4); //4
} else {
glutChangeToMenuEntry(4, "Class C on", 4);
}
if (conf.AIRSPACE_D.get()) {
glutChangeToMenuEntry(5, "Class D off", 5); //5
} else {
glutChangeToMenuEntry(5, "Class D on", 5);
}
if (conf.AIRSPACE_CTR.get()) {
glutChangeToMenuEntry(6, "CTR off", 6); //6
} else {
glutChangeToMenuEntry(6, "CTR on", 6);
}
// recreate/change main menu!
glutSetMenu(menIdMain);
if (conf.MAP.get()) {
glutChangeToMenuEntry(1, "Maps off", 1);
} else {
glutChangeToMenuEntry(1, "Maps on", 1);
}
if (conf.MODULATE.get()) {
glutChangeToMenuEntry(2, "Colored maps off", 2);
} else {
glutChangeToMenuEntry(2, "Colored maps on", 2);
}
if (conf.LANDSCAPE.get()) {
glutChangeToMenuEntry(5, "Terrain off", 11);
} else {
glutChangeToMenuEntry(5, "Terrain on", 11);
}
if (conf.FOG.get()) {
glutChangeToMenuEntry(8, "Haze off", 12);
} else {
glutChangeToMenuEntry(8, "Haze on", 12);
}
if (conf.AIRSPACE.get()) {
glutChangeToMenuEntry(9, "Airspace off", 13);
} else {
glutChangeToMenuEntry(9, "Airspace on", 13);
}
if (conf.CURTAIN.get()) {
glutChangeToMenuEntry(14, "Curtain off", 21);
} else {
glutChangeToMenuEntry(14, "Curtain on", 21);
}
if (conf.MARKER.get()) {
glutChangeToMenuEntry(16, "Marker off", 31);
} else {
glutChangeToMenuEntry(16, "Marker on", 31);
}
if (conf.INFO.get()) {
glutChangeToMenuEntry(17, "Info off", 32);
} else {
glutChangeToMenuEntry(17, "Info on", 32);
}
if (conf.FOLLOW.get()) {
glutChangeToMenuEntry(18, "Follow mode off", 33);
} else {
glutChangeToMenuEntry(18, "Follow mode on", 33);
}
if (conf.MARKER_RANGE.get()) {
glutChangeToMenuEntry(19, "Range off", 34);
} else {
glutChangeToMenuEntry(19, "Range on", 34);
}
if (conf.FLYING.get()) {
glutChangeToMenuEntry(20, "Movie off", 35);
} else {
glutChangeToMenuEntry(20, "Movie on", 35);
}
if (conf.JOYSTICK.get()) {
// glutJoystickFunc(joystick,0);
glutChangeToMenuEntry(21,"Joystick off", 36);
} else {
// glutJoystickFunc(NULL,0);
glutChangeToMenuEntry(21,"Joystick on", 36);
}
if (conf.ORTHOVIEW.get()) {
glutChangeToMenuEntry(23, "3D perspectivic view",
41);
} else {
glutChangeToMenuEntry(23, "2D orthographic view",
41);
}
MENUCHANGED=false;
}
void menuMapSet(int val)
{
MENUPOPPED=true;
if (val == 9999) return;
conf.ActiveMapSet.set(val);
if (conf.MAP.get()) {
GenLandscapeList();
glutPostRedisplay();
}
}
void menuStereo(int val)
{
MENUPOPPED=true;
// nothing to do in Hardware stereo mode
// HW stereo can be enabled at start time and cannot be changed then
if (conf.STEREO_HW.get()) {
return;
}
bool REBUILD = false;
switch (val) {
// turn off stereo modes
case 1:
// rebuilding terrain list is necessary if we had colored anaglyph before
// because everything is drawn in B&W then
if ((conf.STEREO_RG.get() || conf.STEREO_RB.get())
&& !conf.BW.get()) {
REBUILD = true;
}
conf.STEREO.off();
conf.STEREO_RG.off();
conf.STEREO_RB.off();
InitGL(conf.getwidth(), conf.getheight());
if (REBUILD) {
GenLandscapeList();
GenFlightList();
GenAirspaceList();
}
glutPostRedisplay();
break;
case 2:
if (conf.STEREO.get()) {
return;
}
if ((conf.STEREO_RG.get() || conf.STEREO_RB.get())
&& !conf.BW.get()) {
REBUILD = true;
}
conf.STEREO.on();
conf.STEREO_RG.off();
conf.STEREO_RB.off();
InitGL(conf.getwidth(), conf.getheight());
if (REBUILD) {
GenLandscapeList();
GenFlightList();
GenAirspaceList();
}
glutPostRedisplay();
break;
case 3:
if (conf.STEREO_RG.get()) {
return;
}
if (!(conf.STEREO_RB.get() || conf.BW.get())) {
REBUILD = true;
}
conf.STEREO.off();
conf.STEREO_RG.on();
conf.STEREO_RB.off();
InitGL(conf.getwidth(), conf.getheight());
if (REBUILD) {
GenLandscapeList();
GenFlightList();
GenAirspaceList();
}
glutPostRedisplay();
break;
case 4:
if (conf.STEREO_RB.get()) {
return;
}
if (!(conf.STEREO_RG.get() || conf.BW.get())) {
REBUILD = true;
}
conf.STEREO.off();
conf.STEREO_RG.off();
conf.STEREO_RB.on();
InitGL(conf.getwidth(), conf.getheight());
if (REBUILD) {
GenLandscapeList();
GenFlightList();
GenAirspaceList();
}
glutPostRedisplay();
break;
case 5:
conf.SWAP_STEREO.toggle();
glutPostRedisplay();
break;
}
}
void menuColormap(int val)
{
MENUPOPPED=true;
if (conf.colmapnumber.get() == val) {
return;
}
conf.colmapnumber.set(val);
if ((conf.LANDSCAPE.get() && conf.MAP.get() && conf.MODULATE.get())
|| (conf.LANDSCAPE.get() && !conf.MAP.get()
&& !conf.WIRE.get())) {
GenLandscapeList();
glutPostRedisplay();
}
}
void menuColormap_sea(int val)
{
MENUPOPPED=true;
if (conf.colmap2number.get() == val) {
return;
}
conf.colmap2number.set(val);
if ((conf.LANDSCAPE.get() && conf.MAP.get() && conf.MODULATE.get())
|| (conf.LANDSCAPE.get() && !conf.MAP.get()
&& !conf.WIRE.get())) {
GenLandscapeList();
glutPostRedisplay();
}
}
void menuFSColormap(int val)
{
MENUPOPPED=true;
if (conf.flightstrip_colmap.get() == val) {
return;
}
conf.flightstrip_colmap.set(val);
GenFlightList();
glutPostRedisplay();
}
void menuFSMode(int val)
{
MENUPOPPED=true;
if (conf.flightstrip_mode.get() == val) {
return;
}
conf.flightstrip_mode.set(val);
GenFlightList();
glutPostRedisplay();
}
void menuAirspaceType(int val)
{
MENUPOPPED=true;
switch (val) {
case 1:
conf.AIRSPACE_P.toggle();
MENUCHANGED = true;
break;
case 2:
conf.AIRSPACE_R.toggle();
MENUCHANGED = true;
break;
case 3:
conf.AIRSPACE_Q.toggle();
MENUCHANGED = true;
break;
case 4:
conf.AIRSPACE_C.toggle();
MENUCHANGED = true;
break;
case 5:
conf.AIRSPACE_D.toggle();
MENUCHANGED = true;
break;
case 6:
conf.AIRSPACE_CTR.toggle();
MENUCHANGED = true;
break;
}
GenAirspaceList();
glutPostRedisplay();
}
void GenMenu(void)
{
// create Map-Set-Submenu
//if (conf.getMapSetName().size() > 0) {
//cout << "XXX" << conf.getMapSetName().size() << endl;
// freeglut 3.0!
// glutSetMenuFont(menIdMain, GLUT_BITMAP_TIMES_ROMAN_10);
menIdMapSet = glutCreateMenu(menuMapSet);
vector < string > MapSets;
MapSets = conf.getMapSetName();
if (MapSets.size() == 0) {
glutAddMenuEntry("no map sets found", 9999);
}
for (int i = 0; i < (int) MapSets.size(); i++) {
//cout << "set:" << i <<" "<< MapSets[i] << endl;
glutAddMenuEntry(MapSets[i].c_str(), i + 1);
}
//}
// create Stereo menu
menIdStereo = glutCreateMenu(menuStereo);
glutAddMenuEntry("Stereo off", 1);
glutAddMenuEntry("Double image", 2);
glutAddMenuEntry("Red Green", 3);
glutAddMenuEntry("Red Blue", 4);
glutAddMenuEntry("Swap Images", 5);
//create Colormapmenu
menIdColormap = glutCreateMenu(menuColormap);
glutAddMenuEntry("Max's colormap", 1);
glutAddMenuEntry("Atlas colormap", 2);
glutAddMenuEntry("Graymap", 3);
glutAddMenuEntry("Atlas 2 colormap", 4);
glutAddMenuEntry("Violett - blue", 5);
glutAddMenuEntry("Killer Rainbow map", 6);
glutAddMenuEntry("White", 7);
//create Colormapmenu sea
menIdColormap_sea = glutCreateMenu(menuColormap_sea);
glutAddMenuEntry("Max's colormap", 1);
glutAddMenuEntry("Atlas colormap", 2);
glutAddMenuEntry("Graymap", 3);
glutAddMenuEntry("Atlas 2 colormap", 4);
glutAddMenuEntry("Violett - blue", 5);
glutAddMenuEntry("Killer Rainbow map", 6);
glutAddMenuEntry("White", 7);
//create Colormapmenu FS
menIdFSColormap = glutCreateMenu(menuFSColormap);
glutAddMenuEntry("Max's colormap", 1);
glutAddMenuEntry("Atlas colormap", 2);
glutAddMenuEntry("Graymap", 3);
glutAddMenuEntry("Atlas 2 colormap", 4);
glutAddMenuEntry("Violett - blue", 5);
glutAddMenuEntry("Killer Rainbow map", 6);
glutAddMenuEntry("White", 7);
//create FS Mode menu
menIdFSMode = glutCreateMenu(menuFSMode);
glutAddMenuEntry("classic", 0);
glutAddMenuEntry("altitude", 1);
glutAddMenuEntry("speed", 2);
glutAddMenuEntry("vario", 3);
//create Airspace type menu
menIdAirspaceType=glutCreateMenu(menuAirspaceType);
if (conf.AIRSPACE_P.get()) {
glutAddMenuEntry("Prohibited P off", 1); //1
} else {
glutAddMenuEntry("Prohibited P on", 1);
}
if (conf.AIRSPACE_R.get()) {
glutAddMenuEntry("Restricted R off", 2); //2
} else {
glutAddMenuEntry("Restricted R on", 2);
}
if (conf.AIRSPACE_Q.get()) {
glutAddMenuEntry("Danger Q off", 3); //3
} else {
glutAddMenuEntry("Danger Q on", 3);
}
if (conf.AIRSPACE_C.get()) {
glutAddMenuEntry("Class C off", 4); //4
} else {
glutAddMenuEntry("Class C on", 4);
}
if (conf.AIRSPACE_D.get()) {
glutAddMenuEntry("Class D off", 5); //5
} else {
glutAddMenuEntry("Class D on", 5);
}
if (conf.AIRSPACE_CTR.get()) {
glutAddMenuEntry("CTR off", 6); //6
} else {
glutAddMenuEntry("CTR on", 6);
}
// create Main Menu
menIdMain = glutCreateMenu(menuMain);
if (conf.MAP.get()) {
glutAddMenuEntry("Maps off", 1); //1
} else {
glutAddMenuEntry("Maps on", 1);
}
if (conf.MODULATE.get()) {
glutAddMenuEntry("Colored maps off", 2); //2
} else {
glutAddMenuEntry("Colored maps on", 2);
}
glutAddSubMenu("Map Sets", menIdMapSet); //3
//-----------
glutAddMenuEntry(" ", 0); //4
if (conf.LANDSCAPE.get()) {
glutAddMenuEntry("Terrain off", 11); //5
} else {
glutAddMenuEntry("Terrain on", 11);
}
glutAddSubMenu("Terrain Colorramps", menIdColormap); //6
glutAddSubMenu("Sea Colorramps", menIdColormap_sea); //7
if (conf.FOG.get()) {
glutAddMenuEntry("Haze off", 12); //8
} else {
glutAddMenuEntry("Haze on", 12);
}
if (conf.AIRSPACE.get()) {
glutAddMenuEntry("Airspace off", 13); //9
} else {
glutAddMenuEntry("Airspace on", 13);
}
glutAddSubMenu("Airspace types", menIdAirspaceType); // 10
//------------
glutAddMenuEntry(" ", 0); //11
glutAddSubMenu("Flight track Colorramp", menIdFSColormap); //12
glutAddSubMenu("Flight track Mode", menIdFSMode); //13
if (conf.CURTAIN.get()) {
glutAddMenuEntry("Curtain off", 21); //14
} else {
glutAddMenuEntry("Curtain on", 21);
}
//---------
glutAddMenuEntry(" ", 0); //15
if (conf.MARKER.get()) {
glutAddMenuEntry("Marker off", 31); //16
} else {
glutAddMenuEntry("Marker on", 31);
}
if (conf.INFO.get()) {
glutAddMenuEntry("Info off", 32); //17
} else {
glutAddMenuEntry("Info on", 32);
}
if (conf.FOLLOW.get()) {
glutAddMenuEntry("Follow off", 33); //18
} else {
glutAddMenuEntry("Follow on", 33);
}
if (conf.MARKER_RANGE.get()) {
glutAddMenuEntry("Range off", 34); //19
} else {
glutAddMenuEntry("Range on", 34);
}
if (conf.FLYING.get()) {
glutAddMenuEntry("Movie off", 35); //20
} else {
glutAddMenuEntry("Movie on", 35);
}
if (conf.JOYSTICK.get()) {
glutAddMenuEntry("Joystick off",36); //21
} else {
glutAddMenuEntry("Joystick on",36);
}
//-------
glutAddMenuEntry(" ", 0); //22
if (conf.ORTHOVIEW.get()) {
glutAddMenuEntry("3D perspectivic view", 41); //23
} else {
glutAddMenuEntry("2D orthographic view", 41);
}
glutAddSubMenu("Stereo Modes", menIdStereo); //24
glutAddMenuEntry(" ", 0); //25
glutAddMenuEntry("Help", 97); //26
glutAddMenuEntry("About OGIE",98); //27
glutAddMenuEntry("Quit", 99); //28
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void menuStatus(int val, int x, int y)
{
MENUPOPPED = true;
if (conf.DEBUG.get())
cout << "menuStatus called: ";
if (val == GLUT_MENU_IN_USE) {
MENUSTATE = true;
if (conf.DEBUG.get())
cout << "ON" << endl;
}
if (val == GLUT_MENU_NOT_IN_USE) {
MENUSTATE = false;
MENUPOPPED = false;
if (conf.DEBUG.get())
cout << "OFF" << endl;
if (MENUCHANGED)
menuRecreate();
}
}
// all the menu stuff #ifndef ONLY_OSMESA
#endif
//this function sets up the flight-display list
void GenFlightList(void)
{
if (conf.DEBUG.get()) {
cout << "GenFlightList START: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
glDeleteLists(flightdata_displ_list, 1); //delete list to free memory
flightdata_displ_list = glGenLists(1); //create new List
glNewList(flightdata_displ_list, GL_COMPILE);
/*
if (conf.DEBUG.get()) {
cout << "GenFlightList 1: " << flush;
glutReportErrors();
cout << endl << flush;
}
*/
// draw flight linestrip
if (!conf.LANDSCAPE.get() && !conf.MAP.get()) {
fd.draw_linestrip(conf.offset.get(), conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), 0.8, 0.1, 0.1,
1.0, 1.0, 1.0);
} else {
fd.draw_linestrip(conf.offset.get(), conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), conf.flightstrip_col_rup.get(), conf.flightstrip_col_gup.get(), conf.flightstrip_col_bup.get(),
conf.flightstrip_col_rdown.get(), conf.flightstrip_col_gdown.get(), conf.flightstrip_col_bdown.get());
}
/*
if (conf.DEBUG.get()) {
cout << "GenFlightList 2: " << flush;
glutReportErrors();
cout << endl << flush;
}
*/
// The "Shadow" for "Flat-Landscape"
if (conf.FLIGHT.get()) {
if (!conf.LANDSCAPE.get()) {
fd.draw_shadow(conf.offset.get(),
conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), 2.0, 0.0, 0.0,
0.0);
} else {
fd.draw_shadow_terrain(conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), 1.0, 0.0,
0.0, 0.3);
}
}
// we need to render transparent stuff at the end (thus put it at the end of the flight_list)
/*
if (conf.DEBUG.get()) {
cout << "GenFlightList 3: " << flush;
glutReportErrors();
cout << endl << flush;
}
*/
// Curtain
if (conf.CURTAIN.get()) {
fd.draw_curtain(conf.offset.get(), conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), 0.0, 0.0, 0.4, 0.4);
}
glEndList();
// this used to be an experiment to smooth the linestrip:
// fd.setglEvaluator();
if (conf.DEBUG.get()) {
cout << "GenFlightList END: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
}
void GenAirspaceList()
{
if (conf.DEBUG.get()) {
cout << "GenAirList START: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
glDeleteLists(airspace_displ_list, 1); // delete list to free memory
airspace_displ_list = glGenLists(1); // create new List
glNewList(airspace_displ_list, GL_COMPILE);
//Airspace
if (conf.AIRSPACE.get()) {
air.drawAirspace(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get());
}
glEndList();
if (conf.DEBUG.get()) {
cout << "GenAirList END: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
}
/*
void GenPointsList()
{
if (conf.DEBUG.get()) {
cout << "GenPointsList START: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
// lifts. more sections are needed for WPs etc
glDeleteLists(lifts_displ_list,1);
lifts_displ_list = glGenLists(1);
glNewList(lifts_displ_list, GL_COMPILE);
if (conf.LIFTS.get()) {
lifts.drawLifts(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get());
}
glEndList();
if (conf.DEBUG.get()) {
cout << "GenPointsList END: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
}
*/
// generate the terrain display list
void GenLandscapeList()
{
landscape_jump:
if (conf.DEBUG.get()) {
cout << "GenLandList START: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
// loading message
#ifndef ONLY_OSMESA
if (!( conf.OSMESA.get() || conf.OFFSCREEN.get()))
glutSwapBuffers(); //nobody knows whats in the back buffer,
// but there is a good changce that after swapping there is the previous displayed image
// make shure that the text appears right and left in hw-stereo-mode
// doesnt make sense in offscreen mode... and GL_BACK would segfault!
if (! ( conf.OSMESA.get() || conf.OFFSCREEN.get() )) {
if (conf.STEREO_HW.get()) {
glDrawBuffer(GL_BACK);
}
//vector <string> message;
//message.push_back("loading...");
int font_height = conf.getheight() / 5;
glLineWidth(5.0);
gltext(conf.getwidth() / 4, (conf.getheight() / 2),
font_height, "loading...", conf.getwidth(),
conf.getheight());
glutSwapBuffers();
glLineWidth(1.0);
}
#endif
glDeleteLists(landscape_displ_list, 1); //free memory
landscape_displ_list = glGenLists(1); //create new List
glNewList(landscape_displ_list, GL_COMPILE);
//the huge green rectangle (flat-landscape)
if (!conf.LANDSCAPE.get() && !conf.MAP.get()) {
//glPushAttrib(GL_ENABLE_BIT);
//glPushAttrib(GL_POLYGON_BIT);
//glPolygonMode(GL_FRONT, GL_FILL); //should already be set (default)
glDisable(GL_LIGHTING);
glBegin(GL_POLYGON);
float _col[3] = { 0.0, 0.3, 0.0 };
if (conf.BW.get() || conf.STEREO_RB.get()
|| conf.STEREO_RG.get()) {
glColor3fv(graycolor(_col));
} else {
glColor3fv(_col);
}
// if we have texture maps the green floor should be deeper to avoid strange effects...
// can be deeper in any case (why not?) fd.getzmin - 0.1 km (=-100m)
GLfloat greenheight =
fd.getzmin() + ((float) conf.offset.get() / 1000.0) -
0.1;
glVertex3f((GLfloat) fd.getxmax() + conf.getborder(),
(GLfloat) fd.getymin() - conf.getborder(),
greenheight);
glVertex3f((GLfloat) fd.getxmax() + conf.getborder(),
(GLfloat) fd.getymax() + conf.getborder(),
greenheight);
glVertex3f((GLfloat) fd.getxmin() - conf.getborder(),
(GLfloat) fd.getymax() + conf.getborder(),
greenheight);
glVertex3f((GLfloat) fd.getxmin() - conf.getborder(),
(GLfloat) fd.getymin() - conf.getborder(),
greenheight);
glEnd();
//glPopAttrib();
glEnable (GL_LIGHTING); // reset our default
}
// TESTING
/* float _x,_y;
proj.get_xy(47.0,11.0,_x,_y);
glRasterPos3f(_x,_y,3.5);
glColor3f(0,0,0);
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,'X');
*/
// textured maps... on flat ground
if (conf.MAP.get() && !conf.LANDSCAPE.get()) {
for (int r = conf.getMapIndexLow();
r < conf.getMapIndexHigh(); r++) {
Map map;
map.set_proj_pointer(&proj);
map.set_conf_pointer(&conf);
if (conf.getMapFilename(r)[ conf.getMapFilename(r).size() - 3] == 'j'
|| conf.getMapFilename(r)[ conf.getMapFilename(r).size() - 3] == 'J') {
map.readMap_jpeg(conf.getMapFilename(r),
conf.getmap_width(r),
conf.getmap_height(r));
} else {
map.readMap(conf.getMapFilename(r),
conf.getmap_width(r),
conf.getmap_height(r));
}
map.setcenter_lat(fd.getcenter_lat());
map.setcenter_lon(fd.getcenter_lon());
map.settop(conf.getmap_top(r));
map.setbottom(conf.getmap_bottom(r));
map.setright(conf.getmap_right(r));
map.setleft(conf.getmap_left(r));
map.setglmap(fd.getzmin() +
((float) conf.offset.get() / 1000.0) -
0.01, conf.COMPRESSION.get(), true,
conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get());
}
}
//Terrain with textured map
if (conf.LANDSCAPE.get() && conf.MAP.get()) {
short int _max_h_bkp;
short int _min_h_bkp;
if (conf.MODULATE.get()) {
short int _max_h = -8888;
short int _min_h = -8888;
_max_h_bkp = conf.getmax_h();
_min_h_bkp = conf.getmin_h();
// get min and max_h with dummy readDEM_fast
// vielleicht kriegt man das noch mal schneller hin?
//cout << conf.getmax_h() << " max -- min: " << conf.getmin_h() << endl;
if (conf.getmax_h() == -9999
|| conf.getmin_h() == -9999) {
for (int r = conf.getMapIndexLow();
r < conf.getMapIndexHigh(); r++) {
Landscape land;
land.set_conf_pointer(&conf);
land.set_sealevel((double) conf.
get_sealevel());
land.set_sealevel2((double) conf.
get_sealevel2
());
land.set_sealevel3((double) conf.
get_sealevel3());
land.set_proj_pointer(&proj);
land.setdownscalefactor(conf.
getdownscalefactor
());
land.setcenter_lat(fd.
getcenter_lat
());
land.setcenter_lon(fd.
getcenter_lon
());
land.setmax_lat(conf.
getmap_top(r));
land.setmin_lat(conf.
getmap_bottom(r));
land.setmax_lon(conf.
getmap_right(r));
land.setmin_lon(conf.
getmap_left(r));
land.setgrid_lat(conf.
getdem_grid_lat
());
land.setgrid_lon(conf.
getdem_grid_lon
());
int ret = land.readDEM(conf.
getDemFileName(),
conf.
getdem_rows(),
conf.
getdem_columns(),
conf.
getdem_lat_min(),
conf.
getdem_lat_max(),
conf.
getdem_lon_min(),
conf.
getdem_lon_max
(), true);
if (ret == 99) {
if (conf.DEBUG.get())
cout << "readDEM returned 99 " << endl << flush;
glEndList();
goto landscape_jump;
}
if (_min_h == -8888)
_min_h = land.getmin_h();
if (_max_h == -8888)
_max_h = land.getmax_h();
if (land.getmin_h() < _min_h)
_min_h = land.getmin_h();
if (land.getmax_h() > _max_h)
_max_h = land.getmax_h();
}
if (conf.getmax_h() == -9999)
conf.setmax_h(_max_h);
if (conf.getmin_h() == -9999)
conf.setmin_h(_min_h);
}
if (conf.VERBOSE.get()) {
cout <<
"Max and Min Alt used for modulated colors: (min, max): "
<< conf.getmin_h() << ", " << conf.
getmax_h() << endl;
}
}
//cout << "entering Terrain AND Map mode..." << endl;
for (int r = conf.getMapIndexLow();
r < conf.getMapIndexHigh(); r++) {
Map map;
map.set_proj_pointer(&proj);
map.set_conf_pointer(&conf);
Landscape land;
land.set_conf_pointer(&conf);
land.set_sealevel((double) conf.get_sealevel());
land.set_sealevel2((double) conf.get_sealevel2());
land.set_sealevel3((double) conf.get_sealevel3());
land.set_proj_pointer(&proj);
land.setdownscalefactor(conf.getdownscalefactor());
if (conf.getMapFilename(r)[conf.getMapFilename(r).size() - 3] == 'j') {
map.readMap_jpeg(conf.getMapFilename(r),
conf.getmap_width(r),
conf.getmap_height(r));
} else {
map.readMap(conf.getMapFilename(r),
conf.getmap_width(r),
conf.getmap_height(r));
}
land.setcenter_lat(fd.getcenter_lat());
land.setcenter_lon(fd.getcenter_lon());
map.setcenter_lat(fd.getcenter_lat());
map.setcenter_lon(fd.getcenter_lon());
land.setmax_lat(conf.getmap_top(r));
land.setmin_lat(conf.getmap_bottom(r));
land.setmax_lon(conf.getmap_right(r));
land.setmin_lon(conf.getmap_left(r));
land.setgrid_lat(conf.getdem_grid_lat());
land.setgrid_lon(conf.getdem_grid_lon());
int ret = land.readDEM(conf.getDemFileName(),
conf.getdem_rows(),
conf.getdem_columns(),
conf.getdem_lat_min(),
conf.getdem_lat_max(),
conf.getdem_lon_min(),
conf.getdem_lon_max());
if (ret == 99) {
if (conf.DEBUG.get())
cout << "readDEM returned 99 " << endl << flush;
glEndList();
goto landscape_jump;
}
// load map, but do not set texture coordinates
// that will be done via land.setgltrainglestrip_tex
map.setglmap(fd.getzmin() +
((float) conf.offset.get() / 1000.0) -
0.01, conf.COMPRESSION.get(),
conf.MAPS_UNLIGHTED.get(),
conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get(), false);
if (conf.getmax_h() != -9999) {
land.setmax_h(conf.getmax_h());
//cout << "max = "<< conf.getmax_h() << endl;
}
if (conf.getmin_h() != -9999) {
land.setmin_h(conf.getmin_h());
//cout << "min = "<<conf.getmin_h() << endl;
}
land.setgltrianglestrip_tex(conf.colmapnumber.
get(),
conf.colmap2number.
get(),
(conf.STEREO_RB.get()
|| conf.STEREO_RG.
get()
|| conf.BW.get()));
}
// restore values
if (conf.MODULATE.get()) {
conf.setmax_h(_max_h_bkp);
conf.setmin_h(_min_h_bkp);
}
}
// Terrain, only
if (conf.LANDSCAPE.get() && !conf.MAP.get()) {
Landscape land;
land.set_conf_pointer(&conf);
land.set_sealevel((double) conf.get_sealevel());
land.set_sealevel2((double) conf.get_sealevel2());
land.set_sealevel3((double) conf.get_sealevel3());
land.set_proj_pointer(&proj);
land.setdownscalefactor(conf.getdownscalefactor());
land.setcenter_lat(fd.getcenter_lat());
land.setcenter_lon(fd.getcenter_lon());
//adding a border in km (border_land)
float border_deg_lat = conf.getborder_land_lat() / DEGDIST;
float border_deg_lon =
(conf.getborder_land_lon() / DEGDIST) /
cos(fd.getcenter_lat() * PI_180);
land.setmin_lat(fd.getlatmin() - border_deg_lat);
land.setmin_lon(fd.getlonmin() - border_deg_lon);
land.setmax_lat(fd.getlatmax() + border_deg_lat);
land.setmax_lon(fd.getlonmax() + border_deg_lon);
if (conf.VERBOSE.get()) {
cout << "Terrain boundaries: " << land.getmax_lat() << " " << land.getmin_lat() <<
" " << land.getmin_lon() << " " << land.getmax_lon() << endl;
}
land.setgrid_lat(conf.getdem_grid_lat());
land.setgrid_lon(conf.getdem_grid_lon());
int ret = land.readDEM(conf.getDemFileName(), conf.getdem_rows(),
conf.getdem_columns(), conf.getdem_lat_min(),
conf.getdem_lat_max(), conf.getdem_lon_min(),
conf.getdem_lon_max());
if (ret == 99) {
if (conf.DEBUG.get())
cout << "readDEM returned 99 " << endl << flush;
glEndList();
goto landscape_jump;
}
if (conf.getmax_h() != -9999) {
land.setmax_h(conf.getmax_h());
//cout << "max = "<< conf.getmax_h() << endl;
}
if (conf.getmin_h() != -9999) {
land.setmin_h(conf.getmin_h());
//cout << "min = "<<conf.getmin_h() << endl;
}
if (conf.VERBOSE.get()) {
cout <<
"Max and Min Alt used for colors: (min, max): "
<< land.getmin_h() << ", " << land.
getmax_h() << endl;
/*
// these are derived from landscape.cpp
int latsteps = (int) (((float)
(land.getsteps_lat() -
3 *
conf.
getdownscalefactor()) /
(float) conf.
getdownscalefactor()) +
0.5);
int lonsteps = (int) (((float)
(land.getsteps_lon() -
2 *
conf.getdownscalefactor() -
1) /
(float) conf.
getdownscalefactor()) +
0.5);
cout << "The Surface is build with " <<
latsteps * lonsteps * 2
<< " Triangles." << endl;
*/
cout << "DEM data is read in byte order: ";
if (conf.BIGENDIAN.get()) {
cout << "big endian" << endl;
} else {
cout << "little endian" << endl;
}
if (conf.input_dem_factor.get() != 1.0)
cout << "DEM input scaling factor: " << conf.input_dem_factor.get() << endl;
}
land.setgltrianglestrip(conf.WIRE.get(),
conf.colmapnumber.get(),
conf.colmap2number.get(),
(conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get()), false);
}
glEndList(); //end of the list
if (conf.DEBUG.get()) {
cout << "GenLandList END: " << flush;
#ifndef ONLY_OSMESA
glutReportErrors();
#endif
cout << endl << flush;
}
}
// mouse callback-function (when any button is clicked)
#ifndef ONLY_OSMESA
void mouseClickMove(int xmouse, int ymouse)
{
if (HELP || INFO) {
return;
}
if (!conf.MOUSE.get()) {
if (MOUSEWARPED) {
lastmx = conf.getwidth() / 2;
lastmy = conf.getheight() / 2;
MOUSEWARPED = false;
return;
}
}
if (lastmx == 0) { //nothing to do in first call
lastmx = xmouse; //but set the x and y in global lastmx
lastmy = ymouse; //and lastmy
return;
}
//double factor;
if (lastmx == 0) { //nothing to do in first call
lastmx = xmouse; //but set the x and y in global lastmx
lastmy = ymouse; //and lastmy
return;
}
double _dx = xmouse - lastmx; //put differentials into _dx and _dy
double _dy = ymouse - lastmy;
lastmx = xmouse; //save present position
lastmy = ymouse;
//cout << "dx dy " << _dx << " " << _dy << endl;
if (abs(_dx) > 20 || abs(_dy) > 20) {
// we don't want the view to skip, so ignore what is most likely the first call
return;
}
if (!conf.ORTHOVIEW.get()) { // Only if we are not in ORTHO view
float _mstep;
// left button: move towards point (center) and back
if (middlebuttonstate == GLUT_DOWN && leftbuttonstate != GLUT_DOWN) {
double factor;
if(_dy < 0){
factor = pow(0.99, abs((int)_dy));
} else {
factor = pow(1.01, abs((int)_dy));
}
if (!conf.MARKER.get()) {
// move to central point
ego.setx(ego.getx() * factor);
ego.sety(ego.gety() * factor);
ego.setz(ego.getz() * factor);
//if (conf.DEBUG.get())
// cout << "wo marker ego.x: " << ego.getx() << " ego.y: " << ego.gety() << " ego.z: " << ego.getz() << endl;
} else {
//move towards markerpos
// z-koordinates is fscked, even for !MARKER!!!
//cout << "egoz/3: " << ego.getz()/3<< " markerz: "<<fd.getmarkerz()<< " fac" << factor << endl;
//cout << (ego.getz()/3) - fd.getmarkerz() << "diff " << endl;
//if (conf.DEBUG.get())
// cout << "w marker ego.x: " << ego.getx() << " ego.y: " << ego.gety() << " ego.z: " << ego.getz() << endl;
ego.setx( - fd.getmarkerx() + ( ego.getx() + fd.getmarkerx()) * factor );
ego.sety( - fd.getmarkery() + ( ego.gety() + fd.getmarkery()) * factor );
ego.setz( ( fd.getmarkerz() + ( ego.getz()/conf.z_scale.get() - fd.getmarkerz()) * factor ) * conf.z_scale.get() );
}
// this is probably not needed...
//ego.movef(0.2 * _dy);
}
if (middlebuttonstate == GLUT_DOWN && leftbuttonstate == GLUT_DOWN) {
ego.moveu(0.2 * _dy);
ego.moves(0.2 * _dx);
} else if (leftbuttonstate == GLUT_DOWN && middlebuttonstate != GLUT_DOWN) { // left button is down
if (args_info.smooth_mouse_given) {
_mstep = 10;
} else {
_mstep = 3;
}
if (!conf.MARKER.get()) {
ego.spinmoveradial(_dx / _mstep); //spin the ego around the view centre while adjusting view angle
ego.spinmovevertical(_dy / _mstep); // grosser Teiler = sanfte Bewegung
} else {
ego.spinmoveradialpoint(_dx / _mstep, fd.getmarkerx(), fd.getmarkery()); //spin the ego around the view centre while adjusting view angle
ego.spinmoveverticalpoint(_dy / _mstep, fd.getmarkerx(), fd.getmarkery()); // grosser Teiler = sanfte Bewegung
}
}
}
if (conf.FOLLOW.get()) {
update_diff_pos();
}
if (!conf.MOUSE.get()) {
// warp pointer to center of window
glutWarpPointer(conf.getwidth() / 2, conf.getheight() / 2);
MOUSEWARPED = true;
}
glutPostRedisplay(); //update display
}
void mouseClickState(int button, int state, int xmouse, int ymouse)
{
if (button == GLUT_RIGHT_BUTTON) {
rightbuttonstate = state;
}
if (button == GLUT_MIDDLE_BUTTON) {
middlebuttonstate = state;
}
if (button == GLUT_LEFT_BUTTON) {
leftbuttonstate = state;
}
}
// mouse callback-function
void mouseMove(int xmouse, int ymouse)
{
if (HELP || INFO) {
return;
}
// return imediatley if any menu is in use
if (MENUSTATE) {
//cout << "menu acitve" << endl;
return;
}
// if menu was used right before avoid "jumping"
if (MENUPOPPED) {
//cout << "mouse move called after menu POPPPED" << endl;
lastmx = 0;
lastmy=0;
MENUPOPPED = false;
//glutWarpPointer(conf.getwidth() / 2, conf.getheight() / 2);
//MOUSEWARPED = true;
return;
}
//if pointer was warped before (callback is triggered by warping...)
//
if (MOUSEWARPED) {
lastmx = conf.getwidth() / 2;
lastmy = conf.getheight() / 2;
MOUSEWARPED = false;
return;
}
if (lastmx == 0) { //nothing to do in first call
lastmx = xmouse; //but set the x and y in global lastmx
lastmy = ymouse; //and lastmy
return;
}
double _dx = xmouse - lastmx; //put differences to _dx and _dy
double _dy = ymouse - lastmy;
lastmx = xmouse; //save actual position
lastmy = ymouse;
//cout << "dx dy " << _dx << " " << _dy << endl;
// this should prevent "jumps" if the curser enters the window again!
// seems to be effective
if (abs(_dx)+abs(_dy) > 100) {
return;
}
if (!conf.ORTHOVIEW.get()) {
float _mstep;
if (args_info.smooth_mouse_given) {
_mstep = 10;
} else {
_mstep = 3;
}
ego.spinz(_dx / _mstep); //spin the ego!
ego.spinx(-_dy / _mstep); // grosser Teiler = sanfte Bewegung
} else {
ego.shiftx(_dx * conf.getorthoshift());
ego.shifty(_dy * conf.getorthoshift());
if (conf.FOLLOW.get())
update_diff_pos(); // ????
InitGL(conf.getwidth(), conf.getheight());
}
// warp pointer to center of window
glutWarpPointer(conf.getwidth() / 2, conf.getheight() / 2);
MOUSEWARPED = true;
glutPostRedisplay(); //update display
}
#endif
//mouse functions excluded for ONLY_OSMESA
//Draw only.
void Draw(void)
{
//Timecheck drawtime("Draw", &conf);
//call the lists
glCallList(landscape_displ_list);
if (conf.FLIGHT.get()) {
if (conf.MARKER.get()) {
if (!conf.ORTHOVIEW.get()) {
fd.draw_marker(conf.offset.get(),
conf.z_scale.get(),
conf.STEREO_RB.get()
|| conf.STEREO_RG.get()
|| conf.BW.get());
} else {
fd.draw_marker_ortho();
}
}
}
if (conf.LIFTS.get()) {
lifts.drawLifts(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get());
lifts.drawLiftsTxt(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get(), &ego);
}
if (conf.WAYPOINTS.get()) {
waypoints.drawWaypoints(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get());
waypoints.drawWaypointsTxt(conf.STEREO_RB.get()
|| conf.STEREO_RG.get() || conf.BW.get(), &ego);
}
//glCallList(lifts_displ_list);
glCallList(flightdata_displ_list);
glCallList(airspace_displ_list);
//lifts.drawLifts(1);
if (conf.INFO.get()) {
DrawInfo();
}
//drawtime.checknow("end of Draw");
}
// set the position and view-direction...
void setpos(void)
{
glLoadIdentity();
glRotatef(ego.getspinx(), 1.0, 0.0, 0.0); //do the viewpoint transformation
glRotatef(ego.getspiny(), 0.0, 1.0, 0.0);
glRotatef(ego.getspinz(), 0.0, 0.0, 1.0);
glTranslatef(ego.getx(), ego.gety(), -ego.getz());
glScalef(1.0, 1.0, conf.z_scale.get()); //do z-axis scaling
}
void DrawBackground(int bgType)
{
// Use an orthographic view, and save all matrices
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// we also save the enables, as we plan to enable/disable a lot of things
glPushAttrib(GL_ENABLE_BIT);
// disable the expensive tests
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);
// vertical gradient
//int bgType = 2;
switch (bgType) {
case 1:
// solid background // like the old one
glDisable(GL_TEXTURE_2D);
glColor3f(conf.background_color_1r.get(), conf.background_color_1g.get(), conf.background_color_1b.get());
glBegin(GL_QUADS);
glVertex2i( 1, -1);
glVertex2i( 1, 1);
glVertex2i(-1, 1);
glVertex2i(-1, -1);
glEnd();
break;
case 2:
// vertical gradient
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glColor3f(conf.background_color_1r.get(), conf.background_color_1g.get(), conf.background_color_1b.get()); // lighter!
glVertex2i(-1, 1);
glVertex2i( 1, 1);
glColor3f(conf.background_color_2r.get(), conf.background_color_2g.get(), conf.background_color_2b.get());
glVertex2i( 1, -1);
glVertex2i(-1, -1);
glEnd();
break;
case 3:
// horizontal gradient
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glColor3f(conf.background_color_1r.get(), conf.background_color_1g.get(), conf.background_color_1b.get());
glVertex2i(-1, 1);
glVertex2i(-1, -1);
glColor3f(conf.background_color_2r.get(), conf.background_color_2g.get(), conf.background_color_2b.get());
glVertex2i( 1, -1);
glVertex2i( 1, 1);
glEnd();
break;
}
//
// restore our states
// this is done so as to leave the modelview matrix as the last active
// matrix
//
glPopAttrib();
glMatrixMode (GL_PROJECTION);
glPopMatrix();
glMatrixMode (GL_MODELVIEW);
glPopMatrix();
}
// rendering routine
void DrawGLScene(void)
{
// temporary
/* if (conf.DEBUG.get()) {
cout << "entered DRAWGLSCENE" << endl;
}
*/
//Timecheck drawgl("DrawGLScene", &conf);
if (HELP) {
HelpScreen();
return;
}
if (INFO) {
InfoScreen();
return;
}
if (conf.ORTHOVIEW.get())
InitGL(conf.getwidth(), conf.getheight());
if (conf.STEREO_RB.get() || conf.STEREO_RG.get() || conf.BW.get()) {
glClearColor(0.144f, 0.144f, 0.144f, 0.0f); //Background is set to nice blue sky (grayscaled :)
} else {
glClearColor(0.1f, 0.1f, 0.5f, 0.0f); //Background is set to nice blue sky
}
if (!conf.OFFSCREEN.get() && !conf.OSMESA.get()) {
glDrawBuffer(GL_BACK);
} else {
glDrawBuffer(GL_FRONT);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear screen and depth buffer
glLoadIdentity(); //load identity matrix
if(! (conf.BW.get() || conf.FOG.get() || conf.STEREO_RB.get() || conf.STEREO_RG.get())) {
DrawBackground(conf.background.get());
}
if (!conf.ORTHOVIEW.get()) {
setpos();
}
// light position was here.... maybe here again for dynamic light-pos moving?
GLfloat light_position[4] = { 5.0, 5.0, 1.0, 0.0 }; //set the light position
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// stereoscopic drawing with 2 images
if (conf.STEREO.get() && !conf.ORTHOVIEW.get()) {
float _ed = conf.eye_dist.get();
if (conf.SWAP_STEREO.get())
_ed *= -1.0;
// render left image!
glViewport(0, 0, conf.getwidth() / 2, conf.getheight());
ego.moves(-_ed / 2);
setpos();
Draw();
ego.moves(_ed / 2);
//render right image!
glViewport(conf.getwidth() / 2, 0, conf.getwidth() / 2,
conf.getheight());
ego.moves(_ed / 2);
setpos();
Draw();
ego.moves(-_ed / 2);
glViewport(0, 0, conf.getwidth(), conf.getheight());
}
// stereoscopic drawing with hardware
#ifndef ONLY_OSMESA
if (conf.STEREO_HW.get() && !conf.ORTHOVIEW.get()) {
float _ed = conf.eye_dist.get();
if (conf.SWAP_STEREO.get())
_ed *= -1.0;
// render left image!
glDrawBuffer(GL_BACK_LEFT);
ego.moves(_ed / 2);
setpos();
Draw();
ego.moves(-_ed / 2);
glClear(GL_DEPTH_BUFFER_BIT);
//render right image!
glDrawBuffer(GL_BACK_RIGHT);
ego.moves(-_ed / 2);
setpos();
Draw();
ego.moves(_ed / 2);
}
#endif
// stereoscopic red/green or red/blue
if ((conf.STEREO_RB.get() || conf.STEREO_RG.get())
&& !conf.ORTHOVIEW.get()) {
float _ed = conf.eye_dist.get();
if (conf.SWAP_STEREO.get())
_ed *= -1.0;
//render red image
ego.moves(-_ed / 2);
setpos();
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
Draw();
ego.moves(_ed / 2);
glClear(GL_DEPTH_BUFFER_BIT);
//render green or blue image
ego.moves(_ed / 2);
setpos();
if (conf.STEREO_RB.get()) {
glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
}
if (conf.STEREO_RG.get()) {
glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
}
Draw();
ego.moves(-_ed / 2);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
// normal rendering , if no stereo or ortho-mode
if ((!conf.STEREO.get() && !conf.STEREO_RB.get()
&& !conf.STEREO_RG.get() && !conf.STEREO_HW.get())
|| conf.ORTHOVIEW.get()) {
Draw();
//cout << "normal" << endl;
}
if (!conf.OFFSCREEN.get() && !conf.OSMESA.get()) {
#ifndef ONLY_OSMESA
glutSwapBuffers();
#endif
} //and swap the buffers
// every frame will be written as jpeg
if (conf.MOVIE.get()) {
screenshot();
}
//drawgl.checknow("end");
}
#ifndef ONLY_OSMESA
void ReSizeGLScene(int nwidth, int nheight)
{
if (nheight == 0) // this shouldnt happen
nheight = 1;
conf.setwidth(nwidth);
conf.setheight(nheight);
//glViewport(0, 0, conf.getwidth(), conf.getheight()); // Reset The Current Viewport
InitGL(conf.getwidth(), conf.getheight());
glutPostRedisplay();
}
#endif
// initialize openGL
void InitGL(int Width, int Height) //set GL-Window size
{
if (conf.DEBUG.get()) {
cout << "entered void InitGL(WxH)" << Width << "x" << Height << endl << flush;
//cout << "going to call glPixelstorei(GL_PACK_ALIGNEMENT, 1) ..." << flush;
}
//#ifndef __OSX__
glPixelStorei(GL_PACK_ALIGNMENT, 1); //Prevents some strange crashes in the glReadPixels in the screenshot-function
//#else
// if (conf.DEBUG.get()) {
// cout << "... (SKIPPED __OSX__) ..." << flush;
// }
//#endif
/*if (conf.DEBUG.get()) {
cout << "... returned from glPixelstorei(GL...)" << endl << flush;
}*/
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glEnable(GL_NORMALIZE); // Enables normalizing of normal vectors
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT, GL_FILL);
glDisable(GL_COLOR_MATERIAL);
glLineWidth(1.0);
if (conf.SHADE.get()) {
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
} else {
glShadeModel(GL_FLAT);
}
if (conf.FOG.get()) {
glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_EXP2);
glFogf(GL_FOG_DENSITY, conf.fogdensity.get());
GLfloat fogcolor[4] = { 0.1, 0.1, 0.5, 1.0 };
if (!(conf.BW.get() || conf.STEREO_RG.get()
|| conf.STEREO_RB.get())) {
glFogfv(GL_FOG_COLOR, fogcolor);
} else {
glFogfv(GL_FOG_COLOR, graycolor(fogcolor));
}
} else {
glDisable(GL_FOG);
}
GLfloat light_ambient[4] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat light_color[4] = { 0.8, 0.8, 0.8, 1.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//light-position is set in DrawGLScene, after setpos
//set viewport and projection
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset the projection Matrix
if (!conf.ORTHOVIEW.get()) {
int _q=0;
double _far;
glGetIntegerv(GL_DEPTH_BITS, (GLint*) &_q);
float screenfactor;
float _near;
//maybe this can be exactly calculated!
if (_q < 24) {
_near = 1.0;
} else {
_near = 0.2;
}
if (_q < 24) {
_far = 300.0;
} else {
//_far = 500.0;
_far = 600.0;
// cout << "FAR: 600 " <<_q << endl;
}
if (_q > 24) {
_far = 2000.0;
// cout << "FAR: 2000 " << _q <<endl;
}
if (args_info.clipping_far_given) {
_far = args_info.clipping_far_arg;
}
if (args_info.clipping_near_given) {
_near = args_info.clipping_near_arg;
}
if (conf.DEBUG.get()){
cout << "Depth buffer: " << _q << " bit." <<endl
<< "Clipping near: " << _near << endl << "Clipping far: "<< _far <<endl;
double _s = pow(2.0, _q);
cout << "depth values: " << _s << endl;;
double zf = _far * _near / ((1/(double)_s)*(_far-_near) -_far);
double zb = _far * _near / ((((double)_s-1)/_s) * (_far-_near) -_far);
cout << "next near: " << zf <<endl<<"next far: "<< zb<<endl;
}
float _front_clip_width =
2.0 * _near * tan(((float) conf.aov.get() / 2.0) *
(M_PI / 180.0));
if (conf.STEREO.get()) {
screenfactor =
((_front_clip_width) *
((float) conf.getheight() /
((float) conf.getwidth() / 2.0))) / 2.0;
} else {
screenfactor =
((_front_clip_width) *
((float) conf.getheight() /
(float) conf.getwidth())) / 2.0;
}
glFrustum(-_front_clip_width / 2.0,
_front_clip_width / 2.0, -screenfactor,
screenfactor, _near,
_far * conf.getdownscalefactor());
} else {
//experimental for now
float xclip = (conf.orthoclipping.get() / 2.0); //*(conf.getwidth() / conf.getheight()) ;
float yclip =
(conf.orthoclipping.get() / 2.0) *
((float) conf.getheight() / (float) conf.getwidth());
glOrtho(ego.getOx() - xclip, ego.getOx() + xclip,
ego.getOy() - yclip, ego.getOy() + yclip, -20.0,
20.0);
}
//reset MatrixModel to our default state policy
glMatrixMode(GL_MODELVIEW);
}
void screenshot() {
Timecheck sshottime("Screenshot",&conf);
if ( (strcasecmp(conf.get_image_format().c_str(), "jpg") == 0)
|| (strcasecmp(conf.get_image_format().c_str(), "jpeg") == 0) )
screenshot_jpeg();
if ( strcasecmp(conf.get_image_format().c_str(),"rgb") == 0)
screenshot_rgb();
sshottime.checknow("");
}
// ersetzt von screenshot_jpeg
//framebuffer schreibt den framebuffer in ein *.rgb file
void screenshot_rgb() {
short int* rgbmap = new short int[conf.getwidth()*conf.getheight()*3];
glReadPixels(0,0,conf.getwidth(),conf.getheight(),GL_RGB,GL_UNSIGNED_SHORT,rgbmap);
char name[1024];
//char _buff[2];
cout << "writing a rgb " << conf.getwidth() << "x" << conf.getheight() << " picture with 6 Byte per Pixel" << endl;
std::string basename = conf.get_basename();
std::string path = conf.get_save_path();
if (args_info.basename_given) { basename = args_info.basename_arg; }
if (args_info.save_path_given) { path = args_info.save_path_arg + SEPERATOR; }
if (args_info.os_outfile_given) {
sprintf(name, "%s", args_info.os_outfile_arg);
} else {
ifstream testfile;
while (1) {
sprintf(name, "%s%s%d.rgb", path.c_str(), basename.c_str(), conf.getnextframewriternumber());
//cout << name << " geht nixht" << endl;
testfile.open(name, ios::binary);
if (!testfile) {break;}
testfile.close();
//cout << name << " NEIN gibt schon" << endl;
}
//cout << name << " geht!!!!" << endl;
}
ofstream framefile;
framefile.open(name, ios::binary);
// for (int _z=0 ;_z < (width*height*3); _z++){
// framefile.write((char*)&rgbmap[_z],2);
// }
for (int _z=(conf.getwidth()*(conf.getheight()-1)*3); _z>=0; _z=_z-conf.getwidth()*3) {
for (int _s=0; _s<conf.getwidth()*3; _s++) {
framefile.write((char*)&rgbmap[_z+_s],2);
}
}
cout << name << " written." << endl <<flush;
//cout << sizeof (GLushort) << endl;
delete [] rgbmap;
}
void screenshot_jpeg()
{
// rendering in the GL_BACK buffer and reading from it will only work on
// software GL. If GL_BACK is a hardware buffer it wont work
// maybe they dont render overlayed regions of the buffer.
// we will read from (GL_FRONT)
glFinish();
unsigned char *tmpArray, *jpegArray;
int quality = conf.jpeg_quality.get();
char name[1024];
int index = 0;
tmpArray =
new unsigned char[conf.getwidth() * conf.getheight() * 3];
jpegArray =
new unsigned char[conf.getwidth() * conf.getheight() * 3];
if (conf.OSMESA.get())
glReadBuffer(GL_FRONT);
if (conf.OFFSCREEN.get())
glReadBuffer(GL_FRONT);
glFinish();
glReadPixels(0, 0, conf.getwidth(), conf.getheight(), GL_RGB,
GL_UNSIGNED_BYTE, tmpArray);
index = 0;
for (int _z = (conf.getwidth() * (conf.getheight() - 1) * 3);
_z >= 0; _z = _z - conf.getwidth() * 3) {
for (int _s = 0; _s < conf.getwidth() * 3; _s++) {
jpegArray[index] = tmpArray[_z + _s];
index++;
}
}
if (conf.VERBOSE.get()) {
cout << "writing a " << conf.getwidth() << "x" << conf.
getheight() << " jpg image" << endl;
cout << "jpeg quality: " << conf.jpeg_quality.get() << endl;
}
std::string basename = conf.get_basename();
std::string path = conf.get_save_path();
if (args_info.basename_given) { basename = args_info.basename_arg; }
if (args_info.save_path_given) { path = args_info.save_path_arg + SEPERATOR; }
if (args_info.os_outfile_given) {
sprintf(name, "%s", args_info.os_outfile_arg);
} else {
ifstream testfile;
while (1) {
sprintf(name, "%s%s%d.jpg", path.c_str(), basename.c_str(), conf.getnextframewriternumber());
//cout << name << " geht nixht" << endl;
testfile.open(name, ios::binary);
if (!testfile) {break;}
testfile.close();
//cout << name << " NEIN gibt schon" << endl;
}
//cout << name << " geht!!!!" << endl;
}
//sprintf(name, "%s%s%d.jpg", path.c_str(), basename.c_str(), conf.getnextframewriternumber());
//sprintf(name, "frame%d.jpg", conf.getnextframewriternumber());
//if (args_info.os_outfile_given) {
// sprintf(name, "%s", args_info.os_outfile_arg);
//}
write_JPEG_file(conf.getwidth(), conf.getheight(), quality, name,
(JSAMPLE *) jpegArray);
if (conf.VERBOSE.get())
cout << "jpeg: " << name << " written ! " << endl <<
flush;
delete tmpArray;
delete jpegArray;
}
#ifndef ONLY_OSMESA
void IdleFunc(void)
{
//needed in movie mode, to decide whether to repeat frame, or to move marker forward
bool FORWARD=false;
bool REPEAT=false;
if (conf.JOYSTICK.get() && !conf.ORTHOVIEW.get()) {
glutForceJoystickFunc();
}
// determine framerate;
timeval now;
timeval last;
//timezone zone;
//zone.tz_minuteswest = 0;
//zone.tz_dsttime = DST_NONE;
gettimeofday(&now, NULL);
last = conf.get_time_mem();
conf.set_time_mem(now);
//cout << "last : " << last.tv_sec << " " << last.tv_usec << endl;
//cout << "now : " << now.tv_sec << " " << now.tv_usec << endl;
float rate =
1.0 / (((float) now.tv_sec - (float) last.tv_sec)
+
(((float) now.tv_usec -
(float) last.tv_usec) / 1000000.0));
//cout << "rate: " << rate << endl;
conf.set_framerate(rate);
conf.set_fps(rate);
// conf.movi_msec is millisecs usleep is in microseconds!
if (conf.FLYING.get() && !conf.GPSD.get() ) {
usleep((unsigned long int) conf.movie_msecs.get() * 1000);
if (conf.FLYING_REPEAT.get())
REPEAT=true;
if (conf.FLYING_AUTO_REPEAT.get()) {
if (conf.get_fps() > conf.idle_auto_repeat_limit.get()) {
//cout << "fps exceeeds limit" << endl;
REPEAT=true;
}
}
if (REPEAT) {
movie_repeat_counter++;
//cout << "repeater : "<< movie_repeat_counter << endl;
if (movie_repeat_counter >= conf.movie_repeat_factor.get()) {
movie_repeat_counter=0;
FORWARD=true;
}
} else {
FORWARD=true;
}
}
/*
// update date in GPSD mode
if (conf.GPSD.get())
fd.querygps();
// FLYING with GPSD: marker is kept at recent position!
if (conf.FLYING.get() && conf.GPSD.get() ) {
fd.marker_head();
}
*/
if (conf.SPINNING.get() != 0) {
ego.spinmoveradialpoint(conf.SPINNING.get(), fd.getmarkerx(), fd.getmarkery() ); //spin the ego around the marker
if (conf.FOLLOW.get())
update_diff_pos();
}
if (conf.GPSD.get()) {
if (fd.querygps() == 0) { // new data;
if (conf.FLYING.get())
fd.marker_head();
GenFlightList();
// leaving area!
//cout << fd.getlat() << " " << fd.getlon() << endl;
//cout <<"lim: "<< fd.getcenter_lat()+(conf.getborder_land_lat()/DEGDIST) <<
//" " << fd.getcenter_lat()-(conf.getborder_land_lat()/DEGDIST) << endl;
//cout << "lim2: " << fd.getcenter_lon()+(conf.getborder_land_lon()/DEGDIST)
//<< " " << fd.getcenter_lon()-(conf.getborder_land_lon()/DEGDIST) << endl;
if (conf.LANDSCAPE.get() && !conf.MAP.get()) {
// hier noch die limits checken
// in lat gehts manchmal ueber die kante..? ZZZZZ
// immer noch? sieht ganz gut aus soweit
if (fd.getlat() > fd.getcenter_lat()-conf.getdem_grid_lat()*conf.getdownscalefactor()+((conf.getborder_land_lat()-0.0)/DEGDIST)
|| fd.getlat() < fd.getcenter_lat()+conf.getdem_grid_lat()*conf.getdownscalefactor()-((conf.getborder_land_lat()-0.0)/DEGDIST)
|| fd.getlon() > fd.getcenter_lon()-conf.getdem_grid_lon()*conf.getdownscalefactor()+(((conf.getborder_land_lon()-0.0)/DEGDIST)/
cos(fd.getcenter_lat() * PI_180))
|| fd.getlon() < fd.getcenter_lon()+conf.getdem_grid_lon()*conf.getdownscalefactor()-(((conf.getborder_land_lon()-0.0)/DEGDIST)/
cos(fd.getcenter_lat() * PI_180))
) {
//cout << "REBUILDING LANDSCAPE" << endl;
fd.setcenter_lat(fd.getlat());
fd.setcenter_lon(fd.getlon());
fd.setlatmin(fd.getlat());
fd.setlatmax(fd.getlat());
fd.setlonmax(fd.getlon());
fd.setlonmin(fd.getlon());
GenLandscapeList();
}
}
}
}
// forward exits only in flying mode without gpsd
if (FORWARD && conf.FLIGHT.get()) {
fd.forward_marker();
if (fd.getcycles() == 0)
Ende(0);
// wenn marker bewegt neue flightlist machen
if (conf.MARKER_RANGE.get()) {