/** Example 001 HelloWorld adapted to emscripten This Tutorial shows how to run code with emscripten. Emscripten compiles c++ to asm.js to allow it running inside a webbrowser. You have to setup the emscripten environment on your system first to use this. */ #include #include "exampleHelper.h" #include #include /* The code in here is mostly similar to the usual HelloWorld. You can find more information about it there. Here we mainly document the differences needed for emscripten. */ using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; /* This part not necessary for emscripten, only useful to keep it in in case you want to run the same code on Windows with VS as well. */ #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif /* Variables on the stack will stay intact between runs of one_iter() */ IrrlichtDevice *device = 0; IVideoDriver* driver = 0; ISceneManager* smgr = 0; IGUIEnvironment* guienv = 0; ICameraSceneNode* camera = 0; dimension2d screenSize(640, 480); #ifdef __EMSCRIPTEN__ /* Handle changes in canvas size which are done with html/js. Note that it's only OK for windowed so far, the switch to fullscreen not yet working. Also the emscripten_get_canvas_size might cause a slow-down (but haven't found yet a way to avoid it with SDL1). */ void checkCanvasResize() { int w, h, fs; emscripten_get_canvas_size(&w, &h, &fs); const core::dimension2d canvasDim(w,h); if ( canvasDim != screenSize ) { screenSize = canvasDim; driver->OnResize(canvasDim); driver->setViewPort(irr::core::rect(0,0,w,h)); irr::f32 aspect = (irr::f32)w / (irr::f32)h; camera->setAspectRatio(aspect); } } /* emscripten can't run things in an endless-loop or otherwise the browse will consider the script to hang. */ void one_iter() { if(!device->run()) { // Could clean up here in theory, but not sure if it makes a difference /* This tells emscripten to not run any further code. */ emscripten_cancel_main_loop(); return; } // In case you have a resizeable canvas (resized from html) //checkCanvasResize(); driver->beginScene(ECBF_COLOR | ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } #endif //__EMSCRIPTEN__ /* The main method is also run on emscripten. */ int main() { /* Printing out the build date/time is very useful to find troubles with unexpected browser-caches. */ printf("Build-date: %s %s\n", __DATE__, __TIME__); SIrrlichtCreationParameters parameters; /* Create device flags for emscripten are still experimental and might not all work. - deviceType: You can to use EDT_OGLES2 or EDT_WEBGL1 on emscripten. EDT_WEBGL1 is better optimized but does not yet support all options. EDT_OGLES2 needs -s FULL_ES2=1 as linker flag in the Makefile. */ #ifndef __EMSCRIPTEN__ parameters.DriverType = EDT_OGLES2; #else //__EMSCRIPTEN__ parameters.DriverType = EDT_WEBGL1; #endif //__EMSCRIPTEN__ parameters.LoggingLevel = ELL_DEBUG; parameters.WindowSize = screenSize; parameters.Stencilbuffer = false; parameters.AntiAlias = 4; device = createDeviceEx(parameters); if (!device) return 1; /* Window caption will set the title-text in the browser. */ device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); /* Get a pointer to the VideoDriver, the SceneManager and the graphical user interface environment, so that we do not always have to write device->getVideoDriver(), device->getSceneManager(), or device->getGUIEnvironment(). */ driver = device->getVideoDriver(); smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); /* We add a hello world label to the window, using the GUI environment. The text is placed at the position (10,10) as top left corner and (260,22) as lower right corner. */ guienv->addStaticText(L"Hello World! This is Irrlicht on emscripten!", rect(10,10,260,22), true); /* Get a media path dedicated for your platform. We tell emscripten to copy the media folder in the Makefile with: "--preload-file ../../media@/media" That copies our ../../media folder in a .data file which is loaded by the browser. It can then be accessed there by "/media" name (that's the parameter after the '@'). Note that usually you would try to copy only as many files as absolutely necessary to reduce start-up times. */ const io::path mediaPath = getExampleMediaPath(); /* Make a model called Sydney show up. */ IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "sydney.md2"); if (!mesh) { device->drop(); return 1; } IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* Disable lighting because we do not have a dynamic light in here, and the mesh would be totally black otherwise. Set the frame loop such that the predefined STAND animation is used. Add a texture to the model. */ if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture(mediaPath + "sydney.bmp") ); } /* To look at the mesh, we place a camera into 3d space at the position (0, 30, -40). The camera looks from there to (0,5,0), which is approximately the place where our md2 model is. */ camera = smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); #ifndef __EMSCRIPTEN__ // this part only so you can run the same code on desktop /* On desktop we run and endless loop until the user closes the window or presses ALT+F4 (or whatever keycode closes a window). */ while(device->run()) { driver->beginScene(ECBF_COLOR | ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } device->drop(); #else // __EMSCRIPTEN__ /* Setting fps to 0 or a negative value will use the browser’s requestAnimationFrame mechanism to call the main loop function. Emscripten documentation recommends to do that, but you can also set another fps value and the browser will try to call the main-loop fps times per second. The simulate_infinite_loop tells emscripten that this is an application which will simulate an infinite loop. There is also a flag in the Makefile about that: -s NO_EXIT_RUNTIME=1 */ int fps = 0; int simulate_infinite_loop = 1; emscripten_set_main_loop(one_iter, fps, simulate_infinite_loop); #endif //__EMSCRIPTEN__ return 0; } /* That's it. Compile and run. **/