[2.1] How to set projectionMatrix in a MovableObject?

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

[2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

Hi,

i've just tried to get the imgui library to work in a simple way like my other ingame gui.
So far i can render the vertices. But the problem is the projection matrix i think ..
I do not realy understand that stuff so maybe someone could enlighten me?
I think i need to set the projmatrix like chaoscreator:

Code: Select all

Ogre::Matrix4 projMatrix(2.0f / io.DisplaySize.x, 0.0f, 0.0f, -1.0f,
		0.0f, -2.0f / io.DisplaySize.y, 0.0f, 1.0f,
		0.0f, 0.0f, -1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f);
	mPass->getVertexProgramParameters()->setNamedConstant("ProjectionMatrix", projMatrix);
chaos creators code

I'm using a movableobject/renderable. If i remove the 2d stuff:
// use identity projection and view matrices
// mUseIdentityProjection = true;
// mUseIdentityView = true;
i get the 3d presentation, but flipped.
In 2d mode nothing is displayed.
Image

My MovableObject code:

Code: Select all

#include <XERenderer/Editor/ImgGuiRenderable.hpp>

#include <XERenderer/GUI/GUIRenderer.hpp>
#include <XERenderer/GraphicsManager.hpp>

#include <Ogre/OgreMain/include/OgreSceneManager.h>
#include <Ogre/OgreMain/include/OgreRoot.h>
#include "OgreHlmsManager.h"
#include "OgreHlms.h"

#include <ThirdParty/imgui/imgui.h>
#include <OgreHardwarePixelBuffer.h>

#include <Ogre/OgreMain/include/OgreMaterial.h>
#include <Ogre/OgreMain/include/OgreTechnique.h>

namespace XE {

	ImgGuiRenderable::ImgGuiRenderable(Uint32 id, GUIRenderer& guiRenderer,
		Ogre::ObjectMemoryManager* objManager, Ogre::SceneManager* sceneMgr)
		: MovableObject(id, objManager, sceneMgr, 0)
		, Renderable()
		, m_guiRenderer(guiRenderer)

		, m_sceneMgr(sceneMgr)
		, m_sceneNodeLines(0)
		, mOperationType(Ogre::OperationType::OT_TRIANGLE_LIST)

		, _initalizied(false)
	{
		createFontTexture();

		//set renderqueue -> opengl error bind buffer after adding item??
		sceneMgr->getRenderQueue()->setRenderQueueMode(7, Ogre::RenderQueue::Modes::FAST);
		this->setRenderQueueGroup(7);

		m_sceneNodeLines = sceneMgr->getRootSceneNode(Ogre::SCENE_DYNAMIC)->createChildSceneNode(Ogre::SCENE_DYNAMIC);
		m_sceneNodeLines->attachObject(this);

		Ogre::RenderSystem *renderSystem = m_guiRenderer.getGraphicsManager().getRoot()->getRenderSystem();
		m_VaoManager = renderSystem->getVaoManager();

		Ogre::Aabb aabb(Ogre::Aabb::BOX_INFINITE);
		mObjectData.mLocalAabb->setFromAabb(aabb, mObjectData.mIndex);
		mObjectData.mWorldAabb->setFromAabb(aabb, mObjectData.mIndex);
		mObjectData.mLocalRadius[mObjectData.mIndex] = std::numeric_limits<Ogre::Real>::max();
		mObjectData.mWorldRadius[mObjectData.mIndex] = std::numeric_limits<Ogre::Real>::max();

		// default overlays to preserve their own detail level
		mPolygonModeOverrideable = false;

		//>>>>>-------------- 2D --------------------
		// use identity projection and view matrices
	//	mUseIdentityProjection = true;
	//	mUseIdentityView = true;
		//<<<<<-------------- 2D --------------------
	}

	void ImgGuiRenderable::getRenderOperation(Ogre::v1::RenderOperation& op, bool casterPass) {
		OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED,
			"ImgGuiRenderable does not implement getRenderOperation. "
			"Use MovableObject::setRenderQueueGroup to change the group.",
			"ImgGuiRenderable::getRenderOperation");
	}

	void ImgGuiRenderable::updateVertices(float delta)
	{
		//return;

		ImGuiIO& io = ImGui::GetIO();
		io.DeltaTime = delta;
		// Setup display size (every frame to accommodate for window resizing)
		io.DisplaySize = ImVec2(800, 600);

		ImGui::NewFrame();

		bool show_test_window = true;
	
		ImGui::ShowTestWindow(&show_test_window);

		//Tell ImGui to create the buffers
		ImGui::Render();

		ImDrawData *draw_data = ImGui::GetDrawData();

		if (!draw_data)
			return;

		clear();

		Ogre::VertexElement2Vec vertexElements;
		vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT2, Ogre::VES_POSITION));
		vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES));
		vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_COLOUR, Ogre::VES_DIFFUSE));

		size_t maxVertices = 50000;
		size_t maxIndices = 50000;
		
		m_vertexBuffer = m_VaoManager->createVertexBuffer(vertexElements, maxVertices, Ogre::BT_DYNAMIC_PERSISTENT_COHERENT, 0, false);
		m_indexBuffer = m_VaoManager->createIndexBuffer(Ogre::IndexBufferPacked::IT_16BIT,	maxIndices,	Ogre::BT_DYNAMIC_DEFAULT, NULL, false);
		
		//Now the Vao
		Ogre::VertexBufferPackedVec vertexBuffers;
		vertexBuffers.push_back(m_vertexBuffer);
		m_Vao = m_VaoManager->createVertexArrayObject(vertexBuffers, m_indexBuffer, Ogre::OperationType::OT_TRIANGLE_LIST);
		mVaoPerLod[0].push_back(m_Vao);

		if (!_initalizied)
		{
			setDatablock("HlmsUnlitImgui"); // set this after  createVertexArrayObject  and mVaoPerLod[0].push_back(vao) ?? or else crash in renderable
			setCastShadows(false);

			mRenderables.push_back(this);
			_initalizied = true;
		}

		ImDrawVert* vtx_dst = (ImDrawVert*)(m_vertexBuffer->map(0, maxVertices));
		ImDrawIdx* idx_dst = (ImDrawIdx*)m_indexBuffer->map(0, maxIndices);
		
		//iterate through all lists (at the moment every window has its own)
		for (int n = 0; n < draw_data->CmdListsCount; n++)
		{			
			const ImDrawList* cmd_list = draw_data->CmdLists[n];

			memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
			memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));

			vtx_dst += cmd_list->VtxBuffer.size();
			idx_dst += cmd_list->IdxBuffer.size();
		}	

		m_vertexBuffer->unmap(Ogre::UO_UNMAP_ALL);
		m_indexBuffer->unmap(Ogre::UO_UNMAP_ALL);

		Ogre::Aabb aabb2(Ogre::Aabb::BOX_INFINITE);//2D
		mObjectData.mLocalAabb->setFromAabb(aabb2, mObjectData.mIndex); //2D
		mObjectData.mWorldAabb->setFromAabb(aabb2, mObjectData.mIndex); //2D
																		//mObjectData.mLocalAabb->setFromAabb(aabb, mObjectData.mIndex); //3D
																		//mObjectData.mLocalRadius[mObjectData.mIndex] = aabb.getRadius();//3D
		mObjectData.mLocalRadius[mObjectData.mIndex] = std::numeric_limits<Ogre::Real>::max();
		mObjectData.mWorldRadius[mObjectData.mIndex] = std::numeric_limits<Ogre::Real>::max();
	}

	void ImgGuiRenderable::clear()
	{
		if (!_initalizied)
			return;

		//clear aabb
		mObjectData.mLocalAabb->setFromAabb(Ogre::Aabb::BOX_NULL, mObjectData.mIndex);
		mObjectData.mLocalRadius[mObjectData.mIndex] = 0.0f;

		Ogre::VertexArrayObject *vao = m_Vao;

		if (vao)
		{
			Ogre::VaoManager *vaoManager = m_VaoManager;

			const Ogre::VertexBufferPackedVec &vertexBuffers = vao->getVertexBuffers();

			Ogre::VertexBufferPackedVec::const_iterator itBuffers = vertexBuffers.begin();
			Ogre::VertexBufferPackedVec::const_iterator endBuffers = vertexBuffers.end();

			while (itBuffers != endBuffers)
			{
				Ogre::VertexBufferPacked * vertexBuffer = *itBuffers;

				if (vertexBuffer->getMappingState() != Ogre::MS_UNMAPPED)
				{
					vertexBuffer->unmap(Ogre::UO_UNMAP_ALL);
				}

				vaoManager->destroyVertexBuffer(vertexBuffer);

				++itBuffers;
			}

			Ogre::IndexBufferPacked * indexBuffer = vao->getIndexBuffer();

			if (indexBuffer)
			{
				if (indexBuffer->getMappingState() != Ogre::MS_UNMAPPED)
				{
					indexBuffer->unmap(Ogre::UO_UNMAP_ALL);
				}

				vaoManager->destroyIndexBuffer(indexBuffer);
			}

			vaoManager->destroyVertexArrayObject(vao);
		}

		m_Vao = 0;
		mVaoPerLod[0].clear();
		mVaoPerLod[1].clear();
	}

	ImgGuiRenderable::~ImgGuiRenderable()
	{
		//m_sceneMgr->destroyManualObject(this);
		m_sceneMgr->destroySceneNode(m_sceneNodeLines);

	}

	const Ogre::String& ImgGuiRenderable::getMovableType(void) const
	{
		return "ImgGUI";
	}

	void ImgGuiRenderable::createFontTexture()
	{
		// Build texture atlas
		ImGuiIO& io = ImGui::GetIO();
		unsigned char* pixels;
		int width, height;
		io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);

		mFontTex = Ogre::TextureManager::getSingleton().createManual("ImguiFontTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, width, height, 1, 1, Ogre::PF_R8G8B8A8);

		const Ogre::PixelBox & lockBox = mFontTex->getBuffer()->lock(Ogre::Image::Box(0, 0, width, height), Ogre::v1::HardwareBuffer::HBL_DISCARD);
		size_t texDepth = Ogre::PixelUtil::getNumElemBytes(lockBox.format);

		memcpy(lockBox.data, pixels, width*height*texDepth);
		mFontTex->getBuffer()->unlock();
	}
}
header:

