Teenage Mutant Ninja Turtles 3D Truck Tour

Have you ever wondered what the Ninja Turtles’ truck looks like from the inside? Well, now you can, with their brand-new 3D Truck Tour!

Some notable features:

  • Lighting and shading baked into the textures
  • SVG Hotspots open tooltips for additional info
  • Phones load 1/2 resolution assets for less bandwidth & memory consumption
  • Accelerometer-enabled devices use motion of device to rotate camera

Hope you like. Let me know what you think!


You did that @marquizzo? That’s awesome!! Congrats man! Is Nick going to tweet about this? If they (or you) do, we’ll RT!

That is really cool!

I like how it adapts to mobile users and that you load lower res textures.

Few tips from myself, that you can try applying to future projects of similar content, to bring visual quality to next-gen look:

Preload only stuff that is required for initial screen, and once it is shown start loading all assets required for scene straight away. Once user clicks “start” show already progressed loading bar if not yet loaded, or show scene straight away if everything already loaded.
This will allow faster first interactive screen to appear and less time required to get to experience the app.

Lightmaps look a bit washed out, this might be related to gamma correction and exposure. When rendering lightmaps, it is bette to render them for 2.2 gamma, and use same gamma in your app. Then you can adjust exposure to make it right brightness.

To take it totally next level visually, it would be great to use PBR, but that would require quiet a lot of work:

  • Separate albedo from lightmap.
  • Bake AO map to separate texture.
  • Create metalness and glossiness textures (they totally can use same unwrap as it is now, but need to express in color metalness and glossiness values)
  • Add prefiltered box projected cubemap, pre-rendered probably in modeling software you use.
  • Normal map to express fine details in geometry.

So at the end you would have a bit more assets indeed, so bigger download size, but next-gen looking thing. So in result you would have textures:

  • albedo (rgb; jpg)
  • amg (r - ao, g - metalness, b - glossiness; png; can be smaller)
  • normal map (rgb; png)
  • lightmap (rgb; jpg; very small)
  • prefiltered cubemap
    This would have dynamic reflections of environment, and materials would look really like plastic, metal, rubber, leather, or any other you intent to make.

Those are tips that you can play with in the future.
Feel free to actually experiment with those things, and to engage on forum with some tests and asking some feedback. We can always give you tips on what we think can improve a lot your apps.

Anyway, this is really cool app, and awesome to see something like that made in PlayCanvas! If you’ve collected some feedback or ideas for features that would make engine and tools better - please, feel free to share them!

Thanks, Will! Yes, I’m planning on doing so later today, maybe when I get home.

Thanks for the feedback, Max! We considered doing improvements to the materials to have more dynamic reflections, but realized that our texture assets and model were getting pretty large, so we had to cut back to keep the filesize compact and avoid memory issues on older devices.

I tried running app.preload() in the background without calling app.start() until the user clicked on the “Enter” button, as you suggested, but I got unexpected results:

   app.preload(function (err) {
        if (err) {

        app.loadScene(SCENE_PATH, function (err, scene) {
            if (err) {
            // app.start();

The sounds that have autoplay selected started playing prematurely. It seems that autoplay sounds start playing on app.loadScene() instead of waiting for app.start(), so I had to scrap that preloading strategy (I could’ve disabled autoplay, and start them progamatically, but decided not to do an entire new export due to time constraints).

Regarding assets loading, I wouldn’t override those preload methods and other stuff.
Instead mark as preload only things that required for first menu, then add specific tag (e.g. ‘to-load’) to all other assets, and then once first screen loaded do something like this:

var assets = app.assets.findByTag('to-load');
var loaded = 0;
var progress = 0;
var complete = false;
var progressBar = null;

// method called when user hits "start" button
var onStart = function() {
    if (complete) {
        // do not show progress bar
        // go straight to app
    } else {
        // show progress bar with progress
        progressBar = progressBarElement;
        progressBar.style.width = progress + '%';

var onLoad = function() {

    if (loaded === assets.length) {
        // loading complete
        complete = true;
    } else {
        // loading in progress
        progress = Math.floor(loaded / assets.length  100);
        if (progressBar)
            progressBar.style.width = progress + '%';

for(var i = 0; i < assets.length; i++) {
    if (assets[i].resource) {
        // already loaded
    } else {
        assets[i].once('load', onLoad);

This gives you a progress of loading, and all happens in async, and shall be executed straight away at first screen user sees after preloading is done.
Then when user hits “start” check if loading complete, if not render progress bar with progress value from this loading, if complete then go straight in to 3d experience.
There will be shader compilation as well, so you can still show loading for one more frame, or even start 3d experience behind splash screen, that way there will be shader compilation during splash screen, and it will just hide splash screen once user hits “start”.

1 Like

Awesome! Great to know there’s a way to have more control over the asset-loading process. Thanks for the suggestion, I’ll make sure to use this method for our next project.

1 Like

Indeed, and personally, this way is so much better than multiple scenes.