Experimenting with Emscripten

Let’s start the year with a bang!

No, I was not planning on adding support for Emscripten so soon, but I woke up on Saturday morning with that idea in my mind. I was assuming that the process to take a Crimild demo and make it run on a web browser would take me several weekends, but it turned out to be a lot easier.

So, here’s a–

Wait. I see it in your face. You don’t believe me, right? Take a look at THIS WORKING DEMO then.

Screen Shot 2018-01-07 at 1.36.25 PM

 

Keep in mind that it might take a while to load. Also, try rotating the model by dragging the left mouse button. You can use the WASD keys too, but you need to click on the frame first in order to give it focus.

The source code for this demo is already available at Github. It’s using a branch of the latest Crimild version just to make sure I’m not breaking anything else. I intent to merge this code with the main one once I’m confident enough.

Now, where were we? Oh yes: “So, here’s a postmortem”

First things first

The first step was the obvious one: install Emscripten in my computer. The official website has a todo list that is very clear and easy to follow. And I already had NodeJS on my computer so the whole process was quite simple.

After the installation, I made sure the most basic examples, like the Hello World one, were all working. And with my environment correctly configured, I moved on to write the first demo

Dumping a scene

I wanted to start with something simple. Create a scene (a similar one as in the Triangle example), and dump it to the standard output. That’s it. No simulation, no rendering. Just to make sure Crimild’s core module would build and work correctly.

In order to setup the project, I used the official toolchain for CMake also provided by the same Emscripten installation. That was the key to make the process a lot simpler.

The project’s CMakeLists.txt only needed to specify the location of Crimild sources, making sure that only the core classes would be included in the final Makefile. I used the same macros for building apps as in the example projects.

Then, compiled the whole thing and ran it using node.

There was no need to change anything in the code.

At all.

Moving on.

The GLFW affair

I wanted to render something on the screen next, but it wouldn’t be that easy this time.

First, I had to enable the modules that I needed from Crimild. I knew that Emscripten has built-in support for OpenGL ES and GLFW, that was all I needed.

I had to make some changes in Crimild’s CMake files in order to detect wether or not we’re building for Emscripting. That way we’ll use one version of the libraries or the other. For example, although Crimild has a reference to the GLFW project sources, we need to use the one provided by Emscripten in the end. Therefore, I had to make sure I was using the appropriated ones at linking time (which was not the case for the first couple of hours until I figure it out).

Several “undefined symbols” later, I managed to organize Crimild’s CMake files in a way that can be reused for any platform.

I also had to add some extra flags in the code, specially for handling cases like where to locate the OpenGL header files. In addition, I implemented the required methods to declare the main loop function that will be called each frame.

At that point, I started running the demo using a simple index.html page that only contained the canvas and the loading code for the demo.

S**t got real

With a triangle spinning on the screen, the next step was to actually load an animated model.

I didn’t even try to build the Import module, because I knew that Assimp may became a problem, so I took the easy way out: loading a model already saved as a binary stream.

It took me a while to figure out how to work with Emscripten internal file system, and the fact that, as with any other web project, I eventually had to ran an instance of an HTTP server (the SimpleHTTPServer from python, if you’re curious) in order to publish not only the code, but also de data files.

The result was the working demo you have seen above.

Not only was the character walking on the screen, but all the keyboard and mouse interactions worked as well. I wasn’t expecting that.

Closing comments

Like I said, integrating Emscripten was a lot easier than I originally though. And it works like a charm!

At the time of this writing, I still need to enable other modules, like scripting, but I’m pretty confident that it will be just as easy (specially because Lua is already written in ANSI C/C++). Audio support is still to be added as well.

Based on the results so far, I’m considering making a web version of The P.U.R.G.E Protocol as soon as I have the chance.

Who knows. Maybe my next project would be a web based one 😉

See you next time!

Hernan

 

 

 

Advertisements

Crimild v4.7.0 is out!

Crimild v4.7.0 has just been released!!

