Embedding ogre in firefox

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
Post Reply
dudeabot
Gnome
Posts: 334
Joined: Thu Jun 28, 2007 2:12 pm
Location: Brazil
x 5
Contact:

Embedding ogre in firefox

Post by dudeabot »

hello, last day i did some testings trying to embed ogre3d on firefox, most of the step by step i got from

http://www.codeproject.com/KB/openGL/FirefoxOpenGL

so lets quote it a bit:
You will first need to download Gecko plugin API and Firefox source code. Download Gecko SDK and extract to \yourroot\gecko-sdk\.

Download Firefox source code from here, extract to \yourroot\mozilla.
Then we start from a basic plugin sample. Go to the folder: yourroot\mozilla\modules\plugin\tools\sdk\samples\basic\windows.



Here's a little trick, we need to run unix2dos on npbasic.dsp and npbasic.dsw under this folder. Then we open and cover the project by Visual C++ Express, we will be successful now. From project properties, change the Additional include directories to yourroot\gecko-sdk\include; yourroot\mozilla\modules\plugin\tools\sdk\samples\include. Try to build now, if successful, we continue...
NOTE: well i prefer just open on wordpad, press enter and save it :P
updated download links:
http://developer.mozilla.org/en/docs/Gecko_SDK
ftp://ftp.mozilla.org/pub/mozilla.org/f ... ce.tar.bz2 (this is for 3.0, doh =P)

ok so lets make some changes to the plugin.cpp file (this is heavily based on embbeded aplication on playpen)

you can download the code http://gp.leveldesign.com.br/plugin.rar (i havent put basic.rc because mine is slightly modified - use the one that comes with the example. Also make sure you correct the library and include paths on project seetings to your ogre folder)

Code: Select all

#include <windows.h>
#include <windowsx.h>
#include "plugin.h"

#include "Ogre.h"
#include "OgreCgPlugin.h"
#include "OgreD3D9Plugin.h"

static LRESULT CALLBACK PluginWinProc(HWND, UINT, WPARAM, LPARAM);
static WNDPROC lpOldProc = NULL;

using namespace Ogre;
//using namespace OIS;

HWND mhWnd=0;
RenderWindow* renderWindow=0;
bool winActive = false;
bool winSizing = false;

