main.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <string>
00021 #include <iostream>
00022 
00023 #include <archon/util/term.H>
00024 #include <archon/util/text.H>
00025 #include <archon/util/options.H>
00026 #include <archon/util/logger.H>
00027 #include <archon/util/uri.H>
00028 #include <archon/util/web_client.H>
00029 #include <archon/util/file.H>
00030 
00031 #include <archon/x3d/server/x3d.H>
00032 #include <archon/x3d/server/server.H>
00033 #include <archon/x3d/server/parse_xml.H>
00034 //#include <archon/x3d/server/font.H>
00035 #include <archon/x3d/server/text.H>
00036 
00037 #include <archon/x3d/sai/listener.H>
00038 
00039 #include <archon/3dconsole/exception.H>
00040 #include <archon/3dconsole/options.H>
00041 #include <archon/3dconsole/scene_view.H>
00042 
00043 using namespace std;
00044 
00045 namespace Archon
00046 {
00047   using namespace Utilities;
00048 
00049   namespace Console3d
00050   {
00051     struct LoaderJob: X3D::Loader::Job
00052     {
00053       LoaderJob(Ref<X3D::Loader> l, const vector<string> &uriList):
00054         X3D::Loader::Job(l, Uri(), uriList, X3D::Loader::uriType_X3D) {}
00055     };
00056 
00057     string getPrivateDir()
00058     {
00059       return File::getHomeDir() + "/.archon";
00060     }
00061 
00062     void evokePrivateDir(string path)
00063     {
00064       string d = getPrivateDir();
00065       if(!Text::isPrefixOf(d, path)) return;
00066       if(!File::isDir(d)) File::makeDir(d);
00067     }
00068 
00069     int main(int argc, const char *argv[])
00070     {
00071       Options o;
00072 
00073       o.addSwitch("h", "help", opt_help, true,
00074                   "Describe the parameters");
00075       o.addSwitch("c", "config-file", opt_configFile, opt_configFile,
00076                   "Set the path of the configuration file",
00077                   Options::wantArg_always);
00078       o.addSwitch("",  "save-config", opt_saveConfig, true,
00079                   "Save the modified configuration into the configuration file");
00080       o.addSwitch("",  "dump-node-defs", opt_dumpNodeDefs, true,
00081                   "Dump the definition of all known X3D nodes and exit");
00082       o.addConfig("F", "full-screen", opt_fullScreen, true,
00083                   "View in fullscreen mode",
00084                   Options::wantArg_optional);
00085       o.addConfig("r", "resolution", opt_resolution, opt_resolution,
00086                   "Set resolution",
00087                   Options::wantArg_always);
00088       o.addConfig("B", "background-color", opt_backgroundColor, opt_backgroundColor,
00089                   "R,G,B or R,G,B,A color of background (range 0-1)",
00090                   Options::wantArg_always);
00091       o.addConfig("e", "eyepoint", opt_eyepoint, opt_eyepoint,
00092                   "Location of the eye in the default view",
00093                   Options::wantArg_always);
00094       o.addConfig("l", "lookat", opt_lookat, opt_lookat,
00095                   "Point of interest in the default view",
00096                   Options::wantArg_always);
00097       o.addConfig("v", "field-of-view", opt_fieldOfView, opt_fieldOfView,
00098                   "Smallest edge-to-edge angle of viewplane when seen from "
00099                   "the eye",
00100                   Options::wantArg_always);
00101       o.addConfig("H", "head-light", opt_headLight, true,
00102                   "Enable head light",
00103                   Options::wantArg_optional);
00104       o.addConfig("L", "show-light-sources", opt_showLightSources, true,
00105                   "Display light sources as points in their color",
00106                   Options::wantArg_optional);
00107       o.addConfig("w", "wireframe", opt_wireframe, true,
00108                   "Render the scene in wireframe instead of the usual filled "
00109                   "polygons",
00110                   Options::wantArg_optional);
00111       o.addConfig("t", "texture", opt_texture, true,
00112                   "Enable use of texture mapping",
00113                   Options::wantArg_optional);
00114       o.addConfig("m", "mipmap", opt_mipmap, true,
00115                   "Enable mipmaped textures. You need this for textures whos "
00116                   "dimentions are not a power of 2. Note also that there are "
00117                   "some probplems when using mipmaps together with projective "
00118                   "textures.",
00119                   Options::wantArg_optional);
00120       o.addConfig("N", "show-normals", opt_showNormals, true,
00121                   "Reveal the normal at each rendered vertex",
00122                   Options::wantArg_optional);
00123       o.addConfig("", "text-as-quads-mode", opt_textAsQuadsMode, true,
00124                   "Display the quad for each character instead of the character itself.",
00125                   Options::wantArg_optional);
00126       o.addConfig("f", "frame-rate", opt_frameRate, opt_frameRate,
00127                   "Set the number of frames per second",
00128                   Options::wantArg_always);
00129       o.addConfig("s", "subdivision", opt_subdivision, opt_subdivision,
00130                   "Set subdivision of curved geometry such as sphers, tori, "
00131                   "cylinders and cones",
00132                   Options::wantArg_always);
00133       o.addConfig("b", "application-heartbeat", opt_applicationHeartbeat, opt_applicationHeartbeat,
00134                   "Set the delay in seconds between pings from the server to "
00135                   "the applications",
00136                   Options::wantArg_always);
00137       o.addConfig("p", "corba-endpoint-port", opt_corbaEndpointPort, opt_corbaEndpointPort,
00138                   "The TCP/IP port on which the CORBA Orb listens (-1 for auto "
00139                   "assign)",
00140                   Options::wantArg_always);
00141       o.addConfig("a", "accept-clients", opt_acceptClients, true,
00142                   "Accept connection from client applications via the SAI",
00143                   Options::wantArg_optional);
00144       o.addConfig("n", "console-name", opt_consoleName, opt_consoleName,
00145                   "Set the name of this server as known by SAI clients",
00146                   Options::wantArg_always);
00147       o.addConfig("D", "dump-scene", opt_dumpScene, true,
00148                   "Write out a textual description of the scene at the time of "
00149                   "exit",
00150                   Options::wantArg_optional);
00151       o.addConfig("P", "progressive-load", opt_progressiveLoad, true,
00152                   "View scene while loading",
00153                   Options::wantArg_optional);
00154       o.addConfig("", "font-path", opt_fontPath, opt_fontPath,
00155                   "A colon seperated list of directories in which to look "
00156                   "for fonts. Empty entries are ignored.",
00157                   Options::wantArg_always);
00158 
00159       bool optionError = false;
00160       if(o.processCommandLine(argc, argv, true))
00161         optionError = true;
00162 
00163       bool configFileSpecified = !opt_configFile.empty();
00164       if(opt_configFile.empty())
00165         opt_configFile = getPrivateDir() + "/archon.conf";
00166       try
00167       {
00168         if(o.processConfigFile(opt_configFile))
00169           optionError = true;
00170       }
00171       catch(Options::FileAccessException &e)
00172       {
00173         if(configFileSpecified)
00174           cerr << "WARNING: " + e.getMessage() + "\n";
00175       }
00176 
00177       if(o.processCommandLine(argc, argv, false))
00178         optionError = true;
00179 
00180       if(opt_help)
00181       {
00182         cout <<
00183           "3D-Console by Brian Kristiansen & Kristian Spangsege\n"
00184           "\n"
00185           "Synopsis: " + string(argv[0]) + " URI\n"
00186           "\n"
00187           "The URI must refer to an X3D file and\n"
00188           "may be specified relative to the current working directory.\n"
00189           "If you specify a fragment identifier it will be interpreted\n"
00190           "as the name of the viewpoint to use. For example\n"
00191           "  " + argv[0] + " house.x3d#front\n"
00192           "will render the house from the viewpoint named 'front'.\n"
00193           "\n"
00194           "Available options:\n" +
00195           o.list();
00196         return optionError ? 1 : 0;
00197       }
00198 
00199       if(optionError)
00200       {
00201         cerr << "Try --help\n";
00202         return 1;
00203       }
00204 
00205       if(opt_saveConfig) try
00206       {
00207         evokePrivateDir(opt_configFile);
00208         o.saveConfigFile(opt_configFile);
00209       }
00210       catch(Options::FileAccessException &e)
00211       {
00212         cerr << "WARNING: " + e.getMessage() + "\n";
00213       }
00214 
00215       // Treat 1st arg if present as URL of X3D file to load
00216       if(argc > 2)
00217       {
00218         cerr << "Too many aguments\n";
00219         cerr << "Try --help\n";
00220         return 1;
00221       }
00222 
00223       bool uriSpecified = false;
00224       UriReference x3dUriReference;
00225       string uriException;
00226       if(argc>1) try
00227       {
00228         x3dUriReference = UriReference(argv[1]);
00229         uriSpecified = true;
00230       }
00231       catch(Uri::SyntaxException &e)
00232       {
00233         uriException = Uri::explain(e);
00234       }
00235 
00236       if(!uriException.empty())
00237       {
00238         cerr << uriException;
00239         exit(1);
00240       }
00241 
00242       Logger *logger = Logger::get();
00243 
00244       {
00245         vector<string> fontDirs;
00246         {
00247           string::size_type i = 0;
00248           for(;;)
00249           {
00250             string::size_type j = opt_fontPath.find(':', i);
00251             if(j == string::npos) j = opt_fontPath.size();
00252             if(j != i) fontDirs.push_back(opt_fontPath.substr(i, j-i));
00253             if(j == opt_fontPath.size()) break;
00254             i = j+1;
00255           }
00256         }
00257 
00258         for(unsigned i=0; i<fontDirs.size(); ++i)
00259           X3D::addFontPath(fontDirs[i]);
00260 
00261         X3D::initialize();
00262 
00263         if(opt_dumpNodeDefs)
00264         {
00265           X3D::NodeType::describeAll(logger);
00266           exit(0);
00267         }
00268 
00269         Ref<X3D::Server> server = X3D::Server::get(opt_consoleName, opt_frameRate, logger,
00270                                                    uriSpecified, x3dUriReference.getUri(), opt_progressiveLoad);
00271 
00272         // Activate the SAI connection listener
00273         if(opt_acceptClients)
00274         {
00275           Time applicationHeartbeat(opt_applicationHeartbeat);
00276           Ref<X3D::SAI::Listener> listener =
00277             new X3D::SAI::Listener(server, applicationHeartbeat,
00278                                    opt_corbaEndpointPort);
00279 
00280           try
00281           {
00282             listener->startServingClientRequests(server->getRootScene()->getRootGroup());
00283             server->setListener(listener);
00284           }
00285           catch(X3D::SAI::Listener::NameServerException &e)
00286           {
00287             logger->log("WARNING: " + e.getMessage() + " (Client access disabled)");
00288           }
00289         }
00290 
00291         // Set up the default viewpoint
00292         CoordSystem3x3 viewCoordSystem(opt_eyepoint, Matrix3x3(Vector3(0, 1, 0), opt_eyepoint - opt_lookat));
00293 
00294         string viewpointName = x3dUriReference.getFragmentIdentifier();
00295         if(!viewpointName.empty()) viewpointName.erase(0, 1);
00296 
00297         viewScene(server,
00298                   viewpointName,
00299                   viewCoordSystem,
00300                   opt_fieldOfView,
00301                   dist(opt_eyepoint, opt_lookat),
00302                   opt_backgroundColor,
00303                   opt_resolution.x, opt_resolution.y,
00304                   opt_fullScreen, opt_showLightSources, opt_headLight,
00305                   opt_wireframe, opt_texture, opt_mipmap, opt_showNormals, opt_textAsQuadsMode,
00306                   opt_subdivision.x, opt_subdivision.y,
00307                   opt_frameRate);
00308 
00309         //if(opt_dumpScene) cout << server->dumpScenegraph();
00310       }
00311 
00312       logger->log("Waiting for all threads to terminate");
00313       Thread::mainExitWait();
00314 
00315       return 0;
00316     }
00317   }
00318 }
00319 
00320 int main(int argc, const char *argv[]) throw()
00321 {
00322   using namespace Archon::Utilities;
00323 
00324   set_unexpected(Exception::terminal<Archon::Console3d::exceptionCatchInfo>);
00325   set_terminate (Exception::terminal<Archon::Console3d::exceptionCatchInfo>);
00326 
00327   return Archon::Console3d::main(argc, argv);
00328 }

Generated on Sun Jul 30 22:55:41 2006 for Archon by  doxygen 1.4.4