Embedding ogre in firefox
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:
updated download links:
http://developer.mozilla.org/en/docs/Gecko_SDK
ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/source/firefox-3.0.7-source.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)
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.

beatiful
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:
maybe some one with more knowledge on npapi can help solve these problems
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
updated download links:
http://developer.mozilla.org/en/docs/Gecko_SDK
ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/source/firefox-3.0.7-source.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.

beatiful
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