UBrowser and Irrlicht Integration

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

UBrowser and Irrlicht Integration

Post by dude3d »

I am working on integrating ubrowser with Irrlicht and I have made quite some progress. I am able to embed the ubrowser into a billboard scene node and make the browsing part working. I am able to send emails through the embedded browser. So far so good. But I run on two problems:

1) There are some memory leaks detected by my IDE that do not make sense to me. The testgl app coming with ubrowser is using the same logic handling memory management but IDE does not report memory leak. I don't know why the memory leak is happening in Irrlicht integration. I tracked down the memory allocation. The leak seams happening in LLEmbeddedBrowserWindow of which the constructor is called but the destructor is not called. The thing that puzzled me is that testgl is doing the same thing but the IDE never complained.

2) The image quality of ubrowser in Irrlicht is not as good as that in testgl. I chose to use ETCF_OPTIMIZED_FOR_QUALITY when the texture is created from the screen grab of FireFox. I did not see other ways to improve the texture quality.

The code is usable now except the memory leak thing.

I am going to post the code below in case anybody wants to use it or has any idea to fix the two problem.
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

Ubrowser and Irrlicht Integration Code:

Code: Select all

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Callum Prentice (callum@ubrowser.com) code.
 *
 * The Initial Developer of the Original Code is:
 *   Callum Prentice (callum@ubrowser.com)
 *
 * Portions created by the Initial Developer are Copyright (C) 2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *  Callum Prentice (callum@ubrowser.com)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include "Irrlicht.h"
