#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #include "TestKdTree.h" #include "WinCmdLineParser.h" #ifdef __cplusplus extern "C" { #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char *argv[]) #endif { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 // parse windows-style command line WinCmdLineParser cmdparser(strCmdLine); KdTreeAppListener::Options options; try { cmdparser .addOpt("i","infile", ARGUMENT_REQUIRED) .addOpt("o","outfile", ARGUMENT_REQUIRED) .addOpt("l","logfile", ARGUMENT_REQUIRED) .addOpt("d","demomode", ARGUMENT_NONE) .addOpt("","buildmode", ARGUMENT_REQUIRED) .addOpt("","maxdepth", ARGUMENT_REQUIRED) .addOpt("","kt", ARGUMENT_REQUIRED) .addOpt("","ki", ARGUMENT_REQUIRED) .addOpt("r","rendermode", ARGUMENT_REQUIRED) .addOpt("s","scenemgr", ARGUMENT_REQUIRED) .addOpt("","comment", ARGUMENT_REQUIRED) .addOpt("e","enhancevis", ARGUMENT_NONE); cmdparser.getOpt("i", options.mDemoInfileName); cmdparser.getOpt("o", options.mDemoOutfileName); cmdparser.getOpt("l", options.mDemoLogfileName); cmdparser.getOpt("comment", options.mComment); options.mDemoMode = cmdparser.getOpt("d"); options.mEnhancedVisibility = cmdparser.getOpt("e"); std::string tmp; std::stringstream s; if (cmdparser.getOpt("buildmode", tmp)) { int bm = KdTree::KDBM_NOTSET; for (int i = 0; i < KdTree::KDBM_SIZE; i ++) { if (tmp == KdTreeAppListener::BUILDMETHOD[i]) bm = i; } if (bm != KdTree::KDBM_NOTSET) { options.mBuildMethod = bm; } else { MessageBox(NULL, ("Invalid argument for option --buildmode: " + tmp).c_str(), "Error", MB_OK | MB_ICONERROR ); return -1; } } if (cmdparser.getOpt("maxdepth", tmp)) { s << tmp; s >> options.mMaxDepth; s.clear(); } if (cmdparser.getOpt("kt", tmp)) { s << tmp; s >> options.mKT; s.clear(); } if (cmdparser.getOpt("ki", tmp)) { s << tmp; s >> options.mKI; s.clear(); } if (cmdparser.getOpt("r",tmp)) { int rm = KdTree::KDRM_NOTSET; for (int i = 0; i < KdTree::KDRM_SIZE; i ++) { if (tmp == KdTreeAppListener::RENDERMETHOD[i]) rm = i; } if (rm != KdTree::KDRM_NOTSET) { options.mRenderMethod = rm; } else { MessageBox(NULL, ("Invalid argument for option --rendermode: " + tmp).c_str(), "Error", MB_OK | MB_ICONERROR ); return -1; } } if (cmdparser.getOpt("s",tmp)) { int sm = KdTreeAppListener::SM_NOTSET; for (int i = 0; i < KdTreeAppListener::SM_SIZE; i ++) { if (tmp == KdTreeAppListener::SCENEMANAGER[i]) sm = i; } if (sm != KdTreeAppListener::SM_NOTSET) { options.mSceneManager = sm; } else { MessageBox(NULL, ("Invalid argument for option --scenemgr: " + tmp).c_str(), "Error", MB_OK | MB_ICONERROR ); return -1; } } } catch (std::string s) { MessageBox(NULL, s.c_str(), "Error", MB_OK | MB_ICONERROR ); return -1; } // Create application object KdTreeApp app(options); #else // TODO: unix-style getopt // Create application object KdTreeApp app; #endif SET_TERM_HANDLER; // init random number generator // srand(time(0)); try { app.go(); } catch( Ogre::Exception& e ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; #endif } return 0; } #ifdef __cplusplus } #endif #define ENT_GRID 0x01 #define ENT_RND 0x02 #define ENT_SPC 0x04 #define ENT_MOV 0x08 #define ENT_PLN 0x10 void KdTreeApp::setupResources(void) { String tmp; ConfigFile cfDeath; char *errptr; int base = 10; cfDeath.load("testKdTree.cfg"); mSceneFiles = cfDeath.getSetting("scene"); tmp = cfDeath.getSetting("shadows"); StringUtil::toLowerCase(tmp); if (tmp == "on") mShadowsEnabled = true; else mShadowsEnabled = false; tmp = cfDeath.getSetting("planedim"); mPlaneDim = static_cast(strtod(tmp.c_str(), &errptr)); tmp = cfDeath.getSetting("randomcount"); mRandomCount = static_cast(strtol(tmp.c_str(), &errptr, base)); tmp = cfDeath.getSetting("selectentities"); mSelectEntities = static_cast(strtol(tmp.c_str(), &errptr, base)); tmp = cfDeath.getSetting("count"); mModelCount = static_cast(strtol(tmp.c_str(), &errptr, base)); tmp = cfDeath.getSetting("spacing"); mModelSpacing = static_cast(strtol(tmp.c_str(), &errptr, base)); tmp = cfDeath.getSetting("radius"); mRotationRadius = static_cast(strtod(tmp.c_str(), &errptr)); tmp = cfDeath.getSetting("period"); mOptions.mRotationPeriod = static_cast(strtod(tmp.c_str(), &errptr)); tmp = cfDeath.getSetting("movespeed"); mOptions.mMoveSpeed = static_cast(strtod(tmp.c_str(), &errptr)); tmp = cfDeath.getSetting("rotatespeed"); mOptions.mRotateSpeed = static_cast(strtod(tmp.c_str(), &errptr)); // command line has preference over config file if (mOptions.mDemoInfileName.empty()) mOptions.mDemoInfileName = cfDeath.getSetting("demoinfile"); if (mOptions.mDemoOutfileName.empty()) mOptions.mDemoOutfileName = cfDeath.getSetting("demooutfile"); if (mOptions.mDemoLogfileName.empty()) mOptions.mDemoLogfileName = cfDeath.getSetting("demologfile"); ExampleApplication::setupResources(); } void KdTreeApp::createScene(void) { createMaterials(); Entity *deaths; SceneNode *nodes; std::string entName = "death"; std::string nodeName = "DeathNode"; int i, j, x, z; Real planeHalf = mPlaneDim / 2; Real planeThreeEights = mPlaneDim * 3 / 8; Real planeSixth = mPlaneDim / 6; // load scene from file if (mSceneFiles != "") { // don't load the other stuff loadScene(mSceneFiles); // top view mTopCam->setPosition(Vector3(1232, 3990, -1477)); // walkthrough view mCamNode->setPosition(Vector3(827.885, 184.435, -524.984)); mCamNode->setOrientation(Quaternion(0.98935, 0.0348082, -0.141246, 0.00496945)); mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true); } else { mCamNode->setPosition(Vector3(1280,600,1666)); mCamNode->setOrientation(Quaternion(0.936893, -0.124586, 0.323813, 0.04306)); //mCamera->lookAt(Vector3(-20,30,10)); SceneNode *anchor = mSceneMgr->getRootSceneNode()->createChildSceneNode("AnchorNode"); //SceneNode *grndan = anchor->createChildSceneNode("GroundAnchor"); SceneNode *grndan = mSceneMgr->getRootSceneNode(); if (mSelectEntities & ENT_GRID) { for (j = 0, z = -(mModelCount / 2 * mModelSpacing); j < mModelCount; j++, z += mModelSpacing) { for (i = 0, x = -(mModelCount / 2 * mModelSpacing); i < mModelCount; i++, x += mModelSpacing) { deaths = mSceneMgr->createEntity(cat(entName, i, j).c_str(),"robot.mesh"); if (mShadowsEnabled) deaths->setCastShadows(true); nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName, i, j).c_str(), Vector3(x, 0 , z)); nodes->attachObject(deaths); } } } if (mSelectEntities & ENT_RND) { entName = "randomdeath"; nodeName = "RandomDeathNode"; for (i = 0; i < mRandomCount; i++) { Vector3 pos( Math::RangeRandom(-planeHalf,-planeSixth), 0, Math::RangeRandom(-planeThreeEights, planeThreeEights)); deaths = mSceneMgr->createEntity(cat(entName,666,i),"robot.mesh"); if (mShadowsEnabled) deaths->setCastShadows(true); nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName,666,i), pos, Quaternion(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y)); nodes->attachObject(deaths); } } if (mSelectEntities & ENT_SPC) { entName = "randomspaceship"; nodeName = "RandomSpaceshipNode"; for (i = 0; i < mRandomCount; i++) { Vector3 pos( //Math::RangeRandom(-planeHalf,-planeSixth), Math::RangeRandom(planeSixth,planeHalf), Math::RangeRandom(planeHalf * 0.1, planeHalf), Math::RangeRandom(-planeThreeEights, planeThreeEights)); deaths = mSceneMgr->createEntity(cat(entName,666,i),"razor.mesh"); if (mShadowsEnabled) deaths->setCastShadows(true); nodes = /*mSceneMgr->getRootSceneNode()*/anchor->createChildSceneNode(cat(nodeName,666,i), pos, Quaternion(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y)); nodes->attachObject(deaths); } } if (mSelectEntities & ENT_MOV) { Entity *movingDeath = mSceneMgr->createEntity("movingDeath","robot.mesh"); if (mShadowsEnabled) movingDeath->setCastShadows( true ); SceneNode *deathPivotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("deathPivotNode"); mMoveNode = deathPivotNode->createChildSceneNode("movingNode", Vector3(0, 0, mRotationRadius)/*, Quaternion(Radian(Math::HALF_PI), Vector3::UNIT_Y)*/); mMoveNode->attachObject(movingDeath); Entity *ent_ball = mSceneMgr->createEntity("ball","sphere.mesh"); SceneNode *node_pivot = mMoveNode->createChildSceneNode("pivotNode"); SceneNode *node_ball = node_pivot->createChildSceneNode("orbitNode", Vector3(120, 40, 0)); node_ball->attachObject(ent_ball); node_ball->scale(0.1, 0.1, 0.1); //mFollowCam->setAutoTracking(true, mMoveNode); } if (mSelectEntities & ENT_PLN) { Plane ground(Vector3::UNIT_Y, 0); MeshManager::getSingleton().createPlane("ground", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, ground, mPlaneDim * 4 / 3, mPlaneDim, 20, 20, true, 1, 20, 20, Vector3::UNIT_Z); Entity *ent_ground = mSceneMgr->createEntity("GroundEntity", "ground"); ent_ground->setCastShadows(false); ent_ground->setMaterialName("Examples/RustySteel");//("Examples/Rockwall"); SceneNode *node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode", Vector3(0, 0, 0)); node_ground->attachObject(ent_ground); //MeshManager::getSingleton().createPlane("ground2", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, // ground, mPlaneDim/2, mPlaneDim, 10, 20, true, 1, 10, 20, Vector3::UNIT_Z); //ent_ground = mSceneMgr->createEntity("GroundEntity2", "ground2"); //ent_ground->setCastShadows(false); //ent_ground->setMaterialName("Examples/RustySteel"); //node_ground = /*mSceneMgr->getRootSceneNode()*/grndan->createChildSceneNode("GroundNode2", Vector3(-mPlaneDim/4, 0, 0)); //node_ground->attachObject(ent_ground); } // Lights mSceneMgr->setAmbientLight(ColourValue(0.1,0.1,0.1)); Light *light = mSceneMgr->createLight("light"); if (mShadowsEnabled) { mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE); light->setType(Light::LT_POINT); light->setPosition(Vector3(x, 300, z + 200)); } else { light->setType(Light::LT_DIRECTIONAL); light->setDirection(-1,-1,-1); } light->setDiffuseColour(ColourValue::White); light->setSpecularColour(ColourValue(1, 1, 0.2)); // Skybox mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", mPlaneDim * 2); } /* Some math tests Plane planeX(Vector3::UNIT_X, Vector3(10,10,10)); Plane planeY(Vector3::UNIT_Y, Vector3(10,10,10)); Plane planeZ(Vector3::UNIT_Z, Vector3(10,10,10)); Vector3 vect(20,20,20); Vector3 interX = planeX.projectVector(vect); Vector3 interY = planeY.projectVector(vect); Vector3 interZ = planeZ.projectVector(vect); std::stringstream ssX, ssY, ssZ; ssX << "The intersection of " << planeX << " and " << vect << " is at: " << interX; ssY << "The intersection of " << planeY << " and " << vect << " is at: " << interY; ssZ << "The intersection of " << planeZ << " and " << vect << " is at: " << interZ; LogManager::getSingleton().logMessage(ssX.str()); LogManager::getSingleton().logMessage(ssY.str()); LogManager::getSingleton().logMessage(ssZ.str()); */ } void KdTreeApp::createFrameListener(void) { mFrameListener = new KdTreeAppListener(mWindow, mSceneMgr, mOptions); //mFrameListener->showDebugOverlay( true ); mRoot->addFrameListener(mFrameListener); mRenderTargerListener = new KdTreeAppRenderTargetListener(mSceneMgr); mWindow->addListener(mRenderTargerListener); } void KdTreeApp::chooseSceneManager(void) { // Get the SceneManager mSceneMgr = mRoot->createSceneManager( KdTreeAppListener::SCENEMANAGERNAME[mOptions.mSceneManager], "MySceneManager"); // set params depending on scene manager if (mOptions.mSceneManager == KdTreeAppListener::SM_KDT) { mSceneMgr->setOption("BuildMethod", &mOptions.mBuildMethod); mSceneMgr->setOption("KdTreeMaxDepth", &mOptions.mMaxDepth); mSceneMgr->setOption("KT", &mOptions.mKT); mSceneMgr->setOption("KI", &mOptions.mKI); mSceneMgr->setOption("RenderMethod", &mOptions.mRenderMethod); mSceneMgr->setOption("EnhancedVisibility", &mOptions.mEnhancedVisibility); } // set algorithm when scene manager is OCM - numbering is different though if (mOptions.mSceneManager == KdTreeAppListener::SM_OCM) { int alg = CONV_KDT_TO_OCM_ALG(mOptions.mRenderMethod); mSceneMgr->setOption("Algorithm", &alg); } } void KdTreeApp::createCamera(void) { // Create the camera mCamera = mSceneMgr->createCamera("PlayerCam"); mCamera->setNearClipDistance(1); mCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("PlayerCamNode", Vector3(0,0,0)); mCamNode->attachObject(mCamera); // Position it at 500 in Z direction //mCamera->setPosition(Vector3(0,50,500)); //mCamera->setPosition(Vector3(500,256,666)); //mCamera->setPosition(Vector3(1280,600,1666)); // Look back along -Z //mCamera->lookAt(Vector3(0,50,-300)); //mCamera->lookAt(Vector3(-20,30,10)); //mFollowCam = mSceneMgr->createCamera("FollowCam"); //mFollowCam->setPosition(Vector3(800,150,800)); //mFollowCam->setNearClipDistance(5); //mFollowCam->setFOVy(Angle(15)); mTopCam = mSceneMgr->createCamera("TopCam"); mTopCam->setPosition(Vector3(0,mPlaneDim * 1.25,0)); mTopCam->setDirection(0,0,-1); mTopCam->pitch(Radian(-Math::HALF_PI)); mTopCam->setCullingFrustum(mCamera); mTopCam->setNearClipDistance(1); // infinite far plane? if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE)) { mTopCam->setFarClipDistance(0); mCamera->setFarClipDistance(0); } else { mTopCam->setFarClipDistance(20000); mCamera->setFarClipDistance(20000); } } void KdTreeApp::createViewports(void) { // Create one viewport, entire window Viewport* vp = mWindow->addViewport(mCamera); vp->setBackgroundColour(ColourValue(0,0,100)); // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio( Real(vp->getActualWidth()) / Real(vp->getActualHeight())); /* Viewport* fvp = mWindow->addViewport(mFollowCam,2,0.75,0.75,0.25,0.25); fvp->setBackgroundColour(ColourValue(100,0,0)); fvp->setOverlaysEnabled( false ); mFollowCam->setAspectRatio( Real(fvp->getActualWidth()) / Real(fvp->getActualHeight())); */ } bool KdTreeApp::configure(void) { // Show the configuration dialog and initialise the system // You can skip this and use root.restoreConfig() to load configuration // settings if you were sure there are valid ones saved in ogre.cfg #ifdef KDTREE_FASTSTART if(mRoot->restoreConfig()) #else if(mRoot->showConfigDialog()) #endif { // If returned true, user clicked OK so initialise // Here we choose to let the system create a default rendering window by passing 'true' mWindow = mRoot->initialise(true); return true; } else { return false; } } void KdTreeApp::createMaterials() { MaterialPtr mat; Technique * tech; Pass * pass; TextureUnitState * tex; // create play button mat = MaterialManager::getSingleton().create("KdTree/DemoPlayButton", "General"); mat->setLightingEnabled(false); tech = mat->getTechnique(0); tech->setSceneBlending(SBT_TRANSPARENT_ALPHA); tech->setDepthCheckEnabled(false); pass = tech->getPass(0); tex = pass->createTextureUnitState(); tex->setTextureName("DemoPlayButton.png"); // create record button mat = MaterialManager::getSingleton().create("KdTree/DemoRecordButton", "General"); mat->setLightingEnabled(false); tech = mat->getTechnique(0); tech->setSceneBlending(SBT_TRANSPARENT_ALPHA); tech->setDepthCheckEnabled(false); pass = tech->getPass(0); tex = pass->createTextureUnitState(); tex->setTextureName("DemoRecordButton.png"); } //----------------------------------------------------------------------- // splits strings containing multiple file names static int splitFilenames(const std::string str, std::vector &filenames) { int pos = 0; while(1) { int npos = (int)str.find(';', pos); if (npos < 0 || npos - pos < 1) break; filenames.push_back(std::string(str, pos, npos - pos)); pos = npos + 1; } filenames.push_back(std::string(str, pos, str.size() - pos)); return (int)filenames.size(); } bool KdTreeApp::loadScene(const String &filename) { // use leaf nodes of the original spatial hierarchy as occludees std::vector filenames; int files = splitFilenames(filename, filenames); std::stringstream d; d << "number of input files: " << files << "\n"; LogManager::getSingleton().logMessage(d.str()); bool result = false; std::vector::const_iterator fit, fit_end = filenames.end(); int i = 0; // root for different files for (fit = filenames.begin(); fit != fit_end; ++ fit, ++ i) { const std::string fn = *fit; if (strstr(fn.c_str(), ".iv") || strstr(fn.c_str(), ".wrl")) { // hack: set postion manually for vienna //mCamNode->setPosition(Vector3(830, 300, -540)); //mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329)); // load iv files loadSceneIV(fn, mSceneMgr->getRootSceneNode(), i); } result = true; } /* if (result) { int intersectables, faces; std::stringstream d; d << filename << " parsed successfully.\n" << "#NUM_OBJECTS (Total numner of objects)\n" << intersectables << "\n" << "#NUM_FACES (Total numner of faces)\n" << faces << "\n"; } */ return result; } //----------------------------------------------------------------------- bool KdTreeApp::loadSceneIV(const String &filename, SceneNode *root, const int index) { IVReader * mIVReader = new IVReader(); if (1) { String logFilename = "IVLog" + Ogre::StringConverter().toString(index) + ".log"; Log *log = LogManager::getSingleton().createLog(logFilename); mIVReader->setLog(log); } //viennaNode->translate(Vector3(-300, -300, 0)); if (mIVReader->loadFile(filename.c_str())) { SceneNode *node = root->createChildSceneNode("IVSceneNode" + index); mIVReader->buildTree(mSceneMgr, node); mIVReader->collapse(); OGRE_DELETE(mIVReader); return true; } return false; } /**********************************************************************/ /* VisualizationRenderTargetListener implementation */ /**********************************************************************/ //----------------------------------------------------------------------- KdTreeAppRenderTargetListener::KdTreeAppRenderTargetListener(SceneManager *sceneMgr) :RenderTargetListener(), mSceneMgr(sceneMgr) { } //----------------------------------------------------------------------- void KdTreeAppRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt) { // visualization viewport const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER; const bool nShowViz = !showViz; mSavedShadowTechnique = mSceneMgr->getShadowTechnique(); mSavedAmbientLight = mSceneMgr->getAmbientLight(); // -- ambient light must be full for visualization, shadows disabled if (showViz) { mSceneMgr->setAmbientLight(ColourValue(1, 1, 1)); mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); } mSceneMgr->setOption("PrepareVisualization", &showViz); SceneNode * skybox = mSceneMgr->getSkyBoxNode(); if (skybox != 0) mSceneMgr->setOption("SkyBoxEnabled", &nShowViz); //if ((SceneNode * skyplane = mSceneMgr->getSkyPlaneNode()) != 0) // mSceneMgr->setOption("SkyPlaneEnabled", &showViz); RenderTargetListener::preViewportUpdate(evt); } //----------------------------------------------------------------------- void KdTreeAppRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt) { // reset values mSceneMgr->setShadowTechnique(mSavedShadowTechnique); mSceneMgr->setAmbientLight(mSavedAmbientLight); RenderTargetListener::postRenderTargetUpdate(evt); }