Jump to content
reepblue

VR: Map changing fails in when VR Enabled

Recommended Posts

I was working on my VR project this weekend and came across something regarding world clearing/context going nullptr when you go to change the map. The code below is a lua example of this, but if you were to re-write this in C++, the debugger will stop at the first reference of the context. Hit space on the keyboard to call the restart. If you tried when VR is not enabled, it'll work fine.

--Set the application title
title="VR Template"

--Create a window
local windowstyle = 0
local winwidth
local winheight
local gfxmode = System:GetGraphicsMode(System:CountGraphicsModes()-1)

if System:GetProperty("devmode")=="1" then
	gfxmode.x = math.min(1280,gfxmode.x)
	gfxmode.y = Math:Round(gfxmode.x * 9 / 16)
	windowstyle = Window.Titlebar+Window.Center
end

window=Window:Create(title,0,0,gfxmode.x,gfxmode.y,windowstyle)

--Create the graphics context
context=Context:Create(window,0)
if context==nil then return end

--Create a world
world=World:Create()

--Load a map
local mapfile = System:GetProperty("map","Maps/start.map")
if mapfile~="" then
	if Map:Load(mapfile)==false then return end
	prevmapname = FileSystem:StripAll(changemapname)
	
	--Send analytics event
	Analytics:SendProgressEvent("Start",prevmapname)
	
	window:HideMouse()
end

while window:Closed()==false do
	
	if window:KeyHit(Key.Escape) then return end

	if window:KeyHit(Key.Space) then 
		changemapname = "start"
	end

	--Handle map change
	if changemapname~=nil then
		
		--Pause the clock
		Time:Pause()
		
		--Pause garbage collection
		System:GCSuspend()		
		
		--Clear all entities
		world:Clear()
		
		--Send analytics event
		Analytics:SendProgressEvent("Complete",prevmapname)
		
		--Load the next map
		if Map:Load("Maps/"..changemapname..".map")==false then return end
		prevmapname = changemapname
		
		--Send analytics event
		Analytics:SendProgressEvent("Start",prevmapname)
		
		--Resume garbage collection
		System:GCResume()
		
		--Resume the clock
		Time:Resume()
		
		changemapname = nil
	end	
	
	--Update the app timing
	Time:Update()
	
	world:Update()

	--Render the world
	world:Render()
	
	--Refresh the screen
	VR:MirrorDisplay(context)
	context:Sync()
	
end

Again, it throws an exception at VR::MirrorDisplay stating something about the context pointer.

 

 

Share this post


Link to post

To save you more time, replace the stock app files with this:

Header:

#ifndef APP_H
#define APP_H
#ifdef WIN32
#pragma once
#endif

#include "Framework.h"

namespace Leadwerks
{
	class App
	{
		Window* window;
		Context* context;

	public:
		App();
		virtual ~App();

		bool Start();
		bool Loop();

		static void ChangeLevel(const std::string& pName);
	};
}

#endif // APP_H

CPP:

#include "App.h"

#define VR_ENABLED 1  
  
namespace Leadwerks
{
	unsigned int windowstyle = 0;
	unsigned int winwidth;
	unsigned int winheight;
	iVec2  gfxmode;

	World* world;

	std::string changename;
	std::string currentmap;

	void Call_PostStart()
	{
		Entity* e;
		for (int i = 0; i <= world->CountEntities(); i++)
		{
			e = world->GetEntity(i);
			if (e != NULL)
			{
				if (e->GetKeyValue("PostStart") != "1")
				{
					if (e->CallFunction("PostStart"))
					{
						std::string entityname = "\"" + e->GetKeyValue("name") + "\"";
						Print("Firing PostStart() on entity: " + entityname);
						e->SetKeyValue("PostStart", "1");
					}
				}
			}
		}
	};

	void Call_ChangeMap(const std::string& pName)
	{
		std::string fullname = "Maps/" + pName + ".map";
		System::Print("Changing map to: \"" + fullname + "\"...");
		if (Map::Load(fullname) == false)
		{
			Print("Error: Failed to load map file \"" + fullname + "\"...");
			fullname.clear();
			currentmap = "";  

			return;
		}

		fullname.clear();
		currentmap = pName;
		Call_PostStart();
		changename = "";
		System::Print("Current map is: \"Maps/"  + currentmap + ".map" + "\"...");
	};


	App::App() : window(NULL), context(NULL) {}

