示例#1
0
void App::UpdThr()
{
	Ogre::Timer gtim;
	//#ifdef _WIN32
	//DWORD af = 2;
	//gtim.setOption("QueryAffinityMask", &af);
	//#endif
	gtim.reset();

	while (!mShutDown)
	{
		///  step Game  **

		double dt = double(gtim.getMicroseconds()) * 0.000001;
		gtim.reset();
		
		if (pSet->multi_thr == 1 && !bLoading)
		{
			bSimulating = true;
			bool ret = pGame->OneLoop(dt);
			if (!ret)
				mShutDown = true;

			DoNetworking();
			bSimulating = false;
		}
		boost::this_thread::sleep(boost::posix_time::milliseconds(pSet->thread_sleep));
	}
}
示例#2
0
void Application::initializeCEGUI()
{
    Ogre::Timer timer;
    timer.reset();

    CEGUI::OgreRenderer::bootstrapSystem(*mOgreWindow);

    mUIRoot = static_cast<CEGUI::GUISheet*>(CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "Root"));
    mUIRoot->setPosition(CEGUI::UVector2(CEGUI::UDim(0, 0), CEGUI::UDim(0, 0)));
    mUIRoot->setSize(CEGUI::UVector2(CEGUI::UDim(1, 0), CEGUI::UDim(1, 0)));
    mUIRoot->setVisible(true);

    CEGUI::System::getSingleton().setGUISheet(mUIRoot);

    CEGUI::SchemeManager::getSingleton().create("OISBDemo.scheme");
	CEGUI::System::getSingleton().setDefaultMouseCursor("OgreTrayImages", "MouseArrow");
    CEGUI::MouseCursor::getSingleton().hide();

    //mUIRoot->addChildWindow(CEGUI::WindowManager::getSingleton().loadWindowLayout("Introduction.layout"));
    mUIRoot->addChildWindow(CEGUI::WindowManager::getSingleton().loadWindowLayout("HUD.layout"));
    mUIHUDThrottle = static_cast<CEGUI::ProgressBar*>(CEGUI::WindowManager::getSingleton().getWindow("HUD/Throttle"));
    mUIHUDVelocity = CEGUI::WindowManager::getSingleton().getWindow("HUD/Velocity");
    mUIHUDAltitude = CEGUI::WindowManager::getSingleton().getWindow("HUD/Altitude");

    std::stringstream sstr;
    sstr << timer.getMicroseconds();

    CEGUI::Logger::getSingleton().logEvent("Time to start CEGUI: " + sstr.str());
}
示例#3
0
void Application::go()
{
	Ogre::Timer loopTimer;

	bool continueRunning = true;
	while ( continueRunning )
	{
		Ogre::WindowEventUtilities::messagePump();
		
		SimpleInputManager::capture();

		// Update logic stuff
		float elapsedSeconds = loopTimer.getMicroseconds() * 1.0 / 1000000;
		updateLogic( elapsedSeconds );

		// Update graphics stuff
		updateAnimations( elapsedSeconds );
		
		bool windowClosed = m_window->isClosed();
		continueRunning &= ! windowClosed;

		updateStats();

		loopTimer.reset();
		bool renderFrameSuccess = m_root->renderOneFrame();
		continueRunning &= renderFrameSuccess;

		continueRunning &= ! m_exitRequested;		
	}
}
//  Run
//-------------------------------------------------------------------------------------
void BaseApp::Run( bool showDialog )
{
	mShowDialog = showDialog;
	if (!setup())
		return;

	if (!pSet->limit_fps)
		mRoot->startRendering();  // default
	else
	{	Ogre::Timer tim;
		while (1)
		{
			Ogre::WindowEventUtilities::messagePump();
			if (tim.getMicroseconds() > 1000000.0 / pSet->limit_fps_val)
			{
				tim.reset();
				if (!mRoot->renderOneFrame())
					break;
			}else
			if (pSet->limit_sleep >= 0)
				boost::this_thread::sleep(boost::posix_time::milliseconds(pSet->limit_sleep));
	}	}

	destroyScene();
}
示例#5
0
void Application::go()
{
	Ogre::Timer loopTimer;

	bool continueRunning = true;
	while ( continueRunning )
	{
		Ogre::WindowEventUtilities::messagePump();
		
		SimpleInputManager::capture();

		// Update logic stuff

		// Update graphics stuff
		
		bool windowClosed = m_window->isClosed();
		continueRunning &= ! windowClosed;

		loopTimer.reset();
		bool renderFrameSuccess = m_root->renderOneFrame();
		continueRunning &= renderFrameSuccess;

		continueRunning &= ! m_exitRequested;		
	}
}
示例#6
0
//---------------------------------------------------------------------------
void HeatVisionListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
    if(pass_id == 0xDEADBABE)
    {
        // "random_fractions" parameter
        fpParams->setNamedConstant("random_fractions", Ogre::Vector4(Ogre::Math::RangeRandom(0.0, 1.0), Ogre::Math::RangeRandom(0, 1.0), 0, 0));

        // "depth_modulator" parameter
        float inc = ((float)timer->getMilliseconds())/1000.0f;
        if ( (fabs(curr-end) <= 0.001) )
        {
            // take a new value to reach
            end = Ogre::Math::RangeRandom(0.95, 1.0);
            start = curr;
        }
        else
        {
            if (curr > end) curr -= inc;
            else curr += inc;
        }
        timer->reset();

        fpParams->setNamedConstant("depth_modulator", Ogre::Vector4(curr, 0, 0, 0));
    }
}
示例#7
0
	/**
	 * Releases the object's resources
	 */
	void MediaPlayerOCV::end()
	{
		// Check if already released
		if ( !isValid() )
			return;
		
        // Release thread
        if ( m_multithreaded && m_captureThread )
        {
            // Signal the thread and wait for it to be done
            m_captureThread->signal();
            Ogre::Timer timerLimit;
            timerLimit.reset();
            while( (m_captureThread->get_finished() == false) && (timerLimit.getMilliseconds() < 250) )
                ;
			if ( m_captureThread->get_finished() )
            {
                delete m_captureThread;
            }
            else
                LOG_CRITICAL( "MediaPlayerOCV: capture thread timer expired, and the thread did not finish. Something is wrong, there will be a memory leak" );
            m_captureThread = NULL;
        }
        
		// Clear resources
		m_capture.release();
        
        m_frameImg.end();
        
		// Clear flags
		m_bIsValid			= false;
		m_newBufferReady	= false;
		m_loopPending		= false;
	}