Code: Select all

#pragma once


#include <XESystem/SystemConfig.hpp>
//#include <Ogre/OgreMain/include/OgreManualObject2.h>
#include <Ogre/OgreMain/include/OgreMovableObject.h>
#include <Ogre/OgreMain/include/OgreRenderable.h>
#include <OgreTexture.h>

//Ogre::v1
#include <Ogre/OgreMain/include/OgreRenderOperation.h>

#include <vector>
#include <memory>

namespace Ogre {
	class VertexBufferPacked;
	class ObjectMemoryManager;
	class SceneManager;

	typedef std::string String;
}

namespace XE {

	struct Vertex;
	class CameraRenderable;
	class GUIRenderer;
	class RenderableShape;

	class ImgGuiRenderable : public Ogre::MovableObject, public Ogre::Renderable
	{
	public:

		ImgGuiRenderable(Uint32 id, GUIRenderer& guiRenderer,
			Ogre::ObjectMemoryManager* objManager, Ogre::SceneManager* sceneMgr);


		~ImgGuiRenderable();

		// MovableObject overrides
		/** @copydoc MovableObject::getMovableType. */
		const Ogre::String& getMovableType(void) const;

		void updateVertices(float delta);

		// Renderable overrides
		/** @copydoc Renderable::getRenderOperation. */
		virtual void getRenderOperation(Ogre::v1::RenderOperation& op, bool casterPass) OGRE_OVERRIDE;

