Project Goals

The focus of Mesh is to build an online, fully web based Virtual Reality Experience Engine.

Experience Engine is a made up term. However, it is essentially a game engine (like Unity or Unreal), but with a focus on smaller, independent, only-web-based projects.

One of the main benefits of Mesh is there is no software to install, not store to conform to, and only one build target - the web.

The basic style of the engine will be that of a retro, 1990s feel. The style will be somewhere between original Doom and Quake 2 with the story telling ability of Half-Life 1. All of the design choices will reflect this purpose.

While it is possible to use high fidelity assets, the core goal with Mesh Engine is on interactivity and fun, not visual fidelity.

Fun > Fidelity

Eventually it will be multiplayer, but the first milestone is single player story telling.

Software Tools (Pipeline)


  • Time: (delta time * .001) = 1 second
  • Distance: 1 meter (For example: gravity ~= 9.8 meters)
  • Mass: 1 kg

3d Axis in Tools

As you may know 3D Tools have different handed coordinate systems. The main tools Mesh uses have the following systems:

Mesh 3d world space layout is as follows:

      | / +z
-x ---*--- +x
 -z / |

TrenchBroom (maps and entities) 3d layout is as follows:

      | / +y
-x ---*--- +x
 -y / |

While in practice you wont need to worry about this difference, it is useful to know it exists. When you create a level (or structure), Mesh will auto correct for this coordinate system change.

Extra Things to Know

  • Static props object must be in .obj format (more information)
  • Actor models (non-playable characters or animated models) must be in the mdl (Quake 1) format.
  • ‘Levels’ are defined using a custom format built with a custom compiler using the output from Trenchbroom.
  • All texture images must be in power of two (64x64, 128x128, etc).
    • Max texture size is 512x512 (it can actually be larger, but it is not recommended)
    • 16 textures in one renders cycle, 80 textures uploaded to the card


Mesh is written using:

  • Typescript
  • WebGL 1
  • webassembly
  • web workers

Architecture Overview


Bus System

The bus is used to communicate between systems and object components (and anything else that wants to listen). By default anything that extends GameSystem or GameComponent will have access to the bus via handleMessage and sendMessage.

Messages have a subject, type, and payload. Some systems run their own web-workers and communicate back via new messages.

Render System

The render system takes a list of GameObjects, Lights and GLSL Shaders and renders them using WebGL.

Physics System

The physics system is now using a version of Bullet Physics. It’s wrapped to keep the library isolated to the PhysicsSystem and to the RigidBody Component (it also sends messages via the InputMovement Component at the time of this writing)

Loader System

Uses fetch, promises and the message bus. It loads meshes, materials, and textures (it pretends to load shaders as well for consistency).

Sending a message LOAD_OBJECT will make the loader system load an obj file (and any materials and textures associated with that model). It will then respond with a message OBJECT_LOADED when the process has completed.

The OBJECT_LOADED message will have a payload of a newly created GameObject. It’s name will be the object model name (regardless of if the object loaded from cache or server).

Sound System

Sounds must be in .m4a or .mp3 format.