示例#8
0
void Application::update()
{
	Ogre::Timer loopTimer;

	bool continueRunning = true;
	
	while (continueRunning)
	{
		Ogre::WindowEventUtilities::messagePump();

		SimpleInputManager::capture();
		
		float elapsedSeconds = loopTimer.getMicroseconds() * 1.0 / 1000000;

		m_NXOgreTimeController->advance(elapsedSeconds);
	
		loopTimer.reset();

		updateOverlayInfo();

		bool renderFrameSuccess = m_root->renderOneFrame();
		
		if (!renderFrameSuccess || m_exitRequested)
		{
			continueRunning = false;
		}
	}
}
示例#9
0
void OMW::Engine::go()
{
    assert (!mContentFiles.empty());
    assert (!mOgre);

    Settings::Manager settings;
    std::string settingspath;

    settingspath = loadSettings (settings);

    // Create encoder
    ToUTF8::Utf8Encoder encoder (mEncoding);
    mEncoder = &encoder;

    prepareEngine (settings);

    // Play some good 'ol tunes
    MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));

    if (!mSaveGameFile.empty())
    {
        MWBase::Environment::get().getStateManager()->loadGame(mSaveGameFile);
    }
    else if (!mSkipMenu)
    {
        // start in main menu
        MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
        try
        {
            // Is there an ini setting for this filename or something?
            MWBase::Environment::get().getSoundManager()->streamMusic("Special/morrowind title.mp3");

            std::string logo = mFallbackMap["Movies_Morrowind_Logo"];
            if (!logo.empty())
                MWBase::Environment::get().getWindowManager()->playVideo(logo, true);
        }
        catch (...) {}
    }
    else
    {
        MWBase::Environment::get().getStateManager()->newGame (!mNewGame);
    }

    // Start the main rendering loop
    Ogre::Timer timer;
    while (!MWBase::Environment::get().getStateManager()->hasQuitRequest())
    {
        float dt = timer.getMilliseconds()/1000.f;
        dt = std::min(dt, 0.2f);

        timer.reset();
        Ogre::Root::getSingleton().renderOneFrame(dt);
    }
    // Save user settings
    settings.saveUser(settingspath);

    std::cout << "Quitting peacefully." << std::endl;
}
示例#10
0
//---------------------------------------------------------------------------
void HeatVisionListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
    if(pass_id == 0xDEADBABE)
    {
        timer->reset();
        fpParams =
            mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
    }
}
示例#11
0
void Application::run()
{
    initialize();
    setupScene();

    Ogre::Timer timer;
    timer.reset();

    mRunning = true;
    while (mRunning)
    {
        const Ogre::Real delta=
            timer.getMicroseconds() * static_cast<Ogre::Real>(0.000001f);
        timer.reset();

        runOneFrame(delta);
    }

    finalize();
}
示例#12
0
	::FreeConsole();
}