		/** @copydoc Renderable::getWorldTransforms. */
		virtual void getWorldTransforms(Ogre::Matrix4* xform) const OGRE_OVERRIDE {}
		/** @copydoc Renderable::getLights. */
		virtual const Ogre::LightList &getLights(void) const OGRE_OVERRIDE { return queryLights(); }
		/** @copydoc Renderable::getCastsShadows. */
		virtual bool getCastsShadows(void) const { return false; }


	protected:
		//called from Ogre::Renderable
		Ogre::OperationType mOperationType;

	private:

		void createFontTexture();

		void clear();

		bool _initalizied;
		Ogre::SceneManager* _t_OgreSceneMgrPtr;
		Ogre::ObjectMemoryManager* _t_objectMemoryManager;

		Ogre::VertexArrayObject * m_Vao;
		Ogre::VaoManager * m_VaoManager;
		Ogre::VertexElement2Vec m_VertexElements;

		Ogre::VertexBufferPacked *m_vertexBuffer;
		Ogre::IndexBufferPacked* m_indexBuffer;

		GUIRenderer& m_guiRenderer;

		Ogre::SceneManager* m_sceneMgr;
		Ogre::SceneNode* m_sceneNodeLines;


		Ogre::TexturePtr mFontTex;
	};
}
material:

Code: Select all

hlms HlmsUnlitImgui unlit
{
	diffuse_map			ImguiFontTex		
	scene_blend			alpha_blend
	depth_check			off
	depth_write			off
	cull_mode none 
}
My little OGRE engine -> FrankE WIP
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by dark_sylinc »

To answer your question: You can't set a projection matrix per MovableObject anymore (unless you write your own Hlms implementation).