static LRESULT CALLBACK PluginWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_CREATE)
	{
		return 0;
	}

	if (!renderWindow)
		return DefWindowProc(hWnd, message, wParam, lParam);
	switch( message )
	{
	case WM_ACTIVATE:
		winActive = (LOWORD(wParam) != WA_INACTIVE);
		break;

	case WM_ENTERSIZEMOVE:
		winSizing = true;
		break;

	case WM_EXITSIZEMOVE:
		renderWindow->windowMovedOrResized();
		renderWindow->update();
		winSizing = false;
		break;

	case WM_MOVE:
	case WM_SIZE:
		if (!winSizing)
			renderWindow->windowMovedOrResized();
		break;

	case WM_GETMINMAXINFO:
		// Prevent the window from going smaller than some min size
		((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
		((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
		break;

	case WM_CLOSE:
		renderWindow->destroy(); // cleanup and call DestroyWindow
		PostQuitMessage(0); 
		return 0;
	case WM_PAINT:
		if (!winSizing)
		{
			renderWindow->update();
			return 0;
		}
		break;
	}
	return DefWindowProc( hWnd, message, wParam, lParam );
}


NPError NS_PluginInitialize()
{
	return NPERR_NO_ERROR;
}

void NS_PluginShutdown()
{
}

/////////////////////////////////////////////////////////////
//
// construction and destruction of our plugin instance object
//
nsPluginInstanceBase * NS_NewPluginInstance(nsPluginCreateData * aCreateDataStruct)
{
	if(!aCreateDataStruct)
		return NULL;

	nsPluginInstance * plugin = new nsPluginInstance(aCreateDataStruct->instance);
	return plugin;
}

void NS_DestroyPluginInstance(nsPluginInstanceBase * aPlugin)
{
	if(aPlugin)
		delete (nsPluginInstance *)aPlugin;
}

////////////////////////////////////////
//
// nsPluginInstance class implementation
//
nsPluginInstance::nsPluginInstance(NPP aInstance) : nsPluginInstanceBase(),
mInstance(aInstance),
mInitialized(FALSE)
{
	mhWnd = NULL;
}

nsPluginInstance::~nsPluginInstance()
{
}

void setupResources(void)
{
	// Load resource paths from config file
	ConfigFile cf;
	cf.load("resources.cfg");

	// Go through all sections & settings in the file
	ConfigFile::SectionIterator seci = cf.getSectionIterator();

	String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		ConfigFile::SettingsMultiMap *settings = seci.getNext();
		ConfigFile::SettingsMultiMap::iterator i;
		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			archName = i->second;
			ResourceGroupManager::getSingleton().addResourceLocation(
				archName, typeName, secName);
		}
	}
}


NPBool nsPluginInstance::init(NPWindow* aWindow)
{
	if(aWindow == NULL)
		return FALSE;

	mhWnd = (HWND)aWindow->window;
	if(mhWnd == NULL)
		return FALSE;

	D3D9Plugin* mD3D9Plugin = new D3D9Plugin();
	CgPlugin* mCgPlugin = new CgPlugin();
	try{
		//we add EnableOpenGL and SetTimer 
		Root root("", "");
   		root.installPlugin(mD3D9Plugin);
   		root.installPlugin(mCgPlugin);

		// select first renderer & init with no window
		root.setRenderSystem(*(root.getAvailableRenderers()->begin()));
		root.initialise(false);

		// create first window manually
		NameValuePairList options;
		options["parentWindowHandle"] = 
			StringConverter::toString((size_t)mhWnd);

		renderWindow = root.createRenderWindow("embedded", 800, 600, false, &options);

		setupResources();
		ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

		SceneManager *scene = root.createSceneManager(Ogre::ST_GENERIC, "default");


		Camera *cam = scene->createCamera("cam");

		Viewport* vp = renderWindow->addViewport(cam);
		vp->setBackgroundColour(Ogre::ColourValue(0.5, 0.5, 0.7));
		cam->setAutoAspectRatio(true);
		cam->setPosition(0,0,300);
		cam->setDirection(0,0,-1);

		Entity* e = scene->createEntity("1", "ogrehead.mesh");
		scene->getRootSceneNode()->createChildSceneNode()->attachObject(e);
		Light* l = scene->createLight("l");
		l->setPosition(300, 100, -100);

		/*LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");*/

		

		// subclass window so we can intercept window messages and
		// do our drawing to it
		lpOldProc = SubclassWindow(mhWnd, (WNDPROC)PluginWinProc);

		// associate window with our nsPluginInstance object so we can access 
		// it in the window procedure
		SetWindowLong(mhWnd, GWL_USERDATA, (LONG)this);

		//OIS::InputManager* mInputManager;
		//OIS::ParamList pl;
		//size_t windowHnd = 0;
		//std::ostringstream windowHndStr;

		//renderWindow->getCustomAttribute("WINDOW", &windowHnd);
		//windowHndStr << (size_t)windowHnd;
		//pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

		//LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");

		////OIS Input devices
		//OIS::Keyboard* mKeyboard;

		//mInputManager = OIS::InputManager::createInputSystem( pl );
		////OIS::Mouse*    mMouse;

		//LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");

		////Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse)
		////mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, false ));
		//mKeyboard = (OIS::Keyboard*)mInputManager->createInputObject( OIS::OISKeyboard, false );
		////mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));
		
		// subclass window so we can intercept window messages and
		// do our drawing to it
		lpOldProc = SubclassWindow(mhWnd, (WNDPROC)PluginWinProc);

		// associate window with our nsPluginInstance object so we can access 
		// it in the window procedure
		SetWindowLong(mhWnd, GWL_USERDATA, (LONG)this);
		SetTimer(mhWnd,             // handle to main window 
			0,						 // timer identifier 
			1,						 // 10-second interval 
			(TIMERPROC) NULL);		 // no timer callback 		
		mInitialized = TRUE;

		// message loop
		MSG msg;
		while(GetMessage(&msg, NULL, 0, 0 ) != 0)
		{ 
			//mKeyboard->capture();
			TranslateMessage(&msg); 
			DispatchMessage(&msg); 
		} 
	}
	catch( Ogre::Exception& e ) 
	{
		MessageBox( NULL, e.getFullDescription().c_str(), 
			"An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

	}
	delete mCgPlugin;
	delete mD3D9Plugin;

	return TRUE;
}

void nsPluginInstance::shut()
{
	// subclass it back
	SubclassWindow(mhWnd, lpOldProc);
	mhWnd = NULL;
	mInitialized = FALSE;
	
}

NPBool nsPluginInstance::isInitialized()
{
	return mInitialized;
}

const char * nsPluginInstance::getVersion()
{
	return NPN_UserAgent(mInstance);
}
now compile it (you should link statically against ogre, renders, etc)

Test the plugin

Copy npbasic.dll to C:\Program Files\Mozilla Firefox\plugins\ or yourfolder\Mozilla Firefox\plugins\.
From the folder yourroot\mozilla\modules\plugin\tools\sdk\samples\basic\, you will find test.html, double click

Another way to test the plugin

If we open a file of the type that a plugin is registered, then the plugin will be triggered. Open basic.rc with a text editor, find the string "FileExtents" and change the value to whatever you want. I left it as .bic, the default value.

Image
beatiful :D



PROBLEMS:
1)when i close the firefox tab or window, that .dll isnt unloaded, i still dunno why, you will have to close it from task bar probably
2)Having problems to link with OIS.
3) if you have problem compiling:

in the header file npplat.h

move the block:

#ifdef XP_WIN
#include "windows.h"
#endif //XP_WIN

to the top, not the exact top, but comes before all the other includes.





maybe some one with more knowledge on npapi can help solve these problems :)
User avatar
Azgur
Goblin
Posts: 264
Joined: Thu Aug 21, 2008 4:48 pm

Re: Embedding ogre in firefox

Post by Azgur »

All you need now is to add the old Navi that still uses Gecko to that Ogre scene :)
Post Reply