void Game::Run()
{
	InitializeGame();
	ConnectToPVD();
	InitializeKinect();

	kinectController = BodyController();

	InputManager* inputManager = InputManager::GetInstance();

	inputManager->RegisterSensorListener(&kinectController);

	inputManager->BeginAllCapture();

	sceneManager = new SceneManager();
	sceneManager->Initialize(mWindow, mRoot);

	AllocConsole();
	freopen("conin$","r",stdin);
	freopen("conout$","w",stdout);
	freopen("conout$","w",stderr);
	printf("Debugging Window:\n");

	/*std::shared_ptr<GameScene> gameScene(new GameScene(sceneManager, mRoot, "Probending Arena", contestantData));
	sceneManager->FlagSceneSwitch(gameScene, true);
	gameScene.reset();*/

	std::shared_ptr<MenusScene> menuScene = std::make_shared<MenusScene>(sceneManager, mRoot, MenusScene::Screens::MainMenu);
	sceneManager->FlagSceneSwitch(menuScene, true);
	menuScene.reset();

	bool rendering = true;

	Ogre::Timer gameTimer = Ogre::Timer();
	float currentTime = 0;
	float previousTime = 0;

	while (rendering)
	{
		gameTimer.reset();
		
		if(!Update(currentTime / 1000.0f))
			rendering = false;

		//Ogre::WindowEventUtilities::messagePump();
#if(!MEMORY_LEAK_DETECT)
		mRoot->renderOneFrame();
#endif
		currentTime = (float)gameTimer.getMilliseconds();
		
示例#13
0
 bool mouseReleased(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
 {
  if (evt.state.buttonDown(OIS::MB_Left) == false)
   SdkSample::mouseReleased(evt, id);
  
  Ogre::Ray ray = mTrayMgr->getCursorRay(mCamera);

  beastie::ray_query result;
  
  Ogre::Timer timer;
  unsigned long rayTime = 0;
  
  timer.reset();
  bool ret = mTree->intersect(ray, 10000, result);
  rayTime = timer.getMicroseconds();
  
  mResultObject->beginUpdate(0);
  
  if (ret)
  {
   // Hit something.

   mResultObject->position(result.hitTriangle.a + (result.hitTriangle.n * 3.f));
   mResultObject->position(result.hitTriangle.b + (result.hitTriangle.n * 3.f));
   mResultObject->position(result.hitTriangle.c + (result.hitTriangle.n * 3.f));
   
   mHitPosLabelX->setCaption(Ogre::StringConverter::toString(result.globalPosition.x));
   mHitPosLabelY->setCaption(Ogre::StringConverter::toString(result.globalPosition.y));
   mHitPosLabelZ->setCaption(Ogre::StringConverter::toString(result.globalPosition.z));

  }
  else
  {
   // Didn't hit anything.
   
   // Try raycasting the ground plane.
   Ogre::Vector3 globalPosition;
  
   if (beastie::intersections::line( beastie::line(ray, 100000) , mPlane, globalPosition ))
   {
    mHitPosLabelX->setCaption(Ogre::StringConverter::toString(globalPosition.x));
    mHitPosLabelY->setCaption(Ogre::StringConverter::toString(globalPosition.y));
    mHitPosLabelZ->setCaption(Ogre::StringConverter::toString(globalPosition.z));

    float const radius = 50;
 
    // accuracy is the count of points (and lines).
    // Higher values make the circle smoother, but may slowdown the performance.
    // The performance also is related to the count of circles.
    float const accuracy = 15;
 
    for(float theta = 0; theta <= 2 * Math::PI; theta += Ogre::Math::PI / accuracy) {
      mResultObject->position(globalPosition.x + (radius * cos(theta)), 0, globalPosition.z + (radius * sin(theta)));
      mResultObject->position(globalPosition);
    }


   }
   else
   {
    
    // Really didn't click on anything at all.
    
    mHitPosLabelX->setCaption("-");
    mHitPosLabelY->setCaption("-");
    mHitPosLabelZ->setCaption("-");
    mResultObject->position(0,0,0);
    mResultObject->position(0,0,0);
    mResultObject->position(0,0,0);
    
   }
   
   
  }
  
  mResultObject->end();

  return true;
 }
示例#14
0
bool NavMesher::Build()
{
  // ******* Only for OBJ Loading ****
 cleanup();
 const char * filepath = "../../media/models/";
 if (!m_geom || !m_geom->loadMesh(filepath))
 {
  delete m_geom;
  m_geom = 0;
  
  m_ctx->log(RC_LOG_ERROR, "Geom load log %s:");
 }
 assert(m_geom);
 if (!m_geom || !m_geom->getMesh())
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
  return false;
 }
 if(m_geom->getMesh()->getTriCount() <= 0 || m_geom->getMesh()->getVertCount()<=0)
  Ogre::Exception(0,Ogre::String("Bad verts or Triangle count. Verts: "+
  StringConverter::toString( m_geom->getMesh()->getVertCount()) + "/n"
  + "Triangles :" +StringConverter::toString(m_geom->getMesh()->getTriCount())),"NavMesher::Build");
 
 //reset timer
 Ogre::Timer tm;
 tm.reset();
 unsigned long stime = tm.getMicroseconds();
 //clear existing
 Clear();
  // ******* Only for OBJ Loading ****
 const float* bmin = m_geom->getMeshBoundsMin();
 const float* bmax = m_geom->getMeshBoundsMax();
 const float* verts = m_geom->getMesh()->getVerts();
 const int nverts = m_geom->getMesh()->getVertCount();
 const int *tris = m_geom->getMesh()->getTris();
 const int ntris = m_geom->getMesh()->getTriCount();

 if(sizeof(tris) <= 0 || ntris <= 0) {
  return false;
 }
 //
 // Step 1. Initialize build config.
 //
 
 // Init build configuration from GUI
 memset(&m_cfg, 0, sizeof(m_cfg));
 m_cfg.cs = m_cellSize;
 m_cfg.ch = m_cellHeight;
 m_cfg.walkableSlopeAngle = m_agentMaxSlope;
 m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
 m_cfg.walkableClimb = (int)floorf(m_agentMaxClimb / m_cfg.ch);
 m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
 m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
 m_cfg.maxSimplificationError = m_edgeMaxError;
 m_cfg.minRegionArea = (int)rcSqr(m_regionMinSize);  // Note: area = size*size
 m_cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize); // Note: area = size*size
 m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
 m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
 m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
 
 // Set the area where the navigation will be build.
 // Here the bounds of the input mesh are used, but the
 // area could be specified by an user defined box, etc.
 rcVcopy(m_cfg.bmin, bmin);
 rcVcopy(m_cfg.bmax, bmax);
 rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
 // Reset build times gathering.
 m_ctx->resetTimers();
 // Start the build process. 
 m_ctx->startTimer(RC_TIMER_TOTAL);
 
 m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
 m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
 m_ctx->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
 
 //
 // Step 2. Rasterize input polygon soup.
 //
 
 // Allocate voxel heightfield where we rasterize our input data to.
 m_solid = rcAllocHeightfield();
 if (!m_solid)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
  return false;
 }
 if (!rcCreateHeightfield(m_ctx, *m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
  return false;
 }
 
 // Allocate array that can hold triangle area types.
 // If you have multiple meshes you need to process, allocate
 // and array which can hold the max number of triangles you need to process.
 m_triareas = new unsigned char[ntris];
 if (!m_triareas)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'm_triareas' (%d).", ntris);
  return false;
 }
 
 // Find triangles which are walkable based on their slope and rasterize them.
 // If your input data is multiple meshes, you can transform them here, calculate
 // the are type for each of the meshes and rasterize them.
 memset(m_triareas, 0, ntris*sizeof(unsigned char));
 rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas);
 rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb);
 if (!m_keepInterResults)
 {
  delete [] m_triareas;
  m_triareas = 0;
 }
 
 //
 // Step 3. Filter walkables surfaces.
 //
 
 // Once all geoemtry is rasterized, we do initial pass of filtering to
 // remove unwanted overhangs caused by the conservative rasterization
 // as well as filter spans where the character cannot possibly stand.
 rcFilterLowHangingWalkableObstacles(m_ctx, m_cfg.walkableClimb, *m_solid);
 rcFilterLedgeSpans(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
 rcFilterWalkableLowHeightSpans(m_ctx, m_cfg.walkableHeight, *m_solid);

 //
 // Step 4. Partition walkable surface to simple regions.
 //
 // Compact the heightfield so that it is faster to handle from now on.
 // This will result more cache coherent data as well as the neighbours
 // between walkable cells will be calculated.
 m_chf = rcAllocCompactHeightfield();
 if (!m_chf)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
  return false;
 }
 if (!rcBuildCompactHeightfield(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid, *m_chf))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
  return false;
 }
 
 if (!m_keepInterResults)
 {
  rcFreeHeightField(m_solid);
  m_solid = 0;
 }
  
 // Erode the walkable area by agent radius.
 if (!rcErodeWalkableArea(m_ctx, m_cfg.walkableRadius, *m_chf))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not erode.");
  return false;
 }
 // (Optional) Mark areas.
 const ConvexVolume* vols = m_geom->getConvexVolumes();
 for (int i  = 0; i < m_geom->getConvexVolumeCount(); ++i)
  rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
 
 if (m_monotonePartitioning)
 {
  // Partition the walkable surface into simple regions without holes.
  // Monotone partitioning does not need distancefield.
  if (!rcBuildRegionsMonotone(m_ctx, *m_chf, 0, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
  {
   m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
   return false;
  }
 }
 else
 {
  // Prepare for region partitioning, by calculating distance field along the walkable surface.
  if (!rcBuildDistanceField(m_ctx, *m_chf))
  {
   m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
   return false;
  }
  // Partition the walkable surface into simple regions without holes.
  if (!rcBuildRegions(m_ctx, *m_chf, 0, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
  {
   m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
   return false;
  }
 }
 //
 // Step 5. Trace and simplify region contours.
 //
 
 // Create contours.
 m_cset = rcAllocContourSet();
 if (!m_cset)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
  return false;
 }
 if (!rcBuildContours(m_ctx, *m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
  return false;
 }
 
 //
 // Step 6. Build polygons mesh from contours.
 //
 
 // Build polygon navmesh from the contours.
 m_pmesh = rcAllocPolyMesh();
 if (!m_pmesh)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmesh'.");
  return false;
 }
 if (!rcBuildPolyMesh(m_ctx, *m_cset, m_cfg.maxVertsPerPoly, *m_pmesh))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
  return false;
 }
 
 //
 // Step 7. Create detail mesh which allows to access approximate height on each polygon.
 //
 
 m_dmesh = rcAllocPolyMeshDetail();
 if (!m_dmesh)
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmdtl'.");
  return false;
 }
 if (!rcBuildPolyMeshDetail(m_ctx, *m_pmesh, *m_chf, m_cfg.detailSampleDist, m_cfg.detailSampleMaxError, *m_dmesh))
 {
  m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build detail mesh.");
  return false;
 }
 if (!m_keepInterResults)
 {
  rcFreeCompactHeightfield(m_chf);
  m_chf = 0;
  rcFreeContourSet(m_cset);
  m_cset = 0;
 }

 // At this point the navigation mesh data is ready, you can access it from m_pmesh.
 // See rcDebugDrawPolyMesh or dtCreateNavMeshData as examples how to access the data.
 
 //
 // (Optional) Step 8. Create Detour data from Recast poly mesh.
 //
 
 // The GUI may allow more max points per polygon than Detour can handle.
 // Only build the detour navmesh if we do not exceed the limit.
 unsigned char* navData = 0;
 int navDataSize = 0;
 // Update poly flags from areas.

 for (int i = 0; i < m_pmesh->npolys; ++i)
 {
  if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
   m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
   
  if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
   m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
   m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
  {
   m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
  }
  else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
  {
   m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
  }
  else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
  {
   m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
  }
 }

 memset(&m_params, 0, sizeof(m_params));
 m_params.verts = m_pmesh->verts;
 m_params.vertCount = m_pmesh->nverts;
 m_params.polys = m_pmesh->polys;
 m_params.polyAreas = m_pmesh->areas;
 m_params.polyFlags = m_pmesh->flags;
 m_params.polyCount = m_pmesh->npolys;
 m_params.nvp = m_pmesh->nvp;
 m_params.detailMeshes = m_dmesh->meshes;
 m_params.detailVerts = m_dmesh->verts;
 m_params.detailVertsCount = m_dmesh->nverts;
 m_params.detailTris = m_dmesh->tris;
 m_params.detailTriCount = m_dmesh->ntris;
 m_params.walkableHeight = m_agentHeight;
 m_params.walkableRadius = m_agentRadius;
 m_params.walkableClimb = m_agentMaxClimb;
 rcVcopy(m_params.bmin, m_pmesh->bmin);
 rcVcopy(m_params.bmax, m_pmesh->bmax);
 m_params.cs = m_cfg.cs;
 m_params.ch = m_cfg.ch;
 m_params.buildBvTree = true;
 if (!dtCreateNavMeshData(&m_params, &navData, &navDataSize)) {
   m_ctx->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
  return false;
 }
 
 m_navMesh = dtAllocNavMesh();
 if (!m_navMesh) {
  delete [] navData;
   m_ctx->log(RC_LOG_ERROR, "Could not create Detour navmesh");
  return false;
 }
 m_navQuery = dtAllocNavMeshQuery(); 
 dtStatus status = m_navQuery->init(m_navMesh, 2048);
   if (dtStatusFailed(status)) {
           m_ctx->log(RC_LOG_ERROR, "Could not init Detour navmesh query");
           return false;
   }
 if (!m_navMesh->init(navData, navDataSize, true)) {
  delete [] navData;
   m_ctx->log(RC_LOG_ERROR, "Could not init Detour navmesh");
  return false;
 }
 //take time
 stime = tm.getMicroseconds() - stime;
 DrawDebug();
 return true;
}
///  Image from road
///  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
void App::SaveGrassDens()
{
	Ogre::Timer ti;

	for (int i=0; i < RTs-1; ++i)  //-1 preview camera manual
	{
		if (!rt[i].tex)  return;
		rt[i].tex->update();  // all have to exist
	}

	int w = rt[1].tex->getWidth(), h = rt[1].tex->getHeight();
	using Ogre::uint;
	uint *rd = new uint[w*h];   // road render
	uint *gd = new uint[w*h];   // grass dens
	PixelBox pb_rd(w,h,1, PF_BYTE_RGBA, rd);
	rt[1].tex->copyContentsToMemory(pb_rd, RenderTarget::FB_FRONT);

	const int f = std::max(0, scn->sc->grDensSmooth);
	float sum = 0.f;
	register int v,i,j,x,y, a,b,d,m;

	//  gauss kernel for smoothing
	int *mask = new int[(f*2+1)*(f*2+1)];  m = 0;
	if (f==0)
	{	mask[0] = 256.f;  sum = 256.f;  }
	else
	for (j = -f; j <= f; ++j)
	for (i = -f; i <= f; ++i, ++m)
	{
		v = std::max(0.f, (1.f - sqrtf((float)(i*i+j*j)) / float(f)) * 256.f);
		mask[m] = v;  sum += v;
	}
	sum = 2.f / sum;  //par normally would be 1.f - but road needs to stay black and be smooth outside
	//  change smooth to distance from road with fade ?..
		
	///  road - rotate, smooth  -----------
	for (y = f; y < h-f; ++y) {  a = y*w +f;
	for (x = f; x < w-f; ++x, ++a)
	{	b = x*w + (h-y);  // rot 90 ccw  b=a
		
		//  sum kernel
		v = 0;  m = 0;
		for (j = -f; j <= f; ++j) {  d = b -f + j*w;
		for (i = -f; i <= f; ++i, ++d, ++m)
			v += ((rd[d] >> 16) & 0xFF) * mask[m] / 256;  }

		v = std::max(0, (int)(255.f * (1.f - v * sum) ));  // avg, inv, clamp
		
		gd[a] = 0xFF000000 + v;  // write
	}	}

	v = 0xFF0000FF;  //  frame f []  todo: get from rd[b] not clear..
	for (y = 0;  y <= f; ++y)	for (x=0; x < w; ++x)	gd[y*w+x] = v;  // - up
	for (y=h-f-1; y < h; ++y)	for (x=0; x < w; ++x)	gd[y*w+x] = v;  // - down
	for (x = 0;  x <= f; ++x)	for (y=0; y < h; ++y)	gd[y*w+x] = v;  // | left
	for (x=w-f-1; x < w; ++x)	for (y=0; y < h; ++y)	gd[y*w+x] = v;  // | right

	LogO(String("::: Time road dens: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");  ti.reset();

	if (!IsVdrTrack())  // vdr trk no grass, only previews
	{
		Image im;  // for trees, before grass angle and height
		im.loadDynamicImage((uchar*)gd, w,h,1, PF_BYTE_RGBA);
		im.save(gcom->TrkDir()+"objects/roadDensity.png");
	}
	delete[] rd;  delete[] gd;  delete[] mask;

	//  road, terrain  ----------------
	int u = pSet->allow_save ? pSet->gui.track_user : 1;
	rt[0].tex->writeContentsToFile(gcom->pathTrk[u] + pSet->gui.track + "/preview/road.png");
	rt[2].tex->writeContentsToFile(gcom->pathTrk[u] + pSet->gui.track + "/preview/terrain.jpg");

	LogO(String("::: Time save prv : ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}