	App::~App() { delete world; delete window; }

	bool App::Start()
	{
		gfxmode = System::GetGraphicsMode(System::CountGraphicsModes() - 1);
		currentmap = System::GetProperty("map", "Maps/start.map");
		gfxmode.x = Math::Min(1280, gfxmode.x);
		gfxmode.y = Math::Round(gfxmode.x * 9 / 16);
		windowstyle = Window::Titlebar + Window::Center;

#ifdef VR_ENABLED
		VRRules::InitVR();
#endif

		window = Window::Create(System::AppName, 0, 0, gfxmode.x, gfxmode.y, windowstyle);
		context = Context::Create(window, 0);
		if (context == nullptr)
		{
			Debug::Assert("Failed to create context");
		}

		world = World::Create();

		if (currentmap != "")
		{
			ChangeLevel(FileSystem::StripAll(currentmap));
		}

		return true;
	}

	bool App::Loop()
	{
		if (window->Closed()) return false;
		if (window->KeyHit(Key::Escape)) return false;

		if (window->KeyHit(Key::Space)) { ChangeLevel(currentmap); return true; }
		
		if (changename != "")
		{
			// Pause the clock
			Time::Pause();

			/*
			if (VRRules::IsVREnabled())
			{
				VR::DisableCamera();
			}
			*/

			// Pause garbage collection
			System::GCSuspend(); 

			// Clear all entities
			world->Clear();

			// Load the next map
			Call_ChangeMap(changename);

			// Resume garbage collection
			System::GCResume();

			/*
			if (VRRules::IsVREnabled())
			{
				VR::EnableCamera();
			}
			*/

			// Resume the clock
			Time::Resume();

			changename = "";
		}

		// Update the app timing
		Time::Update();

		// Render the world
		world->Update();
		world->Render();

		if (context != NULL)
		{
#ifdef VR_ENABLED
			context->SetBlendMode(Blend::Alpha);
			auto t = Math::Round(Time::UPS());
			context->DrawText("FPS: " + String(t), 2, 2);

			//Refresh the screen
			VR::MirrorDisplay(context);
			context->Sync();
#else
			//Refresh the screen
			context->Sync(true);
#endif
		}

		
		return true;
	}

	void App::ChangeLevel(const std::string& pName)
	{
		changename = pName;
	}
}

 

Share this post


Link to post

This should not be happening but I can’t test it out for a couple of weeks. This is really my workspace right now:

4C12FA2B-40A6-4160-899E-28A7F95DF47E.thumb.jpeg.4a3e6339119d22289d87ef6562f0f539.jpeg

  • Like 4
  • Haha 1
  • Sad 1

Share this post


Link to post

Ok, thanks for the acknowledgement, and hopefully it can be addressed soon.

Also, I've seen worse setups. 🙂

Share this post


Link to post
5 hours ago, Josh said:

Esto no debería estar pasando, pero no puedo probarlo durante un par de semanas. Este es realmente mi espacio de trabajo ahora mismo:

4C12FA2B-40A6-4160-899E-28A7F95DF47E.thumb.jpeg.4a3e6339119d22289d87ef6562f0f539.jpeg

That little box, is it a cpu?
 

Share this post


Link to post
3 hours ago, Yue said:

Something that really impresses me. 

They gave them away so that developers would end up optimizing rendering for them, and in my case it is working. I have been designing the new renderer with this little box, with the idea that anything that performs well on here will be absolutely killer fast on a discrete GPU. As a result, our new engine will easily handle VR with Intel graphics.

  • Like 1

Share this post


Link to post

Also had a problem a couple of months ago with map changing when VR is Enabled:

https://www.leadwerks.com/community/topic/17240-changing-maps-in-vr-results-in-error-message/

Not sure if it is the same problem but haven't got it solved yet...

Share this post


Link to post

Okay, this fix is pretty straightforward. The models created by the VR system are being deleted when the world is cleared. So I need to figure out a way to handle this. I wish Leadwerks 4 had smart pointers!!!

Share this post


Link to post

Hmm, I had an idea of just not storing the VR models with the world classes vector/map container but that might not be a good idea.

Share this post


Link to post

I got it worked out. Works perfectly. Sorry I let that one go for so long. It's fixed for the next build.

  • Like 2

Share this post


Link to post
Guest
This topic is now closed to further replies.
×
×
  • Create New...