This new version includes several new features like the new Audio tools or an improved navigation controller, as well as which is probably the most important one: Behavior Trees.

Behavior Trees are an incredible powerful tool for defining dynamic behaviors for intelligent agents in our simulation based on simple actions and decisions. I’ll be talking about this new feature in length in later posts, since I’m really exited with the results so far.

Other improvements and fixes included in this release:

  • New LineSegment class in math library
  • Fixed particle sorting
  • Path finding support for navigation controllers
  • Other fixes

Check out the full release at Github!

All demo projects have been updated to use the latest release. Make sure to check them out!

Finally, this have been an amazing year for me and Crimild. Special thanks for my Number 1 Fan for her incredible support and constant feedback, challenging me to become better and better every day.

And yes, I have a lot of plans in mind for next year. Many new features and improvements… and lots of refactors, as usual 🙂

Happy New Year!

Hernan

 

Stay awhile and listen

A couple of days ago, I pushed to Github the first implementation for a new audio subsystem with the intention of providing a set of tools for audio playback, both in 2D and 3D.

Although Crimild does currently provide a simple 3D audio tool, it is far from useful in productive environments, specially because it lacks of any means to play audio streams, as in music.

Decided to work from scratch in the new system, I managed to complete a working version in just a couple of days and it has already proven to be much more useful than the previous one.

Here’s a brief introduction of what I’ve accomplished so far.

Core abstraction

As with many other systems in Crimild, the new new audio subsystem is split into two parts: the core abstraction and a platform dependent implementation.

A handful of new classes have been added to the core library, describing abstract interfaces for audio-related concepts, like audio sources, listeners and the audio manager itself, which also acts as an abstract factory for those objects (something that I’m planning to replicate for images too in the future).

In addition, two new components are now available: one for audio sources and the other for the audio listener (usually attached to a camera). These components will handle audio spatialization if needed (for 3D audio), using the parent node’s transformation.

But how useful is an audio system that doesn’t play audio, right?

SFML

As I was looking for a simple, portable, library that will allow me to implement the actual audio layer in a simple way, I came upon SFML. SFML is an abstraction layer for most of the platform specific functionalities, like window handling, networking and, of course, audio.

SFML provides an API to handle both 2D and 3D sounds and streams, so the implementation was pretty straightforward. Much as with other third-party dependencies (like GLFW), this code is organized in a separate package.

Integration

The unique instance for the Audio Manager is stored by the Simulation class itself, in a similar way as with the graphics renderer or other manager. The GLSimulation class, the one used in desktop projects, is already creating a valid instance upon construction, which means client projects should be able to use the new audio facilities right out of the box. No additional setup is needed.

Finally, In order to avoid confusion, I removed the old OpenAL implementation completely.

Examples

There are two examples that make use of the new audio system.

AudioRoom presents you with three music instruments in the floor. As you approach them, a music clip is played and it is possible to have more than one instrument at the same time if you move the camera quick enough.

Screen Shot 2017-11-05 at 6.43.45 PM

The Drone example has been enhanced with multiple actors. This example uses several audio sources and a listener attached to the camera to showcase how 3D sound spatialization works.

Screen Shot 2017-11-05 at 6.43.33 PM

Both of the examples are already available in the demo project.

Final comments

The new audio system is already available in the development branch, in Github. I’m still working on this code, so expect changes in the near future.

Now, I have to admit that I’m not 100% comfortable with SFML. Don’t get me wrong, the library is great and extremely useful, but it feels a bit overkill in my case. SFML provides so much functionality, not only for audio, yet I’m only using a minimal part of it, mainly because Crimild already depends on GLFW for window and input management. On the other hand, I haven’t check how to use SFML on iOS yet and that might cause some headaches in the future. Also, there’s no support for MP3 at the moment.

But then again, SFML is extremely simple to use and I’m short of time at the moment, so I guess it’s a good compromise. I’m confident that I would be able to easily change the implementation in the future if needed, since the level of abstraction of the core classes is quite good.

Time will tell.