Skip to content
megapromotingLet's talk

Expertise · Games and simulations

Games, simulations and interactive experiences that open from a link, built on Three.js over WebGL.

We build interactive browser experiences: rules that apply, a state that changes and a reason for the person to take one more step. Five projects built on the same stack, four of them publicly open right now.

Already builtFive in-house implementations on the same stack, of which four can be opened by anyone without asking us: humanoid-sim.megapromoting.com, vision.megapromoting.com, www.megapromoting.com/satelit/ and relieva.vercel.app — all 200 at the check from 06.09.2026. Three.js appears in 17 source files written by us, in five repositories. The reservation that changes half the page: Unity and Unreal do NOT appear anywhere in our code — neither in a file, nor in a project, nor even as an installed application. That part remains an offer with conditions and is written as such, not as a delivered result.

We build games, simulations and interactive experiences that open from a link. No installation, no store, no plugin: the engine is Three.js over WebGL, and the public enters by clicking an address. That is the stack we can show — five projects built, four of them public, all open for anyone who wants to verify them.

A game is not a pretty page. There are rules that apply, a state that changes and a reason for a person to take one more step. In our investigation game, the reason is a 72-hour clock: one reply costs you 10 minutes, one trip across the city 30, and at closing time the case closes with or without you. In the robot simulation, the reason is curiosity: the same robot, the same jump, different gravity.

The part we take more seriously than usual is provenance. In a simulation, the easiest lie is to let a pretty animation pass as demonstrated physics. In the robot simulation, all 15 actions in the interface are marked in code as `cinematic`, the application’s evidence panel declares `actionValidation: "none"`, and the project launch gate currently answers “Release qualification: blocked”. We prefer to publish the gate that refuses rather than a statement we cannot support.

On Unity and Unreal we say it plainly: we take them on request, but we have no delivered project on them. What follows this sentence — the conditions, the risks and how we start — is written below, not hidden in a footnote.

What it covers

The work, by component

First the rule, then the graphics

A prototype with no textures at all, but with the right rule, says more than a beautiful scene with no stakes. In the investigation game, the rule means five characters, eight clues of which three are hard evidence, four motives, four endings and a 72-hour clock in which every line cuts 10 minutes, and a move 30. The hours 00:00–07:00 are skipped automatically, so the clock does not run down in sleep.

The scene in the browser, on Three.js

The same library in five repositories: Three.js 0.184–0.185, sometimes via `@react-three/fiber` and `@react-three/drei`, other times written directly. Two projects use the React variant; two others write pure Three.js, down to the level where we manage buffer attributes manually. The largest in-house engine has 1,824 lines and draws all satellites as a single `THREE.Points` object, with position, colour, size and transparency attributes updated in place, frame by frame.

Rendering that drops down on weak devices by itself

The shader on this site has three levels: `low` with 24 raymarching iterations and a pixel ratio of 0.5, `medium` with 40 and 0.65, `high` with 80, `highp` precision and a ratio capped at 2. The choice is automatic: on mobile it drops to `low`, and any device with 4 cores or fewer downgrades it from `high` to `medium`. If WebGL is missing, the component shuts down cleanly instead of throwing an error. The same discipline in the other projects: cap 1.6 in the city scene and 1.75 in the terrain scene, 1.5 on mobile in the world demonstrator, with the rendering loop stopped when the canvas leaves the screen.

Large scenes that remain a single drawing

A city with 9,506 buildings does not mean 9,506 objects. Each footprint from OpenStreetMap becomes an `ExtrudeGeometry` without bevel and with `curveSegments: 1`, receives the colour written directly into the vertices, has its `uv` attribute deleted — and then everything is merged into a single geometry by `mergeGeometries`. Degenerate geometric rings in the public data are skipped with `try`/`catch`, not left to bring down the page.

Characters that lie, remember and fail under conditions

The truth of the case is not on the page. The files for the five characters — biography, secret, the condition under which he breaks — are in a file that starts with `import "server-only"` and cannot be imported from the client. The character signals an unlocked clue through a tag the player cannot see, and the server accepts it only if that character has the right to give that clue. A model that invents a clue that does not belong to it is ignored, not believed.

