npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

t3-boilerplate

v0.2.7

Published

Boilerplate for THREEjs

Downloads

9

Readme

t3

t3 is a template to build three.js demos without worrying about the common set up process and allowing multiple applications per page, this project is inspired by Jeromme's three.js boilerplate

Features

  • Module defined to work anywhere (follows the UMD pattern)
  • Integration with dat.gui and Stats
  • Micro scene handler for your multistaged demo :)
  • Micro camera manager
  • Keyboard manager utility to catch keyboard events
  • Themes for the default scene
  • Frame rate control

Playground

Powered by

Installation

NPM

npm install --save-dev t3-boilerplate

Usage:

var t3 = require('t3-boilerplate')

Bower

Install the package with bower (recommended):

bower install t3

Or save the dist/ files on you project library (the old way)

Use with RequireJS

By default bower will install the package on bower_components/t3, you might modify your requirejs configuration file adding a path to the source files

requirejs.config({
  ...
  paths: {
    t3: 'path/to/bower_components/dist/t3'		// concatenated script
    // or
    t3: 'path/to/bower_components/dist/t3.min'	// minified script
  }
  ...
});

And require it on a module using:

define(['t3'], function (t3) {
  // module t3 is loaded :)
});

Explicitly importing the file on your project

As an alternative if you don't use RequireJS, add the source files (t3.js or t3.min.js which can be loaded with the source map for debugging purposes) to your page

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>t3</title>
	<script src="path/to/bower_components/dist/t3.min.js"></script>
</head>
<!-- ... -->
</html>

Getting Started

Basic example

It's required that you create a DOM element for the application which needs to be identified with an id

<div id="canvas"></div>

The minimal example requires only the application's wrapper selector:

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas'
  });
});

Fullscreen > Source Code >

This basic "world" has:

  • A default scene
  • A default camera with OrbitControls
  • A a grid in the XZ plane (defined in the Coordinates model)
  • A set of axes positioned at the center of the scene (Source)
  • A dat-gui folder to enable/disable some options (Source)
  • A gui control for the visibility of the axes, ground and grids (Source)
  • A gui control to pause the animation (Source)
  • A gui control for the maximum frame rate (Source)

Init & Update

Let's introduce the init and update methods in the object passed to t3.run.

The init method is called after t3's constructor has been called, within this method this has the following properties:

  • scenes: a pool of scenes
  • activeScene: the current scene which is by default this.scenes.default
  • cameras: a pool of cameras
  • activeCamera: the current camera which is a perspective camera with Orbit controls and by default is this.cameras.default
  • renderer: a reference to an instance of THREE.WebGLRenderer
  • keyboard: a reference to the keyboard instance (a utility to store keyboard events)
  • datgui: a reference to an instance of dat.gui
  • loopManager: this instance controls the application frame rate and paused state
  • theme: the theme of the application
  • t3cache: the internal cache if injectCache is passed as a configuration option

The update method is called from this.loopManager and receives the time elapsed since the last frame a.k.a. delta

A rotating cube

We're used to create an object and add it to the scene, well, now the scene is this.activeScene and the object has to be added to it:

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      // this.activeScene equals this.scenes.default
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

Fullscreen > Source Code >

Delaying the game loop

Perhaps we might need to call the game loop at a later time, to do so we can add the option renderImmediately: false

define(['t3'], function (t3) {
  var instance = t3.run({
    selector: '#canvas',
    renderImmediately: false,
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      // this.activeScene equals this.scenes.default
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

To make it renderable again at some point call instance.loopManager.start() where the instance is the value returned from calling t3.run

Code for the toggle example:

// instance is the value returned from calling `t3.run`
var paused = instance.loopManager.pause;
instance.loopManager[paused ? 'start' : 'stop']();

Fullscreen > Source Code >

Disabling some objects in the default scene

There are 5 groups on the default scene:

  • (visible) A set of axes (RGB = XYZ)
  • (visible) Ground
  • (visible) A grid on the XZ plane
  • A grid on the YZ plane
  • A grid on the XY plane

The visibility of these elements can be defined in the ambientConfig option

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    helpersConfig: {
      axes: false,
      ground: false,
      gridX: true,
      gridY: true,
      gridZ: true
    },
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      // this.activeScene equals this.scenes.default
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

Fullscreen > Source Code >

Changing Scenes

Since the application has a pool of scenes, we can create as many scenes as we want and change it in runtime, to do so we can call this.setActiveScene with the name of the scene:

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    init: function () {
      var scene,
        geometry,
        material;

      // scene setup
      this.addScene(new THREE.Scene(), 'cone');
      this.addScene(new THREE.Scene(), 'sphere');

      // default scene
      scene = this.scenes['default'];
      geometry = new THREE.BoxGeometry(20, 20, 20);
      material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      scene.add(this.cube);

      // cone scene
      scene = this.scenes.cone;
      geometry = new THREE.CylinderGeometry(10, 0, 20, 64, 64);
      material = new THREE.MeshNormalMaterial();
      this.cylinder = new THREE.Mesh(geometry, material);
      this.cylinder.position.set(100, 100, 100);
      scene.add(this.cylinder);

      // sphere scene
      scene = this.scenes.sphere;
      geometry = new THREE.SphereGeometry(10, 32, 32);
      material = new THREE.MeshNormalMaterial();
      this.sphere = new THREE.Mesh(geometry, material);
      this.sphere.position.set(100, 100, 100);
      scene.add(this.sphere);
    },
    update: function (delta) {
      var me = this;
      ['cube', 'cylinder', 'sphere'].forEach(function (v) {
        me[v].rotation.x += 0.01;
        me[v].rotation.y += 0.01;
      });
    }
  });
});

Code to change the scene:

