00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
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 }