mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 06:45:32 +00:00
Render menu to quad
This commit is contained in:
parent
f25be2a44a
commit
5b24c5f3ce
5 changed files with 64 additions and 50 deletions
|
@ -6,15 +6,17 @@
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/ClipNode>
|
#include <osg/ClipNode>
|
||||||
#include <osg/FrontFace>
|
#include <osg/FrontFace>
|
||||||
|
#include <osg/BlendFunc>
|
||||||
|
#include <osg/Depth>
|
||||||
#include <components/sceneutil/visitor.hpp>
|
#include <components/sceneutil/visitor.hpp>
|
||||||
#include <components/sceneutil/shadow.hpp>
|
#include <components/sceneutil/shadow.hpp>
|
||||||
#include <osgViewer/Renderer>
|
#include <osgViewer/Renderer>
|
||||||
#include "../mwrender/util.hpp"
|
#include "../mwrender/util.hpp"
|
||||||
|
#include "../mwrender/renderbin.hpp"
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
class Menus : public osg::Camera
|
class Menus : public osg::Camera
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -22,16 +24,17 @@ public:
|
||||||
{
|
{
|
||||||
setRenderOrder(osg::Camera::PRE_RENDER);
|
setRenderOrder(osg::Camera::PRE_RENDER);
|
||||||
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
// Give bg a tint of green just to stand out, for testing
|
||||||
|
setClearColor(osg::Vec4(0.f,0.f,0.f,.75f));
|
||||||
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||||
setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
|
|
||||||
setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||||
setName("ReflectionCamera");
|
setName("MenuCamera");
|
||||||
|
|
||||||
setCullMask(MWRender::Mask_GUI);
|
setCullMask(MWRender::Mask_GUI);
|
||||||
setNodeMask(MWRender::Mask_RenderToTexture);
|
setNodeMask(MWRender::Mask_RenderToTexture);
|
||||||
|
|
||||||
unsigned int rttSize = 1000;
|
unsigned int rttSize = 4000;
|
||||||
setViewport(0, 0, rttSize, rttSize);
|
setViewport(0, 0, rttSize, rttSize);
|
||||||
|
|
||||||
// No need for Update traversal since the mSceneRoot is already updated as part of the main scene graph
|
// No need for Update traversal since the mSceneRoot is already updated as part of the main scene graph
|
||||||
|
@ -40,23 +43,18 @@ public:
|
||||||
|
|
||||||
mMenuTexture = new osg::Texture2D;
|
mMenuTexture = new osg::Texture2D;
|
||||||
mMenuTexture->setTextureSize(rttSize, rttSize);
|
mMenuTexture->setTextureSize(rttSize, rttSize);
|
||||||
mMenuTexture->setInternalFormat(GL_RGB);
|
mMenuTexture->setInternalFormat(GL_RGBA);
|
||||||
mMenuTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
mMenuTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
||||||
mMenuTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
mMenuTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||||
mMenuTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
mMenuTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||||
mMenuTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
mMenuTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
attach(osg::Camera::COLOR_BUFFER, mMenuTexture);
|
attach(osg::Camera::COLOR_BUFFER, mMenuTexture);
|
||||||
|
|
||||||
// XXX: should really flip the FrontFace on each renderable instead of forcing clockwise.
|
|
||||||
//osg::ref_ptr<osg::FrontFace> frontFace(new osg::FrontFace);
|
|
||||||
//frontFace->setMode(osg::FrontFace::CLOCKWISE);
|
|
||||||
//getOrCreateStateSet()->setAttributeAndModes(frontFace, osg::StateAttribute::ON);
|
|
||||||
|
|
||||||
//mClipCullNode = new ClipCullNode;
|
|
||||||
//addChild(mClipCullNode);
|
|
||||||
|
|
||||||
SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet());
|
SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet());
|
||||||
|
getOrCreateStateSet()->setRenderBinDetails(-1, "RenderBin");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScene(osg::Node* scene)
|
void setScene(osg::Node* scene)
|
||||||
|
@ -65,6 +63,7 @@ public:
|
||||||
removeChild(mScene);
|
removeChild(mScene);
|
||||||
mScene = scene;
|
mScene = scene;
|
||||||
addChild(scene);
|
addChild(scene);
|
||||||
|
Log(Debug::Verbose) << "Set new scene: " << mScene->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Texture2D* getMenuTexture() const
|
osg::Texture2D* getMenuTexture() const
|
||||||
|
@ -127,29 +126,27 @@ private:
|
||||||
osg::ref_ptr<osg::Vec3Array> normals{ new osg::Vec3Array(1) };
|
osg::ref_ptr<osg::Vec3Array> normals{ new osg::Vec3Array(1) };
|
||||||
osg::ref_ptr<osg::Vec4Array> colors{ new osg::Vec4Array(1) };
|
osg::ref_ptr<osg::Vec4Array> colors{ new osg::Vec4Array(1) };
|
||||||
|
|
||||||
extent_meters *= OpenXREnvironment::get().unitsPerMeter() / 2.f;
|
// Units are divided by 2 because geometry has an extent of 2 (-1 to 1)
|
||||||
|
auto extent_units = extent_meters * OpenXREnvironment::get().unitsPerMeter() / 2.f;
|
||||||
|
|
||||||
float w = extent_meters.x();
|
osg::Vec3 top_left (-1, 1, 1);
|
||||||
float h = extent_meters.y();
|
osg::Vec3 bottom_left(-1, -1, 1);
|
||||||
|
osg::Vec3 bottom_right(1, -1, 1);
|
||||||
osg::Vec3 top_left (-w, h, 1);
|
osg::Vec3 top_right (1, 1, 1);
|
||||||
osg::Vec3 bottom_left(-w, -h, 1);
|
|
||||||
osg::Vec3 bottom_right(w, -h, 1);
|
|
||||||
osg::Vec3 top_right (w, h, 1);
|
|
||||||
(*vertices)[0] = top_left;
|
(*vertices)[0] = top_left;
|
||||||
(*vertices)[1] = bottom_left;
|
(*vertices)[1] = bottom_left;
|
||||||
(*vertices)[2] = bottom_right;
|
(*vertices)[2] = bottom_right;
|
||||||
(*vertices)[3] = top_right;
|
(*vertices)[3] = top_right;
|
||||||
mGeometry->setVertexArray(vertices);
|
mGeometry->setVertexArray(vertices);
|
||||||
(*texCoords)[0].set(0.0f, 0.0f);
|
(*texCoords)[0].set(0.0f, 1.0f);
|
||||||
(*texCoords)[1].set(1.0f, 0.0f);
|
(*texCoords)[1].set(0.0f, 0.0f);
|
||||||
(*texCoords)[2].set(1.0f, 1.0f);
|
(*texCoords)[2].set(1.0f, 0.0f);
|
||||||
(*texCoords)[3].set(0.0f, 1.0f);
|
(*texCoords)[3].set(1.0f, 1.0f);
|
||||||
mGeometry->setTexCoordArray(0, texCoords);
|
mGeometry->setTexCoordArray(0, texCoords);
|
||||||
(*normals)[0].set(0.0f, -1.0f, 0.0f);
|
(*normals)[0].set(0.0f, -1.0f, 0.0f);
|
||||||
(*colors)[0].set(1.0f, 1.0f, 1.0f, 0.0f);
|
(*colors)[0].set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
mGeometry->setNormalArray(normals, osg::Array::BIND_OVERALL);
|
mGeometry->setNormalArray(normals, osg::Array::BIND_OVERALL);
|
||||||
mGeometry->setColorArray(colors, osg::Array::BIND_OVERALL);
|
//mGeometry->setColorArray(colors, osg::Array::BIND_OVERALL);
|
||||||
mGeometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
|
mGeometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
|
||||||
mGeometry->setDataVariance(osg::Object::DYNAMIC);
|
mGeometry->setDataVariance(osg::Object::DYNAMIC);
|
||||||
mGeometry->setSupportsDisplayList(false);
|
mGeometry->setSupportsDisplayList(false);
|
||||||
|
@ -159,28 +156,35 @@ private:
|
||||||
|
|
||||||
mStateSet->setTextureAttributeAndModes(0, menuTexture(), osg::StateAttribute::ON);
|
mStateSet->setTextureAttributeAndModes(0, menuTexture(), osg::StateAttribute::ON);
|
||||||
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
mStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
mStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
mStateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
|
mStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
|
||||||
|
|
||||||
mGeometry->setStateSet(mStateSet);
|
mGeometry->setStateSet(mStateSet);
|
||||||
|
|
||||||
// Units are divided by 2 because geometry has side lengths of 2 units.
|
|
||||||
|
|
||||||
// mTransform->setScale(osg::Vec3(extent_meters.x(), extent_meters.y(), 1.f));
|
mTransform->setScale(osg::Vec3(extent_units.x(), extent_units.y(), 1.f));
|
||||||
mTransform->setScale(osg::Vec3(1.f, 1.f, 1.f));
|
|
||||||
mTransform->setAttitude(pose.orientation);
|
mTransform->setAttitude(pose.orientation);
|
||||||
mTransform->setPosition(pose.position);
|
mTransform->setPosition(pose.position);
|
||||||
|
|
||||||
mGeode->addDrawable(mGeometry);
|
mGeode->addDrawable(mGeometry);
|
||||||
mTransform->addChild(mGeode);
|
mTransform->addChild(mGeode);
|
||||||
mParent->addChild(mTransform);
|
mParent->addChild(mTransform);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mParent->addChild(mMenuCamera.get());
|
SceneUtil::FindByNameVisitor findRootVisitor("OpenXRRoot", osg::NodeVisitor::TRAVERSE_PARENTS);
|
||||||
|
mParent->accept(findRootVisitor);
|
||||||
|
findRootVisitor.mFoundNode->addChild(mMenuCamera.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRMenu::~OpenXRMenu()
|
OpenXRMenu::~OpenXRMenu()
|
||||||
{
|
{
|
||||||
mParent->removeChild(mTransform);
|
mParent->removeChild(mTransform);
|
||||||
mParent->removeChild(mMenuCamera.get());
|
|
||||||
|
SceneUtil::FindByNameVisitor findRootVisitor("OpenXRRoot", osg::NodeVisitor::TRAVERSE_PARENTS);
|
||||||
|
mParent->accept(findRootVisitor);
|
||||||
|
findRootVisitor.mFoundNode->removeChild(mMenuCamera.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRMenu::updateCallback()
|
void OpenXRMenu::updateCallback()
|
||||||
|
@ -217,9 +221,22 @@ private:
|
||||||
root->accept(findGUIVisitor);
|
root->accept(findGUIVisitor);
|
||||||
mGuiRoot = findGUIVisitor.mFoundNode;
|
mGuiRoot = findGUIVisitor.mFoundNode;
|
||||||
if (!mGuiRoot)
|
if (!mGuiRoot)
|
||||||
throw std::logic_error("Gui root doesn't exist");
|
{
|
||||||
|
Log(Debug::Error) << "GUI Root doesn't exist";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
root->asGroup()->addChild(mMenusRoot);
|
SceneUtil::FindByNameVisitor findSceneVisitor("Scene Root");
|
||||||
|
root->accept(findSceneVisitor);
|
||||||
|
if(!findSceneVisitor.mFoundNode)
|
||||||
|
{
|
||||||
|
Log(Debug::Error) << "Scene Root doesn't exist";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Debug::Verbose) << "Root note: " << root->getName();
|
||||||
|
|
||||||
|
findSceneVisitor.mFoundNode->addChild(mMenusRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRMenuManager::~OpenXRMenuManager(void)
|
OpenXRMenuManager::~OpenXRMenuManager(void)
|
||||||
|
@ -239,7 +256,7 @@ private:
|
||||||
mMenusRoot,
|
mMenusRoot,
|
||||||
mGuiRoot,
|
mGuiRoot,
|
||||||
"Main Menu",
|
"Main Menu",
|
||||||
osg::Vec2(2.f, 2.f),
|
osg::Vec2(1.5f, 1.5f),
|
||||||
mPose,
|
mPose,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -270,10 +287,10 @@ private:
|
||||||
|
|
||||||
camera->getViewMatrixAsLookAt(eye, center, up);
|
camera->getViewMatrixAsLookAt(eye, center, up);
|
||||||
|
|
||||||
// Position the menu half a meter in front of the player
|
// Position the menu about two thirds of a meter in front of the player
|
||||||
osg::Vec3 dir = center - eye;
|
osg::Vec3 dir = center - eye;
|
||||||
dir.normalize();
|
dir.normalize();
|
||||||
mPose.position = eye + dir * OpenXREnvironment::get().unitsPerMeter();
|
mPose.position = eye + dir * OpenXREnvironment::get().unitsPerMeter() * 2.f / 3.f;
|
||||||
|
|
||||||
|
|
||||||
mPose.orientation = camera->getViewMatrix().getRotate().inverse();
|
mPose.orientation = camera->getViewMatrix().getRotate().inverse();
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace MWVR
|
||||||
auto* state = gc->getState();
|
auto* state = gc->getState();
|
||||||
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, mFBO);
|
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, mFBO);
|
||||||
gl->glBlitFramebuffer(0, 0, mWidth, mHeight, x, y, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
gl->glBlitFramebuffer(0, 0, mWidth, mHeight, x, y, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ namespace MWVR
|
||||||
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, mBlitFBO);
|
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, mBlitFBO);
|
||||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, mFBO);
|
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, mFBO);
|
||||||
gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blitTarget, 0);
|
gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blitTarget, 0);
|
||||||
gl->glBlitFramebuffer(0, 0, mWidth, mHeight, x, y, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
gl->glBlitFramebuffer(0, 0, mWidth, mHeight, x, y, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
||||||
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
|
@ -50,12 +50,8 @@ namespace MWVR {
|
||||||
return camera.release();
|
return camera.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLint wfbo = 0;
|
|
||||||
static GLint rfbo = 0;
|
|
||||||
void OpenXRView::prerenderCallback(osg::RenderInfo& renderInfo)
|
void OpenXRView::prerenderCallback(osg::RenderInfo& renderInfo)
|
||||||
{
|
{
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &wfbo);
|
|
||||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfbo);
|
|
||||||
if (mSwapchain)
|
if (mSwapchain)
|
||||||
{
|
{
|
||||||
mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
|
mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
|
||||||
|
@ -72,8 +68,6 @@ namespace MWVR {
|
||||||
Log(Debug::Verbose) << "XRView: PostRender";
|
Log(Debug::Verbose) << "XRView: PostRender";
|
||||||
auto state = renderInfo.getState();
|
auto state = renderInfo.getState();
|
||||||
auto gl = osg::GLExtensions::Get(state->getContextID(), false);
|
auto gl = osg::GLExtensions::Get(state->getContextID(), false);
|
||||||
gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, wfbo);
|
|
||||||
gl->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, rfbo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRView::swapBuffers(osg::GraphicsContext* gc)
|
void OpenXRView::swapBuffers(osg::GraphicsContext* gc)
|
||||||
|
|
|
@ -278,7 +278,7 @@ namespace MWVR
|
||||||
mLayer->views = mCompositionLayerProjectionViews.data();
|
mLayer->views = mCompositionLayerProjectionViews.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
blitEyesToMirrorTexture(gc);
|
blitEyesToMirrorTexture(gc, false);
|
||||||
|
|
||||||
gc->swapBuffersImplementation();
|
gc->swapBuffersImplementation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ public:
|
||||||
// Stage 2: execute the draw calls. Run during the Draw traversal. May run in parallel with the update traversal of the next frame.
|
// Stage 2: execute the draw calls. Run during the Draw traversal. May run in parallel with the update traversal of the next frame.
|
||||||
virtual void drawImplementation(osg::RenderInfo &renderInfo) const
|
virtual void drawImplementation(osg::RenderInfo &renderInfo) const
|
||||||
{
|
{
|
||||||
|
std::cout << "DrawImplementation" << std::endl;
|
||||||
osg::State *state = renderInfo.getState();
|
osg::State *state = renderInfo.getState();
|
||||||
|
|
||||||
state->pushStateSet(mStateSet);
|
state->pushStateSet(mStateSet);
|
||||||
|
@ -386,16 +387,18 @@ void RenderManager::initialise()
|
||||||
mUpdate = false;
|
mUpdate = false;
|
||||||
|
|
||||||
mDrawable = new Drawable(this);
|
mDrawable = new Drawable(this);
|
||||||
|
mDrawable->setName("GUI Drawable");
|
||||||
|
|
||||||
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
|
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
|
||||||
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||||
camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||||
camera->setProjectionMatrix(osg::Matrix::identity());
|
camera->setProjectionMatrix(osg::Matrix::identity());
|
||||||
camera->setViewMatrix(osg::Matrix::identity());
|
camera->setViewMatrix(osg::Matrix::identity());
|
||||||
camera->setRenderOrder(osg::Camera::POST_RENDER);
|
camera->setRenderOrder(osg::Camera::NESTED_RENDER);
|
||||||
camera->setClearMask(GL_NONE);
|
camera->setClearMask(GL_NONE);
|
||||||
mDrawable->setCullingActive(false);
|
mDrawable->setCullingActive(false);
|
||||||
camera->addChild(mDrawable.get());
|
camera->addChild(mDrawable.get());
|
||||||
|
camera->setName("GUI Camera");
|
||||||
|
|
||||||
mGuiRoot = camera;
|
mGuiRoot = camera;
|
||||||
mSceneRoot->addChild(mGuiRoot.get());
|
mSceneRoot->addChild(mGuiRoot.get());
|
||||||
|
|
Loading…
Reference in a new issue