void Level00::InitializeLevel()
{
	LevelReader levelReader("Assets/UnitySceneExport.json");
	levelReader.ReadLevel();

	// Walls
	mWallCount = levelReader.mWalls.Position.size();
	LoadStaticSceneObjects(&mWalls, &mWallTransforms, &mWallColliders, &levelReader.mWalls.Position[0], &levelReader.mWalls.Rotation[0], &levelReader.mWalls.Scale[0], mWallCount);

	// Blocks
	mBlockCount = levelReader.mBlocks.Position.size();
	LoadTransforms(&mBlockTransforms, &levelReader.mBlocks.Position[0], &levelReader.mBlocks.Rotation[0], &levelReader.mBlocks.Scale[0], mBlockCount, 0);


	// Note: We are allocating aabbs twice!!! Maybe we should allocate our data structures before filling them out with level data?
	mAABBCount = mWallCount + mBlockCount;
	mAABBs = reinterpret_cast<QuadColliderComponent*>(mSceneAllocator.Allocate(sizeof(QuadColliderComponent) * (mAABBCount), alignof(QuadColliderComponent), 0));
	SetAABBs(levelReader.mWalls, mAABBs, 0);
	SetAABBs(levelReader.mBlocks, mAABBs, mWallCount);

	// Lights
	mCircleCount = levelReader.mLights.size();
	LoadLights(&mLights, &mCircleTransforms, &mLightColliders, &levelReader.mLights[0], mCircleCount);
	//	LoadTransforms(&mCircleTransforms, &levelReader.mLights[0], nullptr, nullptr, mCircleCount, 1);
	mLightPos = levelReader.mLights;

	mCircleColorWeights = (float*)mSceneAllocator.Allocate(sizeof(float)*mCircleCount, alignof(float), 0);
	//for now, only the 5 first lights are "lit"
	for (int i = 0; i < mCircleCount; i++)
	{
		if (i < 5)
			mCircleColorWeights[i] = 1.0f;
		else
			mCircleColorWeights[i] = 0.0f;
	}

	// Robots
	mRobots = levelReader.mRobots;
	mRobotCount = mRobots.size();
	mRobotTransforms = reinterpret_cast<mat4f*>(mSceneAllocator.Allocate(sizeof(mat4f) * mRobotCount, alignof(mat4f), 0));

	// SpawnPoint
	mSpawnPoint.mTransform = &mSpawnPointTransform;
	mSpawnPoint.mTransform->SetPosition(levelReader.mPlayerPos + vec3f(45, -20, 0));
	
	// Create explorers
	mExplorer[0] = Factory<Explorer>::Create();
	mExplorer[1] = Factory<Explorer>::Create();
	mExplorer[2] = Factory<Explorer>::Create();
	mExplorer[3] = Factory<Explorer>::Create();
	mExplorersCount = 0;

	// Goal
	mGoal.mTransform = &mGoalTransform;
	mGoal.mTransform->SetPosition(levelReader.mGoalPos);
	mGoal.mTransform->RotateYaw(PI);
}
Exemple #2
0
void CShootingObject::Load	(LPCSTR section)
{
	if(pSettings->line_exist(section,"light_disabled"))
	{
		m_bLightShotEnabled		= !pSettings->r_bool(section,"light_disabled");
	}else
		m_bLightShotEnabled		= true;

	//время затрачиваемое на выстрел
	fOneShotTime			= pSettings->r_float		(section,"rpm");
	VERIFY(fOneShotTime>0.f);
	fOneShotTime			= 60.f / fOneShotTime;

	LoadFireParams		(section);
	LoadLights			(section, "");
	LoadShellParticles	(section, "");
	LoadFlameParticles	(section, "");
}
Exemple #3
0
bool World::Load()
{
	conf.ParseConfigFile("Data/ConfigFile.txt"); // load configuration file
	
	// Order of loading: Lights -> Textures -> Shaders -> Geometry -> Particles -> Seasons

	LoadLights();
	LoadTextures();
	LoadSounds();
	LoadShaders();
	LoadGeometry();
	LoadParticles();
	
	SetupSeasons();
	
	//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Color::BLACK.GetVec());
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Color::WHITE.GetVec());

	SetLightingMode(Spotlights);

	return true;
};
Exemple #4
0
void CRender::level_Load(IReader* fs)
{
	R_ASSERT						(0!=g_pGameLevel);
	R_ASSERT						(!b_loaded);

	// Begin
	pApp->LoadBegin					();
	dxRenderDeviceRender::Instance().Resources->DeferredLoad	(TRUE);
	IReader*						chunk;

	// Shaders
//	g_pGamePersistent->LoadTitle		("st_loading_shaders");
	g_pGamePersistent->LoadTitle		();
	{
		chunk = fs->open_chunk		(fsL_SHADERS);
		R_ASSERT2					(chunk,"Level doesn't builded correctly.");
		u32 count = chunk->r_u32	();
		Shaders.resize				(count);
		for(u32 i=0; i<count; i++)	// skip first shader as "reserved" one
		{
			string512				n_sh,n_tlist;
			LPCSTR			n		= LPCSTR(chunk->pointer());
			chunk->skip_stringZ		();
			if (0==n[0])			continue;
			xr_strcpy					(n_sh,n);
			LPSTR			delim	= strchr(n_sh,'/');
			*delim					= 0;
			xr_strcpy					(n_tlist,delim+1);
			Shaders[i]				= dxRenderDeviceRender::Instance().Resources->Create(n_sh,n_tlist);
		}
		chunk->close();
	}

	// Components
	Wallmarks					= xr_new<CWallmarksEngine>	();
	Details						= xr_new<CDetailManager>	();

	if	(!g_dedicated_server)	{
		// VB,IB,SWI
//		g_pGamePersistent->LoadTitle("st_loading_geometry");
		g_pGamePersistent->LoadTitle();
		{
			CStreamReader			*geom = FS.rs_open("$level$","level.geom");
			R_ASSERT2				(geom, "level.geom");
			LoadBuffers				(geom,FALSE);
			LoadSWIs				(geom);
			FS.r_close				(geom);
		}

		//...and alternate/fast geometry
		{
			CStreamReader			*geom = FS.rs_open("$level$","level.geomx");
			R_ASSERT2				(geom, "level.geomX");
			LoadBuffers				(geom,TRUE);
			FS.r_close				(geom);
		}

		// Visuals
//		g_pGamePersistent->LoadTitle("st_loading_spatial_db");
		g_pGamePersistent->LoadTitle();
		chunk						= fs->open_chunk(fsL_VISUALS);
		LoadVisuals					(chunk);
		chunk->close				();

		// Details
//		g_pGamePersistent->LoadTitle("st_loading_details");
		g_pGamePersistent->LoadTitle();
		Details->Load				();
	}

	// Sectors
//	g_pGamePersistent->LoadTitle("st_loading_sectors_portals");
	g_pGamePersistent->LoadTitle();
	LoadSectors					(fs);

	// 3D Fluid
	Load3DFluid					();

	// HOM
	HOM.Load					();

	// Lights
	// pApp->LoadTitle			("Loading lights...");
	LoadLights					(fs);

	// End
	pApp->LoadEnd				();

	// sanity-clear
	lstLODs.clear				();
	lstLODgroups.clear			();
	mapLOD.clear				();

	// signal loaded
	b_loaded					= TRUE	;
}
Exemple #5
0
void CWeaponMagazined::InitAddons()
{
	//////////////////////////////////////////////////////////////////////////
	// Прицел
	m_fIronSightZoomFactor = READ_IF_EXISTS(pSettings, r_float, cNameSect(), "ironsight_zoom_factor", 50.0f);

	if (IsScopeAttached())
	{
		if (m_eScopeStatus == ALife::eAddonAttachable)
		{
			m_sScopeName = pSettings->r_string(cNameSect(), "scope_name");
			m_iScopeX = pSettings->r_s32(cNameSect(), "scope_x");
			m_iScopeY = pSettings->r_s32(cNameSect(), "scope_y");

			shared_str scope_tex_name;
			scope_tex_name = pSettings->r_string(*m_sScopeName, "scope_texture");
			m_fScopeZoomFactor = pSettings->r_float(*m_sScopeName, "scope_zoom_factor");

			if (m_UIScope) xr_delete(m_UIScope);
			m_UIScope = xr_new<CUIStaticItem>();

			//			m_UIScope->Init(*scope_tex_name, "hud\\default", 0, 0, alNone);
			m_UIScope->Init(*scope_tex_name, "hud\\scopes", 0, 0, alNone);	// KD: special shader that account screen resolution
		}
		else if (m_eScopeStatus == ALife::eAddonPermanent)
		{
			m_fScopeZoomFactor = pSettings->r_float(cNameSect(), "scope_zoom_factor");
			shared_str scope_tex_name;
			scope_tex_name = pSettings->r_string(cNameSect(), "scope_texture");

			if (m_UIScope) xr_delete(m_UIScope);
			m_UIScope = xr_new<CUIStaticItem>();
			//			m_UIScope->Init(*scope_tex_name, "hud\\default", 0, 0, alNone);
			m_UIScope->Init(*scope_tex_name, "hud\\scopes", 0, 0, alNone);	// KD: special shader that account screen resolution
		}
	}
	else
	{
		if (m_UIScope) xr_delete(m_UIScope);

		if (IsZoomEnabled())
			m_fIronSightZoomFactor = pSettings->r_float(cNameSect(), "scope_zoom_factor");
	}

	if (IsSilencerAttached() && SilencerAttachable())
	{
		m_sFlameParticlesCurrent = m_sSilencerFlameParticles;
		m_sSmokeParticlesCurrent = m_sSilencerSmokeParticles;
		m_pSndShotCurrent = &sndSilencerShot;

		//сила выстрела
		LoadFireParams(*cNameSect(), "");

		//подсветка от выстрела
		LoadLights(*cNameSect(), "silencer_");
		ApplySilencerKoeffs();
	}
	else
	{
		m_sFlameParticlesCurrent = m_sFlameParticles;
		m_sSmokeParticlesCurrent = m_sSmokeParticles;
		m_pSndShotCurrent = &sndShot;

		//сила выстрела
		LoadFireParams(*cNameSect(), "");
		//подсветка от выстрела
		LoadLights(*cNameSect(), "");
	}

	inherited::InitAddons();
}
void GLUTRedraw(void)
{
  // Initialize OpenGL drawing modes
  glEnable(GL_LIGHTING);
  glDisable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ZERO);
  glDepthMask(true);

  // Clear window 
  R3Rgb background = scene->background;
  glClearColor(background[0], background[1], background[2], background[3]);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Load camera
  LoadCamera(&camera);

  // Load scene lights
  LoadLights(scene);

  // Draw scene camera
  DrawCamera(scene);

  // Draw scene lights
  DrawLights(scene);

  // Draw particles
  DrawParticles(scene);

  // Draw particle sources 
  DrawParticleSources(scene);

  // Draw particle sinks 
  DrawParticleSinks(scene);

  // Draw particle springs
  DrawParticleSprings(scene);

  // Draw scene surfaces
  if (show_faces) {
    glEnable(GL_LIGHTING);
    DrawScene(scene);
  }

  // Draw scene edges
  if (show_edges) {
    glDisable(GL_LIGHTING);
    glColor3d(1 - background[0], 1 - background[1], 1 - background[2]);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    DrawScene(scene);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  }

  // Save image
  if (save_image) {
    char image_name[256];
    static int image_number = 1;
    for (;;) {
      sprintf(image_name, "image%d.jpg", image_number++);
      FILE *fp = fopen(image_name, "r");
      if (!fp) break; 
      else fclose(fp);
    }
    GLUTSaveImage(image_name);
    printf("Saved %s\n", image_name);
    save_image = 0;
  }

  // Save video
  if (save_video) {
    char frame_name[512];
    static int next_frame = 0;
    static int num_frames_recorded = 0;
    for (;;) {
      sprintf(frame_name, "%sframe%04d.jpg", video_prefix, next_frame++);
      FILE *fp = fopen(frame_name, "r");
      if (!fp) break; 
      else fclose(fp);
    }
    GLUTSaveImage(frame_name);
    if (next_frame % 100 == 1) {
      printf("Saved %s\n", frame_name);
    }
    if (num_frames_to_record == ++num_frames_recorded) {
      save_video = 0;
      printf("Recorded %d frames, stopping as instructed.\n", num_frames_recorded);
      quit = 1;
    }
  }

  // Quit here so that can save image before exit
  if (quit) {
    if (output_image_name) GLUTSaveImage(output_image_name);
    GLUTStop();
  }

  // Swap buffers 
  glutSwapBuffers();
}    
void LevelFactory::ReadXML(const std::string& aFilePath)
{
	Prism::Engine::GetInstance()->GetModelLoader()->Pause();

	Prism::Engine::GetInstance()->myIsLoading = true;


	FindTextures("Data/Resource/Texture/Particle/");

	myCurrentLevel->myScene = new Prism::Scene();
	myCurrentLevel->myWeaponFactory = new WeaponFactory();
	myCurrentLevel->myWeaponFactory->LoadWeapons("Data/Script/LI_list_weapon.xml");
	myCurrentLevel->myWeaponFactory->LoadProjectiles("Data/Script/LI_list_projectile.xml");
	myCurrentLevel->myEntityFactory = new EntityFactory(myCurrentLevel->myWeaponFactory);
	myCurrentLevel->myEntityFactory->LoadEntites("Data/Script/LI_list_entity.xml", myDifficults[myCurrentDifficultyID].myMultiplier);
	myCurrentLevel->myCollisionManager = new CollisionManager();
	myCurrentLevel->myBulletManager = new BulletManager(*myCurrentLevel->myCollisionManager, *myCurrentLevel->myScene);
	myCurrentLevel->myBulletManager->LoadFromFactory(myCurrentLevel->myWeaponFactory, myCurrentLevel->myEntityFactory, "Data/Script/LI_list_projectile.xml");

	myDirectionalLights.DeleteAll();
	myPointLights.DeleteAll();
	mySpotLights.DeleteAll();


	LoadPlayer();

	myCurrentLevel->myEmitterManager = new EmitterManager(myCurrentLevel->myPlayer);
	

	ReadLevelSettings();
	myCurrentLevel->myEntities.Add(myCurrentLevel->myPlayer);
	myCurrentLevel->myCamera = new Prism::Camera(myCurrentLevel->myPlayer->myOrientation);
	myCurrentLevel->myPlayer->GetComponent<GUIComponent>()->SetCamera(myCurrentLevel->myCamera);
	myCurrentLevel->GetEmitterManager()->AddEmitter(myCurrentLevel->myPlayer->GetComponent<ParticleEmitterComponent>());
	myCurrentLevel->myPlayer->SetPlayerScene(*myCurrentLevel->myScene);

	Sleep(10);
	XMLReader reader;
	reader.OpenDocument(aFilePath);
	tinyxml2::XMLElement* levelElement = reader.ForceFindFirstChild("root");
	levelElement = reader.ForceFindFirstChild(levelElement, "scene");
	std::string skySphere;
	std::string cubeMap;
	std::string missionXML;
	std::string eventXML;
	std::string conversationXML;

	reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "missionxml"), "source", missionXML);
	reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "eventxml"), "source", eventXML);
	reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "conversationxml"), "source", conversationXML);

	CU::Vector3<float> playerPos;
	CU::Vector3<float> playerRot;
	tinyxml2::XMLElement* playerPosElement;
	playerPosElement = reader.ForceFindFirstChild(levelElement, "PlayerStartTranslate");
	playerPosElement = reader.ForceFindFirstChild(playerPosElement, "position");
	reader.ForceReadAttribute(playerPosElement, "X", playerPos.x);
	reader.ForceReadAttribute(playerPosElement, "Y", playerPos.y);
	reader.ForceReadAttribute(playerPosElement, "Z", playerPos.z);
	
	playerPosElement = reader.ForceFindFirstChild(levelElement, "PlayerStartTranslate");
	playerPosElement = reader.ForceFindFirstChild(playerPosElement, "rotation");
	reader.ForceReadAttribute(playerPosElement, "X", playerRot.x);
	reader.ForceReadAttribute(playerPosElement, "Y", playerRot.y);
	reader.ForceReadAttribute(playerPosElement, "Z", playerRot.z);

	myCurrentLevel->myPlayer->myOrientation = CU::Matrix44f();

	myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundX(playerRot.x) 
		* myCurrentLevel->myPlayer->myOrientation;
	myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundY(playerRot.y) 
		* myCurrentLevel->myPlayer->myOrientation;
	myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundZ(playerRot.z) 
		* myCurrentLevel->myPlayer->myOrientation;

	myCurrentLevel->myPlayer->myOrientation = CU::GetOrientation(myCurrentLevel->myPlayer->myOrientation, playerRot);

	myCurrentLevel->myPlayer->myOrientation.SetPos(playerPos * 10.f);
	myCurrentLevel->myPlayer->myOriginalOrientation = myCurrentLevel->myPlayer->myOrientation;

	myCurrentLevel->myPlayer->Reset();

	myCurrentLevel->myConversationManager = new ConversationManager(conversationXML);
	myCurrentLevel->myMissionManager = new MissionManager(*myCurrentLevel, *myCurrentLevel->myPlayer, missionXML);
	myCurrentLevel->myEventManager = new EventManager(eventXML, *myCurrentLevel->myConversationManager
		, *myCurrentLevel->myPlayer);

	reader.ReadAttribute(reader.ForceFindFirstChild(levelElement, "skysphere"), "source", skySphere);
	reader.ReadAttribute(reader.ForceFindFirstChild(levelElement, "cubemap"), "source", cubeMap);

	Prism::Engine::GetInstance()->GetEffectContainer()->SetCubeMap(cubeMap);

	SetSkySphere(skySphere, "Data/Resource/Shader/S_effect_skybox.fx");

	LoadLights(reader, levelElement);
	LoadProps(reader, levelElement);
	LoadDefendables(reader, levelElement, myDifficults[myCurrentDifficultyID].myHealthMultiplier);
	LoadStructures(reader, levelElement);
	LoadTriggers(reader, levelElement);
	LoadPowerups(reader, levelElement);
	
	reader.CloseDocument();

	myCurrentLevel->myEMPHexagon = new Entity(eEntityType::EMP, *myCurrentLevel->myScene, Prism::eOctreeType::STATIC
		, "EMP");
	myCurrentLevel->myEMPHexagon->AddComponent<GraphicsComponent>()->Init("Data/Resource/Model/Weapon/SM_emp_hexasphere.fbx"
		, "Data/Resource/Shader/S_effect_emp.fx");

	myCurrentLevel->myEMPHexagon2 = new Entity(eEntityType::EMP, *myCurrentLevel->myScene, Prism::eOctreeType::STATIC
		, "EMP");
	myCurrentLevel->myEMPHexagon2->AddComponent<GraphicsComponent>()->Init("Data/Resource/Model/Weapon/SM_emp_hexasphere.fbx"
		, "Data/Resource/Shader/S_effect_emp.fx");


	for (int i = 0; i < myCurrentLevel->myEntities.Size(); ++i)
	{
		if (myCurrentLevel->myEntities[i]->GetComponent<AIComponent>() != nullptr)
		{
			std::string targetName = myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->GetTargetName();
			Entity* target = myCurrentLevel->GetEntityWithName(targetName);
			myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->SetEntityToFollow(myCurrentLevel->myPlayer, myCurrentLevel->myPlayer);
			if (target != nullptr)
			{
				myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->SetEntityToFollow(target, myCurrentLevel->myPlayer);
			}
		}

		if (myCurrentLevel->myEntities[i]->GetComponent<ParticleEmitterComponent>() != nullptr)
		{
			myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myEntities[i]->GetComponent<ParticleEmitterComponent>());
		}
	}

	for (int i = 0; i < static_cast<int>(eBulletType::COUNT); ++i)
	{
		if (i <= 8)
		{
			for (int j = 0; j < myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets.Size(); ++j)
			{
				if (myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets[j]->GetComponent<ParticleEmitterComponent>() != nullptr)
				{
					myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets[j]->GetComponent<ParticleEmitterComponent>());
				}
				if (myCurrentLevel->myBulletManager->GetBullet(i)->myEnemyBullets[j]->GetComponent<ParticleEmitterComponent>() != nullptr)
				{
					myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myBulletManager->GetBullet(i)->myEnemyBullets[j]->GetComponent<ParticleEmitterComponent>());
				}
			}
		}
	}
	AddToScene();

	myCurrentLevel->myMissionManager->Init();

	myCurrentLevel->myPlayer->GetComponent<InputComponent>()->SetSkyPosition();
	myCurrentLevel->myPlayer->GetComponent<GUIComponent>()->SetCockpitOrientation();

	Prism::Engine::GetInstance()->GetModelLoader()->UnPause();
	Prism::Engine::GetInstance()->GetModelLoader()->WaitUntilFinished();


	
	Prism::Engine::GetInstance()->GetEffectContainer()->GetEffect("Data/Resource/Shader/S_effect_pbl.fx")->SetAmbientHue(myAmbientHue);
	Prism::Engine::GetInstance()->myIsLoading = false;

	myIsLoading = false;
}
Exemple #8
0
void GLUTRedraw(void)
{
  // Check scene
  if (!scene) return;

  // Set viewing transformation
  viewer->Camera().Load();

  // Clear window
  RNRgb background = scene->Background();
  glClearColor(background.R(), background.G(), background.B(), 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Load lights
  LoadLights(scene);

  // Draw camera
  if (show_camera) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);
    glLineWidth(5);
    DrawCamera(scene);
    glLineWidth(1);
  }

  // Draw lights
  if (show_lights) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);
    glLineWidth(5);
    DrawLights(scene);
    glLineWidth(1);
  }

  // Draw rays
  if (show_rays) {
    glDisable(GL_LIGHTING);
    glColor3d(0.0, 1.0, 0.0);
    glLineWidth(3);
    DrawRays(scene);
    glLineWidth(1);
  }

  // Draw rays
  if (show_photons) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);
    glLineWidth(1);
    DrawPhotonPaths(scene);
    glLineWidth(1);
  }

  // Draw rays
  if (show_global_samples) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);
    glLineWidth(1);
    DrawGlobalSamples(scene);
    glLineWidth(1);
  }

  // Draw rays
  if (show_caustic_samples) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);
    glLineWidth(1);
    DrawCausticSamples(scene);
    glLineWidth(1);
  }

  // Draw scene nodes
  if (show_shapes) {
    glEnable(GL_LIGHTING);
    R3null_material.Draw();
    DrawShapes(scene, scene->Root());
    R3null_material.Draw();
  }

  // Draw bboxes
  if (show_bboxes) {
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 0.0, 0.0);
    DrawBBoxes(scene, scene->Root());
  }

  // Draw frame time
  if (show_frame_rate) {
    char buffer[128];
    static RNTime last_time;
    double frame_time = last_time.Elapsed();
    last_time.Read();
    if ((frame_time > 0) && (frame_time < 10)) {
      glDisable(GL_LIGHTING);
      glColor3d(1.0, 1.0, 1.0);
      sprintf(buffer, "%.1f fps", 1.0 / frame_time);
      DrawText(R2Point(100, 100), buffer);
    }
  }

  // Capture screenshot image
  if (screenshot_image_name) {
    if (print_verbose) printf("Creating image %s\n", screenshot_image_name);
    R2Image image(GLUTwindow_width, GLUTwindow_height, 3);
    image.Capture();
    image.Write(screenshot_image_name);
    screenshot_image_name = NULL;
  }

  // Swap buffers
  glutSwapBuffers();
}