Project client loading screens into 3D space for HMD

--HG--
branch : multipass-stereo
This commit is contained in:
kaetemi 2014-08-07 18:49:05 +02:00
parent 38a418503d
commit 38abf2193f
3 changed files with 290 additions and 164 deletions

View file

@ -168,6 +168,7 @@ public:
private: private:
ovrHmd m_DevicePtr; ovrHmd m_DevicePtr;
bool m_DebugDevice;
int m_Stage; int m_Stage;
int m_SubStage; int m_SubStage;

View file

@ -175,6 +175,7 @@ CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NUL
return; return;
} }
m_DebugDevice = factory->DebugDevice;
if (factory->DebugDevice) m_DevicePtr = ovrHmd_CreateDebug(factory->DebugDeviceType); if (factory->DebugDevice) m_DevicePtr = ovrHmd_CreateDebug(factory->DebugDeviceType);
else m_DevicePtr = ovrHmd_Create(factory->DeviceIndex); else m_DevicePtr = ovrHmd_Create(factory->DeviceIndex);
@ -448,6 +449,9 @@ bool CStereoOVR::attachToDisplay()
{ {
nldebug("OVR: Attach to display '%s'", m_DevicePtr->DisplayDeviceName); nldebug("OVR: Attach to display '%s'", m_DevicePtr->DisplayDeviceName);
if (m_DebugDevice)
return false;
if (!m_AttachedDisplay) if (!m_AttachedDisplay)
{ {
m_Driver->getCurrentScreenMode(m_OriginalMode); m_Driver->getCurrentScreenMode(m_OriginalMode);
@ -792,7 +796,7 @@ void CStereoOVR::setInterfaceMatrix(const NL3D::CMatrix &matrix)
void CStereoOVR::renderGUI() void CStereoOVR::renderGUI()
{ {
m_Driver->setModelMatrix(m_InterfaceCameraMatrix); m_Driver->setModelMatrix(m_InterfaceCameraMatrix);
/*
{ {
NLMISC::CLine line(NLMISC::CVector(0, 5, 2), NLMISC::CVector(0, 5, 3)); NLMISC::CLine line(NLMISC::CVector(0, 5, 2), NLMISC::CVector(0, 5, 3));
@ -808,6 +812,41 @@ void CStereoOVR::renderGUI()
m_Driver->deleteMaterial(mat); m_Driver->deleteMaterial(mat);
} }
{
NL3D::UMaterial mat = m_Driver->createMaterial();
mat.setZWrite(false);
mat.setZFunc(UMaterial::always); // Not nice!
mat.setDoubleSided(true);
mat.setBlend(false);
NLMISC::CLine line;
mat.setColor(NLMISC::CRGBA::Red);
line = NLMISC::CLine(NLMISC::CVector(0, 3, -3), NLMISC::CVector(0, 3, 3)); // YPos
m_Driver->drawLine(line, mat);
mat.setColor(NLMISC::CRGBA::Green);
line = NLMISC::CLine(NLMISC::CVector(3, 0, -3), NLMISC::CVector(3, 0, 3)); // XPos
m_Driver->drawLine(line, mat);
mat.setColor(NLMISC::CRGBA::Magenta);
line = NLMISC::CLine(NLMISC::CVector(0, -3, -3), NLMISC::CVector(0, -3, 3)); // YNeg
m_Driver->drawLine(line, mat);
mat.setColor(NLMISC::CRGBA::Cyan);
line = NLMISC::CLine(NLMISC::CVector(-3, 0, -3), NLMISC::CVector(-3, 0, 3)); // XNeg
m_Driver->drawLine(line, mat);
mat.setColor(NLMISC::CRGBA::Blue);
line = NLMISC::CLine(NLMISC::CVector(0, -3, 3), NLMISC::CVector(0, 3, 3)); // ZPos
m_Driver->drawLine(line, mat);
mat.setColor(NLMISC::CRGBA::Blue);
line = NLMISC::CLine(NLMISC::CVector(0, -3, -3), NLMISC::CVector(0, 3, -3)); // ZNeg
m_Driver->drawLine(line, mat);
m_Driver->deleteMaterial(mat);
}
*/
{ {
nlassert(m_GUITexture); nlassert(m_GUITexture);
@ -910,6 +949,24 @@ void CStereoOVR::renderGUI()
// m_Driver->drawQuad(quadUV, umat); // m_Driver->drawQuad(quadUV, umat);
m_Driver->deleteMaterial(umat); m_Driver->deleteMaterial(umat);
/*{
// nldebug("Render GUI lines");
NL3D::UMaterial rmat = m_Driver->createMaterial();
rmat.setZWrite(false);
rmat.setZFunc(UMaterial::always); // Not nice!
rmat.setDoubleSided(true);
rmat.setColor(NLMISC::CRGBA::Red);
rmat.setBlend(false);
m_Driver->setPolygonMode(UDriver::Line);
driver->activeVertexBuffer(vb);
driver->activeIndexBuffer(ib);
driver->renderTriangles(*rmat.getObjectPtr(), 0, nbQuads * 2);
m_Driver->setPolygonMode(UDriver::Filled);
m_Driver->deleteMaterial(rmat);
}*/
} }
} }
@ -1131,7 +1188,8 @@ NLMISC::CQuat CStereoOVR::getOrientation() const
} }
else else
{ {
nlwarning("OVR: No orientation returned"); if (!m_DebugDevice)
nlwarning("OVR: No orientation returned");
// return old orientation // return old orientation
m_OrientationCached = true; m_OrientationCached = true;
return m_OrientationCache; return m_OrientationCache;

View file

@ -33,6 +33,7 @@
#include "client_cfg.h" #include "client_cfg.h"
#include "bg_downloader_access.h" #include "bg_downloader_access.h"
#include "nel/misc/system_utils.h" #include "nel/misc/system_utils.h"
#include "nel/3d/stereo_hmd.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
@ -173,186 +174,252 @@ void CProgress::internalProgress (float value)
if (Driver->AsyncListener.isKeyPushed (KeyUP)) if (Driver->AsyncListener.isKeyPushed (KeyUP))
selectTipsOfTheDay (TipsOfTheDayIndex+1); selectTipsOfTheDay (TipsOfTheDayIndex+1);
// Font factor // Create camera for stereo mode
float fontFactor = 1; bool stereoHMD = StereoHMD && !MainCam.empty() && (MainCam.getTransformMode() == UCamera::RotQuat);
if (Driver->getWindowHeight() > 0) CVector oldPos;
fontFactor = (float)Driver->getWindowHeight() / 600.f; CQuat oldQuat;
fontFactor *= _FontFactor; if (stereoHMD)
// Set 2d view.
Driver->setMatrixMode2D11();
Driver->clearBuffers (CRGBA(0,0,0,0));
// Display the loading background.
drawLoadingBitmap (value);
// temporary values for conversions
float x, y, width, height;
for(uint i = 0; i < ClientCfg.Logos.size(); i++)
{ {
std::vector<string> res; MainCam.getPos(oldPos);
explode(ClientCfg.Logos[i], std::string(":"), res); MainCam.getRotQuat(oldQuat);
if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL) StereoHMD->setInterfaceMatrix(CMatrix()); // identity
{ NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
fromString(res[1], x); NLMISC::CMatrix camMatrix;
fromString(res[2], y); camMatrix.identity();
fromString(res[3], width); NLMISC::CMatrix hmdMatrix;
fromString(res[4], height); hmdMatrix.setRot(hmdOrient);
Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]); NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
} posMatrix.translate(StereoHMD->getEyePosition());
NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix);
MainCam.setPos(mat.getPos());
MainCam.setRotQuat(mat.getRot());
StereoDisplay->updateCamera(0, &MainCam);
} }
uint i = 0;
if (TextContext != NULL) while ((!stereoHMD && i == 0) || (stereoHMD && StereoDisplay->nextPass()))
{ {
// Init the Pen. ++i;
TextContext->setKeep800x600Ratio(false); if (stereoHMD)
TextContext->setColor(CRGBA(255,255,255)); {
TextContext->setFontSize((uint)(12.f * fontFactor)); // modify cameras for stereo display
TextContext->setHotSpot(UTextContext::TopRight); const CViewport &vp = StereoDisplay->getCurrentViewport();
Driver->setViewport(vp);
StereoDisplay->getCurrentMatrix(0, &MainCam);
StereoDisplay->getCurrentFrustum(0, &MainCam);
// begin current pass
StereoDisplay->beginRenderTarget();
nldebug("Cam pos: %f, %f, %f", MainCam.getPos().x, MainCam.getPos().y, MainCam.getPos().z);
}
if (!stereoHMD || StereoDisplay->wantClear())
{
Driver->clearBuffers(CRGBA(0, 0, 0, 0));
}
if (stereoHMD && StereoDisplay->wantScene())
{
Driver->setMatrixMode3D(MainCam);
}
if (!stereoHMD || StereoDisplay->wantInterface2D())
{
nldebug("Draw progress 2D");
// Font factor
float fontFactor = 1;
if (Driver->getWindowHeight() > 0)
fontFactor = (float)Driver->getWindowHeight() / 600.f;
fontFactor *= _FontFactor;
// Set 2d view.
Driver->setMatrixMode2D11();
// Display the loading background.
drawLoadingBitmap(value);
// temporary values for conversions
float x, y, width, height;
for(uint i = 0; i < ClientCfg.Logos.size(); i++)
{
std::vector<string> res;
explode(ClientCfg.Logos[i], std::string(":"), res);
if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL)
{
fromString(res[1], x);
fromString(res[2], y);
fromString(res[3], width);
fromString(res[4], height);
Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]);
}
}
if (TextContext != NULL)
{
// Init the Pen.
TextContext->setKeep800x600Ratio(false);
TextContext->setColor(CRGBA(255,255,255));
TextContext->setFontSize((uint)(12.f * fontFactor));
TextContext->setHotSpot(UTextContext::TopRight);
#if !FINAL_VERSION #if !FINAL_VERSION
// Display the Text. // Display the Text.
TextContext->printAt(1, 0.98f, _ProgressMessage); TextContext->printAt(1, 0.98f, _ProgressMessage);
#else #else
if( ClientCfg.LoadingStringCount > 0 ) if( ClientCfg.LoadingStringCount > 0 )
{ {
TextContext->printAt(1, 0.98f, _ProgressMessage); TextContext->printAt(1, 0.98f, _ProgressMessage);
} }
#endif // FINAL_VERSION #endif // FINAL_VERSION
// Display the build version. // Display the build version.
TextContext->setFontSize((uint)(12.f * fontFactor)); TextContext->setFontSize((uint)(12.f * fontFactor));
TextContext->setHotSpot(UTextContext::TopRight); TextContext->setHotSpot(UTextContext::TopRight);
string str; string str;
#if FINAL_VERSION #if FINAL_VERSION
str = "FV "; str = "FV ";
#else #else
str = "DEV "; str = "DEV ";
#endif #endif
str += RYZOM_VERSION; str += RYZOM_VERSION;
TextContext->printfAt(1.0f,1.0f, str.c_str()); TextContext->printfAt(1.0f,1.0f, str.c_str());
// Display the tips of the day. // Display the tips of the day.
TextContext->setFontSize((uint)(16.f * fontFactor)); TextContext->setFontSize((uint)(16.f * fontFactor));
TextContext->setHotSpot(UTextContext::MiddleTop); TextContext->setHotSpot(UTextContext::MiddleTop);
ucstring::size_type index = 0; ucstring::size_type index = 0;
ucstring::size_type end = TipsOfTheDay.find((ucchar)'\n'); ucstring::size_type end = TipsOfTheDay.find((ucchar)'\n');
if (end == string::npos) if (end == string::npos)
end = TipsOfTheDay.size();
float fY = ClientCfg.TipsY;
if (!TipsOfTheDay.empty())
{
while (index < end)
{
// Get the line
ucstring line = TipsOfTheDay.substr (index, end-index);
// Draw the line
TextContext->printAt(0.5f, fY, line);
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
index=end+1;
end = TipsOfTheDay.find((ucchar)'\n', index);
if (end == ucstring::npos)
end = TipsOfTheDay.size(); end = TipsOfTheDay.size();
} float fY = ClientCfg.TipsY;
if (!TipsOfTheDay.empty())
// More help
TextContext->setFontSize((uint)(12.f * fontFactor));
/* todo tips of the day uncomment
ucstring ucstr = CI18N::get ("uiTipsEnd");
TextContext->printAt(0.5f, fY, ucstr); */
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
}
if (!_TPReason.empty())
{
TextContext->setHotSpot(UTextContext::MiddleMiddle);
TextContext->setFontSize((uint)(14.f * fontFactor));
TextContext->printAt(0.5f, 0.5f, _TPReason);
TextContext->setHotSpot(UTextContext::BottomLeft);
TextContext->setColor(NLMISC::CRGBA::White);
}
if (!_TPCancelText.empty())
{
if (ClientCfg.Width != 0 && ClientCfg.Height != 0)
{
TextContext->setFontSize((uint)(15.f * fontFactor));
TextContext->setHotSpot(UTextContext::BottomLeft);
ucstring uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel");
UTextContext::CStringInfo info = TextContext->getStringInfo(uc);
float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2);
TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc);
}
}
// Teleport help
//fY = ClientCfg.TeleportInfoY;
if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor)
{
TextContext->setFontSize((uint)(13.f * fontFactor));
// Print some more info
uint32 day = RT.getRyzomDay();
str = toString (CI18N::get ("uiTipsTeleport").toUtf8().c_str(),
CI18N::get (LoadingContinent->LocalizedName).toUtf8().c_str(),
day,
(uint)RT.getRyzomTime(),
CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).toUtf8().c_str(),
CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).toUtf8().c_str());
ucstring ucstr;
ucstr.fromUtf8 (str);
TextContext->setHotSpot(UTextContext::MiddleBottom);
TextContext->setColor(CRGBA(186, 179, 163, 255));
TextContext->printAt(0.5f, 25/768.f, ucstr);
}
// apply text commands
if( ApplyTextCommands )
{
std::vector<CClientConfig::SPrintfCommand> printfCommands = ClientCfg.PrintfCommands;
if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial;
if( !printfCommands.empty() )
{
TextContext->setHotSpot(UTextContext::MiddleBottom);
vector<CClientConfig::SPrintfCommand>::iterator itpc;
for( itpc = printfCommands.begin(); itpc != printfCommands.end(); ++itpc )
{ {
float x = 0.5f;//((*itpc).X / 1024.f); while (index < end)
float y = ((*itpc).Y / 768.f);
TextContext->setColor( (*itpc).Color );
TextContext->setFontSize( (uint)(16.f * fontFactor));
// build the ucstr(s)
ucstring ucstr = CI18N::get((*itpc).Text);
vector<ucstring> vucstr;
ucstring sep("\n");
splitUCString(ucstr,sep,vucstr);
// Letter size
UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|"));
uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap
uint i;
float newy = y;
for( i=0; i<vucstr.size(); ++i )
{ {
TextContext->printAt(x,newy, vucstr[i]); // Get the line
newy = nextLine(fontHeight, Driver->getWindowHeight(), newy); ucstring line = TipsOfTheDay.substr (index, end-index);
// Draw the line
TextContext->printAt(0.5f, fY, line);
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
index=end+1;
end = TipsOfTheDay.find((ucchar)'\n', index);
if (end == ucstring::npos)
end = TipsOfTheDay.size();
}
// More help
TextContext->setFontSize((uint)(12.f * fontFactor));
/* todo tips of the day uncomment
ucstring ucstr = CI18N::get ("uiTipsEnd");
TextContext->printAt(0.5f, fY, ucstr); */
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
}
if (!_TPReason.empty())
{
TextContext->setHotSpot(UTextContext::MiddleMiddle);
TextContext->setFontSize((uint)(14.f * fontFactor));
TextContext->printAt(0.5f, 0.5f, _TPReason);
TextContext->setHotSpot(UTextContext::BottomLeft);
TextContext->setColor(NLMISC::CRGBA::White);
}
if (!_TPCancelText.empty())
{
if (ClientCfg.Width != 0 && ClientCfg.Height != 0)
{
TextContext->setFontSize((uint)(15.f * fontFactor));
TextContext->setHotSpot(UTextContext::BottomLeft);
ucstring uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel");
UTextContext::CStringInfo info = TextContext->getStringInfo(uc);
float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2);
TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc);
}
}
// Teleport help
//fY = ClientCfg.TeleportInfoY;
if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor)
{
TextContext->setFontSize((uint)(13.f * fontFactor));
// Print some more info
uint32 day = RT.getRyzomDay();
str = toString (CI18N::get ("uiTipsTeleport").toUtf8().c_str(),
CI18N::get (LoadingContinent->LocalizedName).toUtf8().c_str(),
day,
(uint)RT.getRyzomTime(),
CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).toUtf8().c_str(),
CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).toUtf8().c_str());
ucstring ucstr;
ucstr.fromUtf8 (str);
TextContext->setHotSpot(UTextContext::MiddleBottom);
TextContext->setColor(CRGBA(186, 179, 163, 255));
TextContext->printAt(0.5f, 25/768.f, ucstr);
}
// apply text commands
if( ApplyTextCommands )
{
std::vector<CClientConfig::SPrintfCommand> printfCommands = ClientCfg.PrintfCommands;
if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial;
if( !printfCommands.empty() )
{
TextContext->setHotSpot(UTextContext::MiddleBottom);
vector<CClientConfig::SPrintfCommand>::iterator itpc;
for( itpc = printfCommands.begin(); itpc != printfCommands.end(); ++itpc )
{
float x = 0.5f;//((*itpc).X / 1024.f);
float y = ((*itpc).Y / 768.f);
TextContext->setColor( (*itpc).Color );
TextContext->setFontSize( (uint)(16.f * fontFactor));
// build the ucstr(s)
ucstring ucstr = CI18N::get((*itpc).Text);
vector<ucstring> vucstr;
ucstring sep("\n");
splitUCString(ucstr,sep,vucstr);
// Letter size
UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|"));
uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap
uint i;
float newy = y;
for( i=0; i<vucstr.size(); ++i )
{
TextContext->printAt(x,newy, vucstr[i]);
newy = nextLine(fontHeight, Driver->getWindowHeight(), newy);
}
}
} }
} }
} }
} }
if (stereoHMD)
{
StereoDisplay->endRenderTarget();
}
} /* stereo loop */
if (stereoHMD)
{
MainCam.setPos(oldPos);
MainCam.setRotQuat(oldQuat);
} }
// Clamp // Clamp