#include "llmozlib.h"
#include <iostream>
//#include "vld.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
//
class irrEmbeddedBrowser :
	public LLEmbeddedBrowserWindowObserver, public irr::IEventReceiver
{
	public:
		irrEmbeddedBrowser( char* arg0, irr::video::IVideoDriver *irr_video_driver, irr::IrrlichtDevice* irr_device ) : 
			mIrrVideoDriver( irr_video_driver ),
			mIrrDevice( irr_device ),
			mBrowserWindowWidth( 1024 ),	// width & height must be powers of 2 in this demo
			mBrowserWindowHeight ( 1024 ),	// until i figure out how to texture scale to fill poly
			mNeedsUpdate( false )
	{
		// configure textures
		mIrrVideoDriver->setTextureCreationFlag( irr::video::ETCF_CREATE_MIP_MAPS, false );

		mIrrVideoDriver->setTextureCreationFlag( irr::video::ETCF_OPTIMIZED_FOR_QUALITY, true );
//		mIrrVideoDriver->setTextureCreationFlag( irr::video::ETCF_ALWAYS_32_BIT, true );

		// need a native window handle to pass to Mozilla - Irrlicht can give it to us..
		void* native_window_handle = (void*)mIrrVideoDriver->getExposedVideoData().OpenGLWin32.HWnd;

		// initialize, set up profile and open a browser window
		std::string profileBaseDir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") );
		std::string profileName( "irrlichtProfile" );
		LLMozLib::getInstance()->init( profileBaseDir, profileName );
		mBrowserWindowId = LLMozLib::getInstance()->createBrowserWindow( native_window_handle, mBrowserWindowWidth, mBrowserWindowHeight );

		// tell LLMozLib about the size of the browser window
		LLMozLib::getInstance()->setSize( mBrowserWindowId, mBrowserWindowWidth, mBrowserWindowHeight );

		// observer events that LLMozLib emits
		LLMozLib::getInstance()->addObserver( mBrowserWindowId, this );

		// got to the home page
		LLMozLib::getInstance()->navigateTo( mBrowserWindowId, "http://www.google.com" );

		// extremely sad hack - need to wait for browser surface to become valid
		// fixed in most recent version of LLMozLib which will be released RSN
		const unsigned char* pixels = LLMozLib::getInstance()->grabBrowserWindow( mBrowserWindowId );
		while( ! pixels )
		{
			pixels = LLMozLib::getInstance()->grabBrowserWindow( mBrowserWindowId );
			mIrrDevice->run();
		};

		// make an image
		mIrrImage = mIrrVideoDriver->createImageFromData( irr::video::ECF_A8R8G8B8,
					irr::core::dimension2d< irr::s32 >( mBrowserWindowWidth, mBrowserWindowHeight ),
					(void*)pixels,
					true);

		// texture management
		mIrrTexture = mIrrVideoDriver->addTexture( "LLMozLib", mIrrImage );


		/*
		// add a cube to display the texture
		irr::scene::ISceneNode* node = mIrrDevice->getSceneManager()->addCubeSceneNode( 100 );
		node->setPosition( irr::core::vector3df( 0,0,0 ) );
		node->setMaterialTexture( 0, mIrrTexture );
		node->setMaterialFlag( irr::video::EMF_LIGHTING, false );
		irr::scene::ISceneNodeAnimator* anim = mIrrDevice->getSceneManager()->createRotationAnimator( irr::core::vector3df( 0.1f, 0, 0.13f ) );
		node->addAnimator( anim );
		anim->drop();
		*/

		node = mIrrDevice->getSceneManager()->addBillboardSceneNode(
			mIrrDevice->getSceneManager()->getRootSceneNode(), irr::core::dimension2d<irr::f32>(mBrowserWindowWidth, mBrowserWindowHeight),
			irr::core::vector3df(0, 0, 0), 202);
		node->setPosition( irr::core::vector3df( 0,0,0 ) );
		node->setMaterialTexture( 0, mIrrTexture );
		node->setMaterialFlag( irr::video::EMF_LIGHTING, false );

	};

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	~irrEmbeddedBrowser()
	{
		LLMozLib::getInstance()->remObserver( mBrowserWindowId, this );

		LLMozLib::getInstance()->destroyBrowserWindow( mBrowserWindowId );

		LLMozLib::getInstance()->reset();
		LLMozLib::destroy();
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	bool update()
	{
		// something changed on the page so it needs to be updated
		if ( mNeedsUpdate )
		{
			// lock
			irr::s32* texture = (irr::s32*)mIrrTexture->lock();
			irr::s32* image = (irr::s32*)mIrrImage->lock();

			// grab the page 
			LLMozLib::getInstance()->grabBrowserWindow( mBrowserWindowId );
	
			// copy it from the image to the texture
			memcpy( texture, image, LLMozLib::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLMozLib::getInstance()->getBrowserHeight( mBrowserWindowId ) );

			// flag that we updated it
			mNeedsUpdate = false;

			// unlock 
			mIrrTexture->unlock();
			mIrrImage->unlock();
		};

		return true;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	void navigateTo( std::string url )
	{
		LLMozLib::getInstance()->navigateTo( mBrowserWindowId, url );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	void onPageChanged( const EventType& eventIn )
	{
		// flag that an update is required - page grab happens in idle() so we don't stall
		mNeedsUpdate = true;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onNavigateBegin( const EventType& eventIn )
	{
		std::cout << "Event: begin navigation to " << eventIn.getEventUri() << std::endl;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onNavigateComplete( const EventType& eventIn )
	{
		std::cout << "Event: end navigation to " << eventIn.getEventUri() << " with response status of " << eventIn.getIntValue() << std::endl;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onUpdateProgress( const EventType& eventIn )
	{
		std::cout << "Event: progress value updated to " << eventIn.getIntValue() << std::endl;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onStatusTextChange( const EventType& eventIn )
	{
		std::cout << "Event: status updated to " << eventIn.getStringValue() << std::endl;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onLocationChange( const EventType& eventIn )
	{
		std::cout << "Event: location changed to " << eventIn.getStringValue() << std::endl;
	};

	////////////////////////////////////////////////////////////////////////////////
	// virtual
	void onClickLinkHref( const EventType& eventIn )
	{
		std::cout << "Event: clicked on link to " << eventIn.getStringValue() << std::endl;
	};

	virtual bool OnEvent( irr::SEvent event )
	{
		if ( event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown == false )
		{
			if ( event.KeyInput.Key == '0' )
				navigateTo( "http://www.google.com" );

			if ( event.KeyInput.Key == '1' )
				navigateTo( "http://www.irrlicht3d.org/" );

			if ( event.KeyInput.Key == '2' )
				navigateTo( "http://news.google.com" );

			if ( event.KeyInput.Key == '3' )
				navigateTo( "http://www.flickr.com/explore/interesting/7days/" );

			if ( event.KeyInput.Key == '4' )
				navigateTo( "http://www.faser.net/mab/chrome/content/mab.xul" );

			if ( event.KeyInput.Key == '5' )
				navigateTo( "http://developer.yahoo.com/yui/examples/slider/rgb2.html?mode=dist" );

			if ( event.KeyInput.Key == 27 )
				mIrrDevice->closeDevice();
		}else if(event.EventType == irr::EET_MOUSE_INPUT_EVENT)
		{
			irr::video::S3DVertex* vertices = node->getVertices();
			irr::core::position2d<irr::s32> positions[4];

			irr::s32 xStart = 0;
			irr::s32 xEnd = 0;
			irr::s32 yStart = 0;
			irr::s32 yEnd = 0;
			for(irr::s32 i = 0; i < 4; i++)
			{
				positions[i] = mIrrDevice->getSceneManager()->getSceneCollisionManager()
					->getScreenCoordinatesFrom3DPosition(vertices[i].Pos, 
					mIrrDevice->getSceneManager()->getActiveCamera());
				if(i == 0)
				{
					xStart = positions[i].X;
					xEnd = positions[i].X;
					yStart = positions[i].Y;
					yEnd = positions[i].Y;
				}else{
					if(positions[i].X >= xEnd)
					{
						xEnd = positions[i].X;
					}
					if(positions[i].Y <= xStart){
						xStart = positions[i].X;
					}

					if(positions[i].Y >= yEnd)
					{
						yEnd = positions[i].Y;
					}
					if(positions[i].Y < yStart){
						yStart = positions[i].Y;
					}
				}
			}
			// texture is scaled to fit the screen so we scale mouse coords in the same way
			irr::s32 xIn = (event.MouseInput.X - xStart + 0.0f) / (xEnd - xStart) 
				* mBrowserWindowWidth;
			irr::s32 yIn = (event.MouseInput.Y - yStart + 0.0f) / (yEnd - yStart)
				* mBrowserWindowHeight;

			if(event.MouseInput.Event == irr::EMIE_LMOUSE_PRESSED_DOWN)
			{
				// send event to LLMozLib
				LLMozLib::getInstance()->mouseDown( mBrowserWindowId, xIn, yIn );
			}else if(event.MouseInput.Event == irr::EMIE_LMOUSE_LEFT_UP)
			{
				// send event to LLMozLib
				LLMozLib::getInstance()->mouseUp( mBrowserWindowId, xIn, yIn );

				// this seems better than sending focus on mouse down (still need to improve this)
				LLMozLib::getInstance()->focusBrowser( mBrowserWindowId, true );
			}else if(event.MouseInput.Event == irr::EMIE_MOUSE_MOVED){

				// send event to LLMozLib
				LLMozLib::getInstance()->mouseMove( mBrowserWindowId, xIn, yIn );
			}
		}

		return false;
	};

	private:
		int mBrowserWindowId;
		int mBrowserWindowWidth;
		int mBrowserWindowHeight;
		bool mNeedsUpdate;
		irr::video::IVideoDriver *mIrrVideoDriver;
		irr::video::IImage *mIrrImage;
		irr::video::ITexture *mIrrTexture;
		irr::IrrlichtDevice *mIrrDevice;
		irr::scene::IBillboardSceneNode* node;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
//
int main( int argc, char *argv[] )
{
	irr::IrrlichtDevice *theDevice = irr::createDevice( irr::video::EDT_OPENGL, irr::core::dimension2d< irr::s32 >( 800, 800 ), 32, false, false, false, 0 );

	theDevice->setWindowCaption( L"irrLicht and LLMozlib" );

    irr::video::IVideoDriver* driver = theDevice->getVideoDriver();

    irrEmbeddedBrowser* theEmbeddedBrowser = new irrEmbeddedBrowser( argv[0], driver, theDevice );

	theDevice->setEventReceiver(theEmbeddedBrowser);
	
	
	irr::scene::ICameraSceneNode* cam = theDevice->getSceneManager()->addCameraSceneNode( 0, irr::core::vector3df( -100, -700, 100 ), irr::core::vector3df( 0, 0, 0 ) );
	
	/*
	irr::scene::ICameraSceneNode* cam = theDevice->getSceneManager()->addCameraSceneNodeFPS( 0, 100, 400, -1);
	cam->setPosition(irr::core::vector3df( -100, 50, 100 ));
	cam->setTarget(irr::core::vector3df( 0, 0, 0 ) );
	*/

    while ( theDevice->run() )
    {
		if(theDevice->isWindowActive()){
			driver->beginScene( true, true, irr::video::SColor( 0xff, 0xa0, 0xa0, 0xc0 ) );

			theDevice->getSceneManager()->drawAll();

			theEmbeddedBrowser->update();

			driver->endScene();

			irr::core::stringw str = L"  FPS: ";
			str += driver->getFPS();
			theDevice->setWindowCaption(str.c_str());
		}

    }

	delete theEmbeddedBrowser;
	//cam->drop();
    theDevice->drop();

    return 0;
}
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

To get the above code compiled, you have to change the Irrlicht engine a little bit:

Add the following to IBillboardSceneNode.h:

Code: Select all

	virtual video::S3DVertex* getVertices() = 0;
Add the following to CBillboardSceneNode.h:

Code: Select all

	virtual video::S3DVertex* getVertices();
Add the following to CBillboardSceneNode.cpp:

Code: Select all

video::S3DVertex* CBillboardSceneNode::getVertices()
{
	return vertices;
}
Or if you don't want to hack up the Irrlicht engine:

you may replace to following line in the last post:

Code: Select all

			irr::video::S3DVertex* vertices = node->getVertices();
with the following

Code: Select all


	video::S3DVertex vertices[4];

	core::vector3df pos = node->getAbsolutePosition();

	core::vector3df campos = camera->getAbsolutePosition();
	core::vector3df target = camera->getTarget();
	core::vector3df up = camera->getUpVector();
	core::vector3df view = target - campos;
	view.normalize();

	core::vector3df horizontal = up.crossProduct(view);
	if ( horizontal.getLength() == 0 )
	{
		horizontal.set(up.Y,up.X,up.Z);
	}
	horizontal.normalize();
	horizontal *= 0.5f * Size.Width;

	core::vector3df vertical = horizontal.crossProduct(view);
	vertical.normalize();
	vertical *= 0.5f * Size.Height;

	view *= -1.0f;

	for (s32 i=0; i<4; ++i)
		vertices[i].Normal = view;

	vertices[0].Pos = pos + horizontal + vertical;
	vertices[1].Pos = pos + horizontal - vertical;
	vertices[2].Pos = pos - horizontal - vertical;
	vertices[3].Pos = pos - horizontal + vertical;

You may need some minor change to get the code compiled.
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

For ubrowser related information, please refer to this post:


http://irrlicht.sourceforge.net/phpBB2/ ... t=ubrowser
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Nice
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Bob Finnie
Posts: 49
Joined: Tue Jan 23, 2007 12:36 pm
Location: Bedford, UK

Post by Bob Finnie »

Has anyone got this up and running?
I seem to have serious problems with the LLMozLib libs/build.

Does anyone have a copy of the lib/h files that will run with VS 2005 (VC++8).. they could share?
I've tried the instructions on the other thread - I have tried downloading the alternative VS2005 libs but to no avail.

I can compile and link it now however I'm getting run time errors in MSVCR80.dll and all sorts of other crap..

I think I may have mismatched dlls/libs etc,.

Can anyone help?

Thanks for your time...

Bob
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

I have the lib/h, dll and etc for vsc++ 2005. How do you want to get it? I can email it to you if you like.
Bob Finnie
Posts: 49
Joined: Tue Jan 23, 2007 12:36 pm
Location: Bedford, UK

Post by Bob Finnie »

Yeah - that would be great dude3d. My email is bobfinnie at googlemail dot com.

Many thanks for that
Kudos to you
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

Bob, check your email. I just sent the zip to you.
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

Damn. Google blocked my email saying that the zip contains executable files, the DLLs.
dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

dude3d
Posts: 25
Joined: Thu Sep 06, 2007 3:45 am

Post by dude3d »

Bob Finnie
Posts: 49
Joined: Tue Jan 23, 2007 12:36 pm
Location: Bedford, UK

Post by Bob Finnie »

Thanks dude - Downloaded OK.

much kudos
khenissi
Posts: 11
Joined: Mon Jun 06, 2011 10:44 am

Post by khenissi »

I tried the solution of dude3d but I have a problem with llmozlib
I added #include "llmozlib.h" in include folder but there is still a problem
this is the error: undefined reference to `LLMozLib::getInstance()'
my IDE is code Blocks
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, you need to link the library of course. This holds true for all IDEs.
Post Reply