mirror of
https://github.com/minetest/irrlicht.git
synced 2024-12-29 09:27:31 +01:00
241 lines
6.7 KiB
C++
241 lines
6.7 KiB
C++
|
/** 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 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.
|
|||
|
**/
|