var scenes = ['default', 'cone', 'sphere'];
current = current + 1;
current %= scenes.length;
instance.setActiveScene(scenes[current]);

Fullscreen > Source Code >

Changing Cameras

Since the application has a pool of cameras, adding more cameras is as easy as registering it with a name just like changing scenes:

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    init: function () {
      var camera,
        width = window.innerWidth,
        height = window.innerHeight,
        fov, ratio, near, far;

      // origin camera
      fov = 45;
      ratio = width / height;
      near = 1;
      far = 1000;
      camera = new THREE.PerspectiveCamera(fov, ratio, near, far);
      camera.position.set(30, 30, 30);
      camera.lookAt(new THREE.Vector3(100, 100, 100));
      this.addCamera(camera, 'origin');

      // orthographic camera
      camera = new THREE.OrthographicCamera(
        width / -2, width / 2, height / 2, height / -2, near, far
      );
      camera.position.set(200, 300, 200);
      camera.lookAt(new THREE.Vector3(100, 100, 100));
      this
        .addCamera(camera, 'orthographic')
        // add orbit controls to the camera
        .createCameraControls(camera);

      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

Code to change the camera:

var cameras = ['default', 'origin', 'orthographic'];
current = current + 1;
current %= cameras.length;
instance.setActiveCamera(cameras[current]);

Fullscreen > Source Code >

Themes

If you don't like the dark theme you can switch to the light theme on the default scene by passing theme: 'light' in the configuration options:

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    theme: 'light',
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

Fullscreen > Source Code >

Wanna roll your own? Just add an object to the object t3.themes and you're done!

define(['t3'], function (t3) {

  t3.themes.sandyStone = {
    clearColor: 0xE6E2AF,
    fogColor: 0xE6E2AF,
    groundColor: 0xA7A37E
  };

  return t3.run({
    selector: '#canvas',
    theme: 'sandyStone',
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      this.cube = new THREE.Mesh(geometry, material);
      this.cube.position.set(100, 100, 100);
      this.activeScene
        .add(this.cube);
    },
    update: function (delta) {
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
    }
  });
});

The available configuration options are:

  • clearColor (used in the THREE.WebGLRenderer instance)
  • fogColor (used in the THREE.Fog instance)
  • groundColor (ground color of the helper)

Fullscreen > Source Code >

Caching objects

Another useful utility that the template has is the possibility of caching elements, three.js defines the field name for any THREE.Object3D which allows to make lookups (Source), the template extends this functionality and makes it possible to save the last added/removed object from any instance of THREE.Object3D (Source)

define(['t3'], function (t3) {
  return t3.run({
    selector: '#canvas',
    injectCache: true,
    init: function () {
      var geometry = new THREE.BoxGeometry(20, 20, 20);
      var material = new THREE.MeshNormalMaterial();
      var cube = new THREE.Mesh(geometry, material);
      cube.position.set(100, 100, 100);
      // since THREE.Object3D.prototype was injected with the method
      // `cache` we can call it to save the last added/removed object
      // under `this.__t3cache__` passing a name
      this.activeScene
        .add(cube)
        // unique identifier = cube
        .cache('cube');

      // removal example
      // this.activeScene
      //   .remove(cube)
      //   .cache();
    },
    update: function (delta) {
      var cube = this.getFromCache('cube');
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
    }
  });
});

Fullscreen > Source Code >

Adding custom functionality by extending t3.Application

t3.run creates in fact a subclass of t3.Application allowing an application to be quickly started, you can extend the functionality of the t3.Application class by creating a subclass:

Application.run = function (options) {
  options = _.merge({
    init: function () {},
    update: function () {},
  }, options);
  assert(options.selector, 'canvas selector required');

  var QuickLaunch = function (options) {
    Application.call(this, options);
    options.init.call(this, options);
  };
  QuickLaunch.prototype = Object.create(Application.prototype);

  QuickLaunch.prototype.update = function (delta) {
    Application.prototype.update.call(this, delta);
    options.update.call(this, delta);
  };

  return new QuickLaunch(options);
};

TODO list

  • Render only on mouseover
  • Pause if not visible

Development

After cloning the repo install the required node dependencies with:

npm install

Generate the bundle with:

gulp

This will generate an unminified file since it creates the bundle with watchify, if you want to build the minified file including its source map execute:

gulp build

Project structure

Generated by tree:

src
├── controller
│   ├── Application.js
│   ├── Keyboard.js
│   └── LoopManager.js
├── index.js
├── lib
│   ├── OrbitControls.js
│   ├── THREEx
│   │   ├── FullScreen.js
│   │   ├── WindowResize.js
│   │   └── index.js
│   ├── dat.gui.min.js
│   └── stats.min.js
├── model
│   └── Coordinates.js
└── themes
    ├── dark.js
    └── light.js

5 directories, 13 files

Powered by PojoViz:

Changelog

0.2.5

`browserify-shim` is no longer a dependency

0.2.4

`extend` is used to merge objects

0.2.3

`ambientConfig` renamed to `helpersConfig`
`Coordinates` now uses `THREE.Grid`

0.2.2

available as `t3-boilerplate` in npm

0.2.0

config.id replaced with config.selector in the configuration options of t3.run

0.1.3

PojoViz example embedded
Functions now have the form `function Name() {` to be analyzed with pojoviz
Fixed minor typos in the Readme file

0.1.2

Fixed some broken links [thanks to mscdex]
Additional instructions for development
Custom themes

0.1.1

Fixed some typos in the documentation
`t3.run` is now an alias for `t3.Application.run`

Acknowledgments

Special thanks to @mrdoob the author of three.js

Also this project wouldn't have been possible without the help from the following libraries:

Last but not least, thanks to Udacity and their awesome Interactive 3D graphics course, you should definitely check out their courses :)