To solve your problem:
1. Call MovableObject::setUseIdentityProjection( true );
2. Make sure you're using an Unlit datablock (it seems you're already doing that).
3. If you still require a custom projection matrix (and assuming you can use the same proj matrix for every MovableObject), do not call MovableObject::setUseIdentityProjection( true ); and put all UI-related MovableObjects in its own RenderQueue ID (e.g. let's say RQ ID 250) via MovableObject::setRenderQueueGroup; and then prepare a render_scene pass that only draws this ID. You have two ways:

Way #1

Code: Select all

//Render everything but the UI
pass render_scene
{
    rq_first 0
    rq_last 250
}
//Render UI
pass render_scene
{
    //Arbitrary number we'll use to identify this pass in C++ code.
    identifier 10010
    rq_first 250
    rq_last 255
}
And register a CompositorWorkspaceListener (via CompositorWorkspace::setListener).
Overload CompositorWorkspaceListener::passPreExecute and look for pass->getDefinition()->mIdentifier == 10010.
When that hits, change the camera's projection matrix to a custom one via Camera::setCustomProjectionMatrix.

Way #2

Code: Select all

//Render everything but the UI
pass render_scene
{
    rq_first 0
    rq_last 250
}
//Render UI
pass render_scene
{
    camera ui_my_camera_name
    rq_first 250
    rq_last 255
}
This method is similar, but instead of using a CompositorWorkspaceListener, it uses two cameras. Before initializing the workspace, create a second camera named "ui_my_camera_name"; and set that camera's projection matrix to whatever you want.

Hopefully that will do.

Cheers
Matias
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

dark_sylinc wrote:To answer your question: You can't set a projection matrix per MovableObject anymore (unless you write your own Hlms implementation).
Sounds like you're not planning to add this possibilty into the current Hlms implementation... :wink:
My little OGRE engine -> FrankE WIP
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by dark_sylinc »

No. This feature is rarely used and rarely needed, and adding it makes everything and everyone pay the price (requires 64 bytes extra per MovableObject; requires Unlit following alternate codepaths, etc)
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

Thanks matias!
I've tried the listener and the projection seems to work.
But if i move the camera the vertices are clipped?
Image

Code: Select all

		void ImGuiCompositorWorkspaceListener::passPreExecute(Ogre::CompositorPass *pass) {
		
			if (pass->getDefinition()->mIdentifier == 10010)
			{
				Ogre::Matrix4 projMatrix(2.0f / 800, 0.0f, 0.0f, -1.0f,
					0.0f, -2.0f / 600, 0.0f, 1.0f,
					0.0f, 0.0f, -1.0f, 0.0f,
					0.0f, 0.0f, 0.0f, 1.0f);
				
				m_camera->setCustomProjectionMatrix(true, projMatrix);
			}
			else
			{
				m_camera->setCustomProjectionMatrix(false);
			}
		}
Not projectionmatrix related, but it looks like i cannot use the generated fonttexture in hlms materials?
The texture is not found and displayed only white, but exists in the texturemanager. It's 100% chaos creators generation code so the texture must be correct...
Every other texture used from filesystem works.
Do i need to set something special for hlms diffuse texture?

Code: Select all

"HlmsUnlitImgui" :
		{
			"macroblock" : "Macroblock_5",
			"blendblock" : "Blendblock_1",
			"shadow_const_bias" : 0.01,
			"diffuse_map0" :
			{
				"texture" : "ImguiFontTex",
				"sampler" : "Sampler_4"
			}
		}
My little OGRE engine -> FrankE WIP
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by dark_sylinc »

Hi,

When loading from JSON, Ogre will use the HlmsTextureManager (which is a texture manager built on top of the regular TextureManager); thus it won't see the font texture living in TextureManager.
You can set it manually from C++ though (I know it's a hassle though, that needs improving)
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

Well, i'm still sticking with the clipping problem while camera rotation.

Any Idea?

Image
My little OGRE engine -> FrankE WIP
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

i've attached the movable object to the camera just4fun and the display works, but it's flickering...
this method was removed?

Code: Select all

//render the object
			mSceneMgr->_injectRenderWithPass(mPass, mRenderables[i], 0, false, false);
My little OGRE engine -> FrankE WIP
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by devxkh »

well, after struggling for some days with this shit and nothing worked even with nasty hacks or huge workarounds, i've decided to add the ability to a renderable.
My pull request: https://bitbucket.org/sinbad/ogre/pull- ... mment-None

The only overhead to the current version is a simple if!

Code: Select all

if (useCustomProjectionMatrix)
Hopefully you'll accept the pullrequest, since it makes it a lot more easier to set the projectionmatrix for a renderable.
My little OGRE engine -> FrankE WIP
Lax
Hobgoblin
Posts: 583
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 50

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by Lax »

I agree with devxkh, at the moment its no possible e.g. to render stuff like a selection rectangle correctly on screen. I think such things are important.

Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

farrer
Halfling
Posts: 64
Joined: Mon Sep 12, 2011 7:35 pm
x 13

Re: [2.1] How to set projectionMatrix in a MovableObject?

Post by farrer »

As you seem to be just rendering to a 2d screen space, its much more easer to set to use the identity world matrix and set the coordinates to be inner the [-1,1] coordinates space.

Anyway, from the pictures you show, I would guess that the clipping is due to some overlap with the camera's near clip plane. Had you tried to reset that?
Post Reply