irrlicht/examples/01.HelloWorld_emscripten/main.cpp

241 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/** 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 <irrlicht.h>
#include "exampleHelper.h"
#include <emscripten.h>
#include <stdio.h>
/*
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<u32> 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<u32> canvasDim(w,h);
if ( canvasDim != screenSize )
{
screenSize = canvasDim;
driver->OnResize(canvasDim);
driver->setViewPort(irr::core::rect<irr::s32>(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<s32>(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 browsers
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.
**/