UBrowser and Irrlicht Integration
UBrowser and Irrlicht Integration
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.
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.
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;
}
To get the above code compiled, you have to change the Irrlicht engine a little bit:
Add the following to IBillboardSceneNode.h:
Add the following to CBillboardSceneNode.h:
Add the following to CBillboardSceneNode.cpp:
Or if you don't want to hack up the Irrlicht engine:
you may replace to following line in the last post:
with the following
You may need some minor change to get the code compiled.
Add the following to IBillboardSceneNode.h:
Code: Select all
virtual video::S3DVertex* getVertices() = 0;
Code: Select all
virtual video::S3DVertex* getVertices();
Code: Select all
video::S3DVertex* CBillboardSceneNode::getVertices()
{
return vertices;
}
you may replace to following line in the last post:
Code: Select all
irr::video::S3DVertex* vertices = node->getVertices();
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;
For ubrowser related information, please refer to this post:
http://irrlicht.sourceforge.net/phpBB2/ ... t=ubrowser
http://irrlicht.sourceforge.net/phpBB2/ ... t=ubrowser
Nice
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
-
- Posts: 49
- Joined: Tue Jan 23, 2007 12:36 pm
- Location: Bedford, UK
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
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
-
- Posts: 49
- Joined: Tue Jan 23, 2007 12:36 pm
- Location: Bedford, UK
You can download it from here.
<a href="http://www.gigasize.com/get.php?d=qp03jwbfsmd"> http://www.gigasize.com/get.php?d=qp03jwbfsmd</a>
<a href="http://www.gigasize.com/get.php?d=qp03jwbfsmd"> http://www.gigasize.com/get.php?d=qp03jwbfsmd</a>
Sorry, that link is borken. Try
http://www.gigasize.com/get.php?d=qp03jwbfsmd
http://www.gigasize.com/get.php?d=qp03jwbfsmd
-
- Posts: 49
- Joined: Tue Jan 23, 2007 12:36 pm
- Location: Bedford, UK