Language as a mechanic, not as translation

A character answers briefly and defensively in Romanian, but in Russian he becomes talkative and dangerously frank — the rule is written in his file, and the first line in Russian increases his trust. The microphone follows the same language (`ru-RU` or `ro-RO`). Where localisation is classic, we go further: the robot simulation has eight languages, with Arabic explicitly marked as right-to-left script.

Simulation with formulas, not with impressions

The jump height scales with the ratio of gravities, the gait period with 2π√(L/g), the Froude number with v²/(g·L), and air resistance with the planet’s atmospheric density. Battery autonomy passes through a temperature drop function with four thresholds: above 20 °C unchanged, above 0 °C `0.85 + 0.0075·T`, above −20 °C `0.55 + 0.015·T`, above −40 °C `0.12 + 0.02·T`, and below that 5%. The gait is inverse kinematics with two segments, solved through the cosine law, with a support factor of 0.6 per cycle.

Sound and voice built, not downloaded

The atmosphere of the investigation game has no audio file at all: rain is pink noise filtered low-pass at 1,400 Hz and high-pass at 300 Hz, looped; the crackle of vinyl is short impulses generated every 180 ms; thunder is a burst of noise with exponential decay, scheduled at 18–48 seconds. The visual rain is a separate 2D canvas, up to 180 tilted drops. Voice works both ways: dictation through the browser speech recognition interface and synthesised lines per character through ElevenLabs `eleven_multilingual_v2`, MP3 44.1 kHz / 128 kbps.

3D model format for which there is still no ready loader

The Unitree G1 and Go2 robots come in MJCF, the MuJoCo format, which has no standard loader for Three.js. I wrote one: 170 lines that read the XML, rebuild the body hierarchy, extract each joint with its axis and range, and load the geometry through `STLLoader` and `OBJLoader`. The scene loads 67 mesh files, 62 MB — 29 actuated joints for the humanoid, 12 for the quadruped, counted in the `<actuator>` block of each model.

What it looks like

The path, step by step.

01

The rule on paper, before any pixel

We write what the player gains, what they lose, what an action costs them and when it ends. We deliver the rules document and the list of states — not a moodboard. If the rule does not hold up when read, it does not hold up when drawn either.

02

Playable prototype without keys and without costs

The investigation game can be played through in full and without any API key: the route falls back on a set of scripted lines of 237 lines, and the voices become those of the browser. This makes it possible to see the game from start to finish before paying for the first token. We apply the same logic to any project: the demo mode is a delivery requirement, not a consolation.

03

Rendering budget, set before content

We set the target from the start: which device must run acceptably, what the pixel ratio cap is, how many quality steps there are and when the loop stops. Then the content is fitted into that budget. It is the reverse of how it is usually done, and it is why our scenes do not collapse on a phone.

04

What is demonstrated is labelled, what is not — the same

Every value shown is given a status: measured, inferred from sources, or simulated. The ground in the robot simulation carries the `visual_only` marker in the scene, so no one confuses it with a collision surface. We deliver the label together with the value; it is extra work in construction and the only thing that keeps the page honest after we leave.

05

Handover including what is missing

At the end we hand over the code, the assets with their licences, and the written list of what is not ready. The robot simulation is published as a static build served by Nginx and has no automatic publishing pipeline — this is stated in its own README, not in an internal note. We prefer the list of gaps to come from us.

1Rule written onpaper2scene in the browser onThree.js3treapta de randarethat goes down by itselfpe dispozitiv slabThe same order in all five projects.
The path, in 3 steps

The data

What we touch, where it lives, and how long it stays

The questions anyone with a data protection officer would ask — asked here before they do.

What comes out of the browser and what does not
In the investigation game, the save stays in `localStorage` under the key `dosarul14-save-v1` and does not go anywhere. Only the conversation goes to the server, trimmed to the last 20 messages, with a maximum of 600 characters per message. The model and voice keys live exclusively on the server, in the API routes; the public page never sees them. In the world demonstrator, the voice command is recognised by the browser — audio is not sent anywhere.
Where the data and models come from
The G1 and Go2 robots are derived from Google DeepMind MuJoCo Menagerie and retain the BSD-3-Clause licence, with the notice included alongside the model. The city in the urban scene is OpenStreetMap over Copernicus DEM GLO-30, with the snapshot date written in the data file (2026-07-02). The street-level photographs each carry the author, licence and source page. The car in the world demonstrator and all the decor in the robot simulation are generated from primitives — they are not purchased assets.
Provenance shown, not just respected
The urban scene has a mode that recolours the city to show which buildings have the declared height in OpenStreetMap and which are inferred from the number of floors — 1.128 declared versus 8.378 estimated, that is 11.9 %. The ×3 vertical exaggeration is written in the legend, next to the real terrain range, 37.7–155.9 m. The world demonstrator labels every change in the scene with one of four sources, and the creative layer is shown literally as “simulated”.
What “validated” means for us
In the robot simulation, an action becomes validated only after a versioned scenario, an authoritative physics run, independent validation, declared tolerances and a reproducible artefact. Today none of them meet all five, so all 15 are marked `cinematic` and the interface says so. The MuJoCo reports exist and are versioned: the passive fall of the humanoid on Earth is run with MuJoCo 3.10.0 and a time step of 1 ms, on a model with 31 bodies, 72 geoms, 30 joints and total mass 33.341142 kg, with the `sha256` fingerprint of the file. The free-fall acceleration verification passes at −9.806650 m/s² with a tolerance of 0.049033.
The gate that says “no”
Run on 06.09.2026, the project’s evidence verifier responds: determinism — passed; physics — passed; calibrated joint stop — false; launch qualification — blocked. The reason is written: the stop’s 5 ms response is not calibrated on real hardware. The gate remains red until it is.

A case

A training simulation that refuses to lie

The situation

A team wants to show in presentations how a robot behaves on the Moon versus on Earth, without the technical audience in the room being able to say “that is just an animation.”

What we built

The robot model is loaded from its real format — MJCF, through the loader we wrote, with each joint and its range; for the humanoid, 29 actuated joints are included. Gait uses two-segment inverse kinematics, with a support factor of 0.6. Gravity changes the values in the formulas, not the speed of an animation: jump height scales with the gravity ratio, step period with 2π√(L/g), battery autonomy goes through temperature derating with four thresholds. The terrain is generated deterministically from the planet seed — 80 m per side, amplitude 0.18 m on Earth and 0.58 m on the Moon — and carries the `visual_only` mark in the scene, so no one takes it for a collision surface. Separate from the browser, a numerical validation runs in MuJoCo, with a 1 ms step, which writes its result to a versioned JSON report, with the model fingerprint.

What came out

The scene opens from a link, in eight languages, including right-to-left writing. Every action in the interface is honestly labelled — today, all as a cinematic preview — and a collapsible panel shows exactly what was numerically verified and what was not. When someone in the room asks “is it proven?”, the answer is on the screen, not in the pitch.

What the case does not say

Assume a robot model in an open format, with its licence checked; a written list of the values that must be shown; and the agreement that unvalidated values remain marked as such, including in sales presentations. Without the third point, the project is not this one.

Questions

What people ask us before they call

Which engine are you building on and why exactly that one?

Three.js over WebGL, in the browser. The reason is practical: the deliverable is a link. No installation, no store, no review process, and a fix reaches everyone at the moment of publishing. We use it in five repositories — versions 0.184 and 0.185 — sometimes through `@react-three/fiber` and `@react-three/drei`, sometimes written directly, down to the point where we manually handle buffer attributes. Four of the projects are openly public right now, so the statement can be checked without asking us.

Can you do it in Unity or Unreal?

We take them on by order, but the honest answer starts differently: we have not delivered any project in Unity or Unreal. We searched all the code on the workstation — no `UnityEngine` reference, no `.uproject` file, no `.csproj`, no Unreal macro. The engines are not even installed. What changes in practice if you choose one of them: the deliverable is no longer a web address, but a platform build; distribution goes through a store or installer; and the licensing terms are those published by Unity, respectively Epic, at the project date, and we check them then, not assume them. How we proceed: we start with a paid prototype and, if the project requires engine experience we do not have in-house, we say so before the contract.

Does it work on mobile?

Yes, and it is a decision made at build time, not a hope. The shader on this site has three quality levels — 24, 40 and 80 iterations — and scales down on its own: on mobile it starts at the lightest one, and on any device with 4 cores or fewer the maximum step becomes the middle one. The pixel ratio is capped everywhere: 0.5 on the low step here, 1.5 on mobile in the world demonstrator, 1.6 and 1.75 in the two urban map scenes. When the canvas goes off-screen, the loop stops. What I cannot give you: an FPS figure on a specific phone — we do not have a publishable measurement of that, so we do not invent one.

Does the game open in the browser or is it installed?

Everything we have built so far opens in the browser. Three of the projects are static builds served by Nginx from our server; one is on Vercel. An installable game — desktop, phone or console — is a different discussion: it requires a developer account, a review process, age rating and, most likely, another engine. None of our projects are distributed through a store, so that would be a new path, with its own steps.

Who owns the code and assets at the end?

The code written for your project belongs to you, and the terms are written in the contract before the work starts. For assets, the distinction matters: those generated from primitives or public data come without additional constraints — the car in the world demonstrator is built from boxes, capsules and cylinders, the city in the urban scene is OpenStreetMap over Copernicus DEM. Imported ones keep their licence: the Unitree robots are BSD-3-Clause from MuJoCo Menagerie, with the notice next to the model. In a project with custom-made graphics, the source and ownership of each asset are set out on a list, asset by asset.

What happens with multiplayer?

This is the most honest reservation we have. None of the five projects has shared player state: the investigation game keeps everything in `localStorage`, and the robot simulation keeps state in page memory. A game with several people at once needs an authoritative state server, synchronisation, and network lag handling — new pieces, not a ticked setting. It can be built, but it enters the project as a separate subsystem, with its own work, not as an option.

How long until I see something playable?

I am not giving you a number I cannot stand behind. I am giving you the order: the first delivery is a playable prototype with the correct rule and minimum graphics, and it must work with no API key at all — just as our investigation game is played through entirely on scripted lines. Only after the rule holds are graphics, voice and the model added. If a supplier promises the deadline before seeing the rule, they are promising something they have not measured.

What does it cost to keep the characters “alive”, meaning on the model?

You control the cost through the limits written in code, not through hope. In the investigation game: the history sent to the model is cut to the last 20 messages, the player’s message to 600 characters, the reply to 400 tokens, and the maximum wait time is 45 seconds. Voice synthesis cuts the text to 900 characters. Each of these thresholds is a line we can move together, with a direct effect on the bill. And the no-key mode remains, where the game works on scripted lines and consumes nothing.

What do you not do?

We do not claim that an animation is physically proven. In the robot simulation, all 15 actions are marked in code as `cinematic`, the evidence panel declares `actionValidation: "none"`, and the launch checker says today “Release qualification: blocked”, because the 5 ms response of the joint stopper is not calibrated on real hardware. We do not deliver multiplayer as a hidden option. We do not present ourselves as a Unity or Unreal studio. And we do not put a demo in the offer without saying whether it is public — our investigation game, for example, runs only locally and has no address.

What the statements above rest on (25 sources)
  1. The four public demonstrators respond 200: humanoid-sim.megapromoting.com (974 B), vision.megapromoting.com (619 B), www.megapromoting.com/satelit/ (1,160 B), relieva.vercel.app (680,122 B)https://humanoid-sim.megapromoting.com/ · https://vision.megapromoting.com/ · https://www.megapromoting.com/satelit/ · https://relieva.vercel.app/ · 2026-09-06

24 of them are code and files from our repositories. We don't publish their name or line: together, on a single page, they would describe too precisely how systems that aren't only ours are built. We go through them with you, in the repository, on request — verification stays possible, it just happens in a conversation.

What would you want to work better?

Tell us about your process. Together we decide what is worth building, what we can connect, and how we check the result.

Let's talk