Project GUI into space

--HG--
branch : multipass-stereo
This commit is contained in:
kaetemi 2014-08-01 15:44:12 +02:00
parent f32c3bf6b0
commit c11706feb8
4 changed files with 215 additions and 56 deletions

View file

@ -53,6 +53,9 @@ public:
/// Get the HMD orientation
virtual NLMISC::CQuat getOrientation() const = 0;
/// Set the GUI reference
virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix) = 0;
/// Get GUI center (1 = width, 1 = height, 0 = center)
virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const = 0;

View file

@ -123,6 +123,9 @@ public:
/// Get the HMD orientation
virtual NLMISC::CQuat getOrientation() const;
/// Set the GUI reference
virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix);
/// Get GUI center (1 = width, 1 = height, 0 = center)
virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const;
@ -134,21 +137,23 @@ public:
/// Set the scale of the game in units per meter
virtual void setScale(float s);
/// Calculates internal camera information based on the reference camera
void initCamera(uint cid, const NL3D::UCamera *camera);
/// Render GUI
void renderGUI();
/// Checks if the device used by this class was actually created
bool isDeviceCreated();
static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut);
static bool isLibraryInUse();
static void releaseLibrary();
/// Calculates internal camera information based on the reference camera
void initCamera(uint cid, const NL3D::UCamera *camera);
/// Checks if the device used by this class was actually created
bool isDeviceCreated();
private:
CStereoOVRDevicePtr *m_DevicePtr;
int m_Stage;
int m_SubStage;
CViewport m_RegularViewport;
CViewport m_LeftViewport;
CViewport m_RightViewport;
CFrustum m_ClippingFrustum[NL_STEREO_MAX_USER_CAMERAS];
@ -156,12 +161,13 @@ private:
CFrustum m_RightFrustum[NL_STEREO_MAX_USER_CAMERAS];
CFrustum m_OriginalFrustum[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_InterfaceCameraMatrix;
mutable bool m_OrientationCached;
mutable NLMISC::CQuat m_OrientationCache;
UDriver *m_Driver;
NLMISC::CSmartPtr<NL3D::ITexture> m_BarrelTex;
NL3D::CTextureUser *m_BarrelTexU;
NL3D::CTextureUser *m_SceneTexture;
NL3D::UMaterial m_BarrelMat;
NL3D::CTextureUser *m_GUITexture;
NLMISC::CQuadUV m_BarrelQuadLeft;
NLMISC::CQuadUV m_BarrelQuadRight;
NLMISC::CRefPtr<CPixelProgramOVR> m_PixelProgram;

View file

@ -169,7 +169,7 @@ public:
OVR::HMDInfo HMDInfo;
};
CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_BarrelTexU(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f)
CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f)
{
++s_DeviceCounter;
m_DevicePtr = new CStereoOVRDevicePtr();
@ -213,9 +213,6 @@ CStereoOVR::~CStereoOVR()
m_BarrelMat.getObjectPtr()->setTexture(0, NULL);
m_Driver->deleteMaterial(m_BarrelMat);
}
delete m_BarrelTexU;
m_BarrelTexU = NULL;
m_BarrelTex = NULL; // CSmartPtr
delete m_PixelProgram;
m_PixelProgram = NULL;
@ -340,7 +337,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
{
m_Driver = driver;
m_BarrelTex = new CTextureBloom(); // lol bloom
/*m_BarrelTex = new CTextureBloom(); // lol bloom
m_BarrelTex->setRenderTarget(true);
m_BarrelTex->setReleasable(false);
m_BarrelTex->resize(m_DevicePtr->HMDInfo.HResolution, m_DevicePtr->HMDInfo.VResolution);
@ -348,7 +345,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
m_BarrelTex->setWrapS(ITexture::Clamp);
m_BarrelTex->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*m_BarrelTex);
m_BarrelTexU = new CTextureUser(m_BarrelTex);
m_BarrelTexU = new CTextureUser(m_BarrelTex);*/
m_BarrelMat = m_Driver->createMaterial();
m_BarrelMat.initUnlit();
@ -361,7 +358,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
barrelMat->setZWrite(false);
barrelMat->setZFunc(CMaterial::always);
barrelMat->setDoubleSided(true);
barrelMat->setTexture(0, m_BarrelTex);
// barrelMat->setTexture(0, m_BarrelTex);
m_BarrelQuadLeft.V0 = CVector(0.f, 0.f, 0.5f);
m_BarrelQuadLeft.V1 = CVector(0.5f, 0.f, 0.5f);
@ -373,7 +370,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver)
m_BarrelQuadRight.V2 = CVector(1.f, 1.f, 0.5f);
m_BarrelQuadRight.V3 = CVector(0.5f, 1.f, 0.5f);
nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed
// nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed
m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f);
m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f);
@ -448,53 +445,59 @@ bool CStereoOVR::nextPass()
// Do not allow weird stuff.
uint32 width, height;
m_Driver->getWindowSize(width, height);
nlassert(width == m_DevicePtr->HMDInfo.HResolution);
nlassert(height == m_DevicePtr->HMDInfo.VResolution);
// nlassert(width == m_DevicePtr->HMDInfo.HResolution);
// nlassert(height == m_DevicePtr->HMDInfo.VResolution);
if (m_Driver->getPolygonMode() == UDriver::Filled)
{
switch (m_Stage)
switch (m_Stage) // Previous stage
{
case 0:
++m_Stage;
m_SubStage = 0;
// stage 1:
// (initBloom)
// clear buffer
// draw scene left
return true;
case 1:
++m_Stage;
m_Stage += 2;
m_SubStage = 0;
// stage 2:
// draw scene right
// draw interface 2d (onto render target)
return true;
case 2:
++m_Stage;
m_SubStage = 0;
// stage 3:
// (endBloom)
// draw interface 3d left
// (initBloom)
// clear buffer
// draw scene left
return true;
case 3:
++m_Stage;
m_SubStage = 0;
// stage 4:
// draw interface 3d right
// draw scene right
return true;
case 4:
++m_Stage;
m_SubStage = 0;
// stage 5:
// (endInterfacesDisplayBloom)
// draw interface 2d left
// (endBloom)
// draw interface 3d left
return true;
case 5:
++m_Stage;
m_SubStage = 0;
// stage 6:
// draw interface 2d right
// draw interface 3d right
return true;
/*case 6:
++m_Stage;
m_SubStage = 0;
// stage 7:
// (endInterfacesDisplayBloom)
// draw interface 2d left
return true;
case 7:
++m_Stage;
m_SubStage = 0;
// stage 8:
// draw interface 2d right
return true;*/
case 6:
m_Stage = 0;
m_SubStage = 0;
@ -526,26 +529,30 @@ bool CStereoOVR::nextPass()
const NL3D::CViewport &CStereoOVR::getCurrentViewport() const
{
if (m_Stage % 2) return m_LeftViewport;
if (m_Stage == 2) return m_RegularViewport;
else if (m_Stage % 2) return m_LeftViewport;
else return m_RightViewport;
}
const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const
{
if (m_Stage % 2) return m_LeftFrustum[cid];
if (m_Stage == 2) return m_OriginalFrustum[cid];
else if (m_Stage % 2) return m_LeftFrustum[cid];
else return m_RightFrustum[cid];
}
void CStereoOVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const
{
if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]);
if (m_Stage == 2) camera->setFrustum(m_OriginalFrustum[cid]);
else if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]);
else camera->setFrustum(m_RightFrustum[cid]);
}
void CStereoOVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const
{
CMatrix translate;
if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f));
if (m_Stage == 2) { }
else if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f));
else translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f));
CMatrix mat = m_CameraMatrix[cid] * translate;
if (camera->getTransformMode() == NL3D::UTransformable::RotQuat)
@ -564,7 +571,7 @@ bool CStereoOVR::wantClear()
{
switch (m_Stage)
{
case 1:
case 3:
m_SubStage = 1;
return true;
}
@ -575,8 +582,8 @@ bool CStereoOVR::wantScene()
{
switch (m_Stage)
{
case 1:
case 2:
case 3:
case 4:
m_SubStage = 2;
return true;
}
@ -587,8 +594,8 @@ bool CStereoOVR::wantInterface3D()
{
switch (m_Stage)
{
case 3:
case 4:
case 5:
case 6:
m_SubStage = 3;
return true;
}
@ -599,37 +606,163 @@ bool CStereoOVR::wantInterface2D()
{
switch (m_Stage)
{
case 5:
case 6:
case 2:
m_SubStage = 4;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
/// Returns non-NULL if a new render target was set
bool CStereoOVR::beginRenderTarget()
{
// render target always set before driver clear
// nlassert(m_SubStage <= 1);
if (m_Driver && m_Stage == 1 && (m_Driver->getPolygonMode() == UDriver::Filled))
// Set GUI render target
if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0);
nlassert(!m_GUITexture);
uint32 width, height;
m_Driver->getWindowSize(width, height);
m_GUITexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height, true, UTexture::RGBA8888);
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_GUITexture);
m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 0, 0));
return true;
}
// Begin 3D scene render target
if (m_Driver && m_Stage == 3 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
nlassert(!m_SceneTexture);
uint32 width, height;
m_Driver->getWindowSize(width, height); // Temporary limitation, TODO: scaling!
m_SceneTexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_SceneTexture);
return true;
}
return false;
}
void CStereoOVR::setInterfaceMatrix(const NL3D::CMatrix &matrix)
{
m_InterfaceCameraMatrix = matrix;
}
void CStereoOVR::renderGUI()
{
/*CMatrix mat;
mat.translate(m_InterfaceCameraMatrix.getPos());
CVector dir = m_InterfaceCameraMatrix.getJ();
dir.z = 0;
dir.normalize();
if (dir.y < 0)
mat.rotateZ(float(NLMISC::Pi+asin(dir.x)));
else
mat.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x)));
m_Driver->setModelMatrix(mat);*/
m_Driver->setModelMatrix(m_InterfaceCameraMatrix);
{
nlassert(m_GUITexture);
NLMISC::CQuadUV quad;
NL3D::UMaterial umat = m_Driver->createMaterial();
umat.initUnlit();
umat.setColor(NLMISC::CRGBA::White);
umat.setDoubleSided(true);
umat.setBlend(true);
umat.setAlphaTest(false);
NL3D::CMaterial *mat = umat.getObjectPtr();
mat->setShader(NL3D::CMaterial::Normal);
mat->setBlendFunc(CMaterial::one, CMaterial::TBlend::invsrcalpha);
mat->setZWrite(false);
// mat->setZFunc(CMaterial::always); // Not nice
mat->setDoubleSided(true);
mat->setTexture(0, m_GUITexture->getITexture());
// user options
float height = 6.0f;
float distance = 3.0f;
uint32 winw, winh;
m_Driver->getWindowSize(winw, winh);
float width = height * (float)winw / (float)winh;
NLMISC::CQuadUV quadUV;
quadUV.V0 = CVector(-(width * 0.5f), distance, -(height * 0.5f));
quadUV.V1 = CVector((width * 0.5f), distance, -(height * 0.5f));
quadUV.V2 = CVector((width * 0.5f), distance, (height * 0.5f));
quadUV.V3 = CVector(-(width * 0.5f), distance, (height * 0.5f));
quadUV.Uv0 = CUV(0.f, 0.f);
quadUV.Uv1 = CUV(1.f, 0.f);
quadUV.Uv2 = CUV(1.f, 1.f);
quadUV.Uv3 = CUV(0.f, 1.f);
m_Driver->drawQuad(quadUV, umat);
m_Driver->deleteMaterial(umat);
}
{
NLMISC::CLine line(NLMISC::CVector(0, 3, -3), NLMISC::CVector(0, 3, 3));
NL3D::UMaterial mat = m_Driver->createMaterial();
mat.setZWrite(false);
mat.setZFunc(UMaterial::always);
mat.setDoubleSided(true);
mat.setColor(NLMISC::CRGBA::Red);
mat.setBlend(false);
m_Driver->drawLine(line, mat);
m_Driver->deleteMaterial(mat);
}
}
/// Returns true if a render target was fully drawn
bool CStereoOVR::endRenderTarget()
{
// after rendering of course
// nlassert(m_SubStage > 1);
// End GUI render target
if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// End GUI render target
nlassert(m_GUITexture);
CTextureUser texNull;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(texNull);
}
// End of 3D Interface pass left
if (m_Driver && m_Stage == 5 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// Render 2D GUI in 3D space, assume existing camera is OK
renderGUI();
}
// End of 3D Interface pass right
if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
// Render 2D GUI in 3D space, assume existing camera is OK
renderGUI();
// Recycle render target
m_Driver->getRenderTargetManager().recycleRenderTarget(m_GUITexture);
m_GUITexture = NULL;
}
// End 3D scene render target
if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui
{
CTextureUser cu;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
nlassert(m_SceneTexture);
CTextureUser texNull;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(texNull);
bool fogEnabled = m_Driver->fogEnabled();
m_Driver->enableFog(false);
@ -640,7 +773,7 @@ bool CStereoOVR::endRenderTarget()
m_Driver->getWindowSize(width, height);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setTexture(0, m_BarrelTex);
barrelMat->setTexture(0, m_SceneTexture->getITexture());
drvInternal->activePixelProgram(m_PixelProgram);
@ -705,8 +838,13 @@ bool CStereoOVR::endRenderTarget()
drvInternal->activePixelProgram(NULL);
m_Driver->enableFog(fogEnabled);
// Recycle render target
m_Driver->getRenderTargetManager().recycleRenderTarget(m_SceneTexture);
m_SceneTexture = NULL;
return true;
}
return false;
}

View file

@ -1386,8 +1386,20 @@ bool mainLoop()
MainCam.setRotQuat(View.currentViewQuat());
if (StereoHMD)
{
CMatrix camMatrix;
camMatrix.translate(MainCam.getMatrix().getPos());
CVector dir = MainCam.getMatrix().getJ();
dir.z = 0;
dir.normalize();
if (dir.y < 0)
camMatrix.rotateZ(float(NLMISC::Pi+asin(dir.x)));
else
camMatrix.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x)));
StereoHMD->setInterfaceMatrix(camMatrix);
NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
NLMISC::CMatrix camMatrix = MainCam.getMatrix();
// NLMISC::CMatrix camMatrix = MainCam.getMatrix();
NLMISC::CMatrix hmdMatrix;
hmdMatrix.setRot(hmdOrient);
NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
@ -1645,7 +1657,7 @@ bool mainLoop()
{
if (Render)
{
if (ClientCfg.Bloom)
if (!StereoDisplay && ClientCfg.Bloom) // NO VR BLOOMZ
{
nlassert(bloomStage == 0);
// set bloom parameters before applying bloom effect
@ -1695,7 +1707,7 @@ bool mainLoop()
// Render
if (Render)
{
if (ClientCfg.Bloom && bloomStage == 1)
if (!StereoDisplay && ClientCfg.Bloom && bloomStage == 1) // NO VR BLOOMZ
{
// End the actual bloom effect visible in the scene.
if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
@ -1822,7 +1834,7 @@ bool mainLoop()
// special case in OpenGL : all scene has been display in render target,
// now, final texture is display with a quad
if (!ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2)
if (!StereoDisplay && !ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) // NO VR BLOOMZ
{
// End bloom effect system after drawing the 3d interface (z buffer related).
if (StereoDisplay) Driver->setViewport(NL3D::CViewport());