glutmain.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:15k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // glutmain.cpp
  2. // 
  3. // Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
  4. //
  5. // GLUT front-end for Celestia.
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. #include <iostream>
  12. #include <fstream>
  13. #include <algorithm>
  14. #include <cstdlib>
  15. #include <cctype>
  16. #include <cstring>
  17. #include <time.h>
  18. #include <unistd.h>
  19. #include <celengine/gl.h>
  20. #ifndef MACOSX
  21. #include <GL/glut.h>
  22. #else
  23. #include <Carbon/Carbon.h>
  24. #include <GLUT/glut.h>
  25. #endif
  26. #include <celengine/celestia.h>
  27. #include <celmath/vecmath.h>
  28. #include <celmath/quaternion.h>
  29. #include <celutil/util.h>
  30. #include <celutil/debug.h>
  31. #include <celmath/mathlib.h>
  32. #include <celengine/astro.h>
  33. #include "celestiacore.h"
  34. /* what are you supposed to be?
  35. #include "popt.h"
  36. */
  37. using namespace std;
  38. char AppName[] = "Celestia";
  39. static CelestiaCore* appCore = NULL;
  40. //static bool fullscreen = false;
  41. static bool ready = false;
  42. // Mouse motion tracking
  43. static int lastX = 0;
  44. static int lastY = 0;
  45. static bool leftButton = false;
  46. static bool middleButton = false;
  47. static bool rightButton = false;
  48. static int mainWindow = 1;
  49. // Mouse wheel button assignments
  50. #define MOUSE_WHEEL_UP   3
  51. #define MOUSE_WHEEL_DOWN 4
  52. static void Resize(int w, int h)
  53. {
  54.     appCore->resize(w, h);
  55. }
  56. /*
  57.  * Definition of GLUT callback functions
  58.  */
  59. static void Display(void)
  60. {
  61.     if (ready)
  62.     {
  63.         appCore->draw();
  64.         glutSwapBuffers();
  65.     }
  66. }
  67. static void Idle(void)
  68. {
  69.     if (glutGetWindow() != mainWindow)
  70.         glutSetWindow(mainWindow);
  71.     appCore->tick();
  72.     Display();
  73. }
  74. static void MouseDrag(int x, int y)
  75. {
  76.     int buttons = 0;
  77.     if (leftButton)
  78.         buttons |= CelestiaCore::LeftButton;
  79.     if (rightButton)
  80.         buttons |= CelestiaCore::RightButton;
  81.     if (middleButton)
  82.         buttons |= CelestiaCore::MiddleButton;
  83.     appCore->mouseMove(x - lastX, y - lastY, buttons);
  84.     lastX = x;
  85.     lastY = y;
  86. }
  87. static void MouseButton(int button, int state, int x, int y)
  88. {
  89. #ifdef MACOSX
  90.     if (button == GLUT_LEFT_BUTTON) {
  91.         UInt32 mods=GetCurrentKeyModifiers ();
  92.         if      (mods & optionKey)  button=GLUT_MIDDLE_BUTTON;
  93.         else if (mods & cmdKey)     button=GLUT_RIGHT_BUTTON;
  94.     }
  95. #endif /* MACOSX */
  96.     // On Linux, mouse wheel up and down are usually translated into
  97.     // mouse button 4 and 5 down events.
  98.     if (button == MOUSE_WHEEL_UP)
  99.     {
  100.         appCore->mouseWheel(-1.0f, 0);
  101.     }
  102.     else if (button == MOUSE_WHEEL_DOWN)
  103.     {
  104.         appCore->mouseWheel(1.0f, 0);
  105.     }
  106.     else if (button == GLUT_LEFT_BUTTON)
  107.     {
  108.         leftButton = (state == GLUT_DOWN);
  109.         if (state == GLUT_DOWN)
  110.             appCore->mouseButtonDown(x, y, CelestiaCore::LeftButton);
  111.         else
  112.             appCore->mouseButtonUp(x, y, CelestiaCore::LeftButton);
  113.     }
  114.     else if (button == GLUT_RIGHT_BUTTON)
  115.     {
  116.         rightButton = (state == GLUT_DOWN);
  117.         if (state == GLUT_DOWN)
  118.             appCore->mouseButtonDown(x, y, CelestiaCore::RightButton);
  119.         else
  120.             appCore->mouseButtonUp(x, y, CelestiaCore::RightButton);
  121.     }
  122.     else if (button == GLUT_MIDDLE_BUTTON)
  123.     {
  124.         middleButton = (state == GLUT_DOWN);
  125.         if (state == GLUT_DOWN)
  126.             appCore->mouseButtonDown(x, y, CelestiaCore::MiddleButton);
  127.         else
  128.             appCore->mouseButtonUp(x, y, CelestiaCore::MiddleButton);
  129.     }
  130.     lastX = x;
  131.     lastY = y;
  132. }
  133. static void KeyPress(unsigned char c, int x, int y)
  134. {
  135.     // Ctrl-Q exits
  136.     if (c == '21')
  137.         exit(0);
  138.     appCore->charEntered((char) c);
  139.     //appCore->keyDown((int) c);
  140. }
  141. static void KeyUp(unsigned char c, int x, int y)
  142. {
  143.     appCore->keyUp((int) c);
  144. }
  145. static void HandleSpecialKey(int key, bool down)
  146. {
  147.     int k = -1;
  148.     switch (key)
  149.     {
  150.     case GLUT_KEY_UP:
  151.         k = CelestiaCore::Key_Up;
  152.         break;
  153.     case GLUT_KEY_DOWN:
  154.         k = CelestiaCore::Key_Down;
  155.         break;
  156.     case GLUT_KEY_LEFT:
  157.         k = CelestiaCore::Key_Left;
  158.         break;
  159.     case GLUT_KEY_RIGHT:
  160.         k = CelestiaCore::Key_Right;
  161.         break;
  162.     case GLUT_KEY_HOME:
  163.         k = CelestiaCore::Key_Home;
  164.         break;
  165.     case GLUT_KEY_END:
  166.         k = CelestiaCore::Key_End;
  167.         break;
  168.     case GLUT_KEY_F1:
  169.         k = CelestiaCore::Key_F1;
  170.         break;
  171.     case GLUT_KEY_F2:
  172.         k = CelestiaCore::Key_F2;
  173.         break;
  174.     case GLUT_KEY_F3:
  175.         k = CelestiaCore::Key_F3;
  176.         break;
  177.     case GLUT_KEY_F4:
  178.         k = CelestiaCore::Key_F4;
  179.         break;
  180.     case GLUT_KEY_F5:
  181.         k = CelestiaCore::Key_F5;
  182.         break;
  183.     case GLUT_KEY_F6:
  184.         k = CelestiaCore::Key_F6;
  185.         break;
  186.     case GLUT_KEY_F7:
  187.         k = CelestiaCore::Key_F7;
  188.         break;
  189.     case GLUT_KEY_F11:
  190.         k = CelestiaCore::Key_F11;
  191.         break;
  192.     case GLUT_KEY_F12:
  193.         k = CelestiaCore::Key_F12;
  194.         break;
  195.     }
  196.     /* Glut doesn't seem to handle Keypad Keys, so we can't pass them on.
  197.        They will be passed as the appropriate Special keys instead */
  198.     if (k >= 0)
  199.     {
  200.         if (down)
  201.             appCore->keyDown(k);
  202.         else
  203.             appCore->keyUp(k);
  204.     }
  205. }
  206. static void SpecialKeyPress(int key, int x, int y)
  207. {
  208.     HandleSpecialKey(key, true);
  209. }
  210. static void SpecialKeyUp(int key, int x, int y)
  211. {
  212.     HandleSpecialKey(key, false);
  213. }
  214. #ifdef MACOSX
  215. static void menuCallback (int which);
  216. static void initMenus(void) {
  217.     int gMain,gNavigation,gTime,gLabels,gRendering;
  218.     int gViews,gSpaceflight,gNumber,gJoystick,gMouse;
  219.     gMain=gNavigation=gTime=gLabels=gRendering=0;
  220.     gViews=gSpaceflight=gNumber=gJoystick=gMouse=0;
  221.     gNavigation=glutCreateMenu(menuCallback);
  222.     glutAddMenuEntry("Center                      C",101);
  223.     glutAddMenuEntry("Go closer                   G",102);
  224.     glutAddMenuEntry("Follow                      F",103);
  225.     glutAddMenuEntry("Orbit                       Y",104);
  226.     glutAddMenuEntry("Track                       T",105);
  227.     glutAddMenuEntry("Move closer              HOME",106);
  228.     glutAddMenuEntry("Move farther              END",107);
  229.     glutAddMenuEntry("Cancel motion             ESC",108);
  230.     glutAddMenuEntry("*Roll Camera            <- ->",000);
  231.     glutAddMenuEntry("*Camera Pitch         UP DOWN",000);
  232.     gTime=glutCreateMenu(menuCallback);
  233.     glutAddMenuEntry("10x faster                  L",201);
  234.     glutAddMenuEntry("10x slower                  K",202);
  235.     glutAddMenuEntry("Reverse time                J",203);
  236.     gLabels=glutCreateMenu(menuCallback);
  237.     glutAddMenuEntry("Toggle planet/moon          N",301);
  238.     glutAddMenuEntry("Toggle star                 B",302);
  239.     glutAddMenuEntry("Toggle constellation        =",303);
  240.     glutAddMenuEntry("Toggle info text            V",304);
  241.     gRendering=glutCreateMenu(menuCallback);
  242.     glutAddMenuEntry("Wireframe                   W",401);
  243.     glutAddMenuEntry("Per-pixel lighting     CTRL+P",402);
  244.     glutAddMenuEntry("Vertex programs        CTRL+V",403);
  245.     glutAddMenuEntry("Show FPS                    `",404);
  246.     glutAddMenuEntry("*Limiting magnitude       ] [",000);
  247.     glutAddMenuEntry("*Ambient illumination     } {",000);
  248.     glutAddMenuEntry("*Narrow/Widen FOV         , .",000);
  249.     gViews=glutCreateMenu(menuCallback);
  250.     glutAddMenuEntry("Galaxies                    U",501);
  251.     glutAddMenuEntry("Planet orbits               O",502);
  252.     glutAddMenuEntry("Constellations              /",503);
  253.     glutAddMenuEntry("Atmospheres            CTRL+A",504);
  254.     glutAddMenuEntry("Cloud textures              I",505);
  255.     glutAddMenuEntry("Night side planet maps CTRL+L",506);
  256.     glutAddMenuEntry("Equatorial coordinates      ;",507);
  257.     gSpaceflight=glutCreateMenu(menuCallback);
  258.     glutAddMenuEntry("Stop                       F1",601);
  259.     glutAddMenuEntry("Set velocity to 1 km/s     F2",602);
  260.     glutAddMenuEntry("Set velocity to 1,000 km/s F3",603);
  261.     glutAddMenuEntry("Set velocity to lightspeed F4",604);
  262.     glutAddMenuEntry("Set velocity to 10^6 km/s  F5",605);
  263.     glutAddMenuEntry("Set velocity to 1 AU/s     F6",606);
  264.     glutAddMenuEntry("Set velocity to 1 ly/s     F7",607);
  265.     glutAddMenuEntry("Increase velocity (exp)     A",608);
  266.     glutAddMenuEntry("Decrease velocity (exp)     Z",609);
  267.     glutAddMenuEntry("Reverse direction           Q",610);
  268.     glutAddMenuEntry("Movement to screen origin   X",611);
  269.     gNumber=glutCreateMenu(menuCallback);
  270.     glutAddMenuEntry("Stop rotation               5",701);
  271.     glutAddMenuEntry("*Yaw left/right           4 6",702);
  272.     glutAddMenuEntry("*Pitch up/down            2 8",703);
  273.     glutAddMenuEntry("*Roll left/right          7 9",704);
  274.     gJoystick=glutCreateMenu(menuCallback);
  275.     glutAddMenuEntry("Enable joystick            F8",801);
  276.     glutAddMenuEntry("*Yaw                   X axis",000);
  277.     glutAddMenuEntry("*Pitch                 Y axis",000);
  278.     glutAddMenuEntry("*Roll             L,R trigger",000);
  279.     glutAddMenuEntry("*Speed             Button 1,2",000);
  280.     gMain=glutCreateMenu(menuCallback);
  281.     glutAddMenuEntry("Select the sun (Home)    H",001);
  282. /*    glutAddMenuEntry("Select by name       ENTER",002); */
  283.     glutAddMenuEntry("Run demo                         D",003);
  284. /*   
  285.     gMouse=glutCreateMenu(menuCallback);
  286.     glutAddSubMenu("*Orient camera    CLICK+DRAG",000);
  287.     glutAddSubMenu("*Orbit object    RCLICK+DRAG",000);
  288. */
  289.     glutAddSubMenu("Selected Object", gNavigation);
  290.     glutAddSubMenu("Time",gTime);
  291.     glutAddSubMenu("Labels",gLabels);
  292.     glutAddSubMenu("Rendering",gRendering);
  293.     glutAddSubMenu("Views",gViews);
  294.     glutAddSubMenu("Spaceflight",gSpaceflight);
  295.     glutAddSubMenu("Number Pad",gNumber);
  296.     glutAddSubMenu("Joystick",gJoystick);
  297. /*
  298.     glutAddSubMenu("Mouse",gMouse);
  299. */
  300.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  301. }
  302. #define CTRLKEY(KEY) (KEY-'a'+(char)1)
  303. #define caseKey(CASE,WHICH) 
  304.     case (CASE): 
  305.         appCore->charEntered((char)(WHICH)); 
  306.         appCore->keyDown((int)(WHICH)); 
  307.         appCore->keyUp((int)(WHICH)); 
  308.         break
  309. #define caseKeySpecial(CASE,WHICH) 
  310.     case (CASE): 
  311.         appCore->keyDown(CelestiaCore::Key_##WHICH); 
  312.         appCore->keyUp(CelestiaCore::Key_##WHICH); 
  313.         break
  314. static void menuCallback (int which) {
  315.     switch(which) {
  316.         // main menu
  317.         caseKey(1,'h');
  318.         caseKey(2,0x13);
  319.         caseKey(3,'d');
  320.         // navigation
  321.         caseKey(101,'c');
  322.         caseKey(102,'g');
  323.         caseKey(103,'f');
  324.         caseKey(104,'y');
  325.         caseKey(105,'t');
  326.         caseKeySpecial(106,Home);
  327.         caseKeySpecial(107,End);
  328.         caseKey(108,0x27);
  329.         // time
  330.         caseKey(201,'l');
  331.         caseKey(202,'k');
  332.         caseKey(203,'j');
  333.         // labels
  334.         caseKey(301,'n');
  335.         caseKey(302,'b');
  336.         caseKey(303,'=');
  337.         caseKey(304,'v');
  338.         // rendering
  339.         caseKey(401,'w');
  340.         caseKey(402,CTRLKEY('p'));
  341.         caseKey(403,CTRLKEY('v'));
  342.         caseKey(404,'`');
  343.         // views
  344.         caseKey(501,'u');
  345.         caseKey(502,'o');
  346.         caseKey(503,'/');
  347.         caseKey(504,CTRLKEY('a'));
  348.         caseKey(505,'i');
  349.         caseKey(506,CTRLKEY('l'));
  350.         caseKey(507,';');
  351.         // spaceflight
  352.         caseKeySpecial(601,F1);
  353.         caseKeySpecial(602,F2);
  354.         caseKeySpecial(603,F3);
  355.         caseKeySpecial(604,F4);
  356.         caseKeySpecial(605,F5);
  357.         caseKeySpecial(606,F6);
  358.         caseKeySpecial(607,F7);
  359.         caseKey(608,'a');
  360.         caseKey(609,'z');
  361.         caseKey(610,'q');
  362.         caseKey(611,'x');
  363.         // number pad
  364.         caseKey(701,5);
  365.         // joystick
  366.         caseKeySpecial(801,F8);
  367.     }
  368. }
  369. #endif
  370. #ifdef MACOSX
  371. static void killLastSlash(char *buf) {
  372.   int i=strlen(buf);
  373.   while (--i && buf[i]!='/') {}
  374.   if (buf[i]=='/') buf[i]=0;
  375. }
  376. static void dirFixup(char *argv0) {
  377.     char *myPath;
  378.     assert(myPath=(char *)malloc(strlen(argv0)+128));
  379.     strcpy(myPath,argv0);
  380.     killLastSlash(myPath);
  381.     killLastSlash(myPath);
  382.     // BEWARE!  GLUT is going to put us here anyways, DO NOT TRY SOMEWHERE ELSE
  383.     // or you will waste your goddamn time like I did
  384.     // damn undocumented shit.
  385.     strcat(myPath,"/Resources");
  386.     chdir(myPath);
  387.     free(myPath);
  388. }
  389. #endif /* MACOSX */
  390. int main(int argc, char* argv[])
  391. {
  392. setlocale(LC_ALL, "");
  393. setlocale(LC_NUMERIC, "C");
  394. bindtextdomain(PACKAGE, LOCALEDIR);
  395. bind_textdomain_codeset(PACKAGE, "UTF-8");
  396. textdomain(PACKAGE);
  397.    #ifdef MACOSX
  398.    #define BUNDLEONLY 1
  399.    #ifndef BUNDLEONLY
  400.    // for bundles only!
  401.    if (argc==2 && argv[1][0]=='-' && argv[1][1]=='p' && argv[1][2]=='s' && argv[1][3]=='n')
  402.    {
  403.    #endif /* !BUNDLEONLY */
  404.         argc--;
  405.         dirFixup(argv[0]);
  406.     #ifndef BUNDLEONLY
  407.     } else  
  408.     /* BE REAL DAMN CAREFUL WITH THIS LINGERING IF! */
  409.     #endif /* !BUNDLEONLY */
  410.     #else /* MACOSX */
  411.     if (chdir(CONFIG_DATA_DIR) == -1)
  412.     {
  413.         cerr << "Cannot chdir to '" << CONFIG_DATA_DIR <<
  414.             "', probably due to improper installationn";
  415.     }
  416.     #endif /* !MACOSX */
  417.     // Not ready to render yet
  418.     ready = false;
  419.     char c;
  420. int startfile = 0;
  421.     while ((c = getopt(argc, argv, "v::f")) > -1)
  422.     {
  423.         if (c == '?')
  424.         {
  425.             cout << "Usage: celestia [-v] [-f <filename>]n";
  426.             exit(1);
  427.         }
  428.         else if (c == 'v')
  429.         {
  430.             if(optarg)
  431.                 SetDebugVerbosity(atoi(optarg));
  432.             else
  433.                 SetDebugVerbosity(0);
  434.         }
  435. else if (c == 'f') {
  436. startfile = 1;
  437. }
  438.     }
  439.     appCore = new CelestiaCore();
  440.     if (appCore == NULL)
  441.     {
  442.         cerr << "Out of memory.n";
  443.         return 1;
  444.     }
  445.     if (!appCore->initSimulation())
  446.     {
  447.         return 1;
  448.     }
  449.     glutInit(&argc, argv);
  450.     glutInitWindowSize(480, 360);
  451.     glutInitWindowPosition(0, 0);
  452.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  453.     mainWindow = glutCreateWindow("Celestia");
  454.     Resize(480, 360);
  455.     glutReshapeFunc(Resize);
  456.     glutDisplayFunc(Display);
  457.     glutIdleFunc(Idle);
  458.     glutMouseFunc(MouseButton);
  459.     glutMotionFunc(MouseDrag);
  460.     glutKeyboardFunc(KeyPress);
  461.     glutKeyboardUpFunc(KeyUp);
  462.     glutSpecialFunc(SpecialKeyPress);
  463.     glutSpecialUpFunc(SpecialKeyUp);
  464.     #ifdef MACOSX
  465.     initMenus();
  466.     #endif
  467.     // GL should be all set up, now initialize the renderer.
  468.     appCore->initRenderer();
  469.     // Set the simulation starting time to the current system time
  470.     time_t curtime=time(NULL);
  471.     appCore->start((double) curtime / 86400.0 + (double) astro::Date(1970, 1, 1));
  472.     #ifdef MACOSX
  473.     /* localtime in Darwin is is reentrant only
  474.        equiv to Linux localtime_r()
  475.        should probably port !MACOSX code to use this too, available since
  476.        libc 5.2.5 according to manpage */
  477.     struct tm *temptime=localtime(&curtime);
  478.     appCore->setTimeZoneBias(temptime->tm_gmtoff);
  479.     appCore->setTimeZoneName(temptime->tm_zone);
  480.     #else
  481.     localtime(&curtime); // Only doing this to set timezone as a side effect
  482.     appCore->setTimeZoneBias(-timezone);
  483.     appCore->setTimeZoneName(tzname[daylight?0:1]);
  484.     #endif
  485. if (startfile == 1) {
  486. if (argv[argc - 1][0] == '-') {
  487. cout << "Missing Filename.n";
  488. return 1;
  489. }
  490. cout << "*** Using CEL File: " << argv[argc - 1] << endl;
  491. appCore->runScript(argv[argc - 1]);
  492. }
  493.     ready = true;
  494.     glutMainLoop();
  495.     return 0;
  496. }