Integrating Angular js & three.js

25

Transcript of Integrating Angular js & three.js

Page 1: Integrating Angular js & three.js
Page 2: Integrating Angular js & three.js

Josh Staples @cubicleDowns blog.tempt3d.com github.com/cubicleDowns/ng-three-viewer

Page 3: Integrating Angular js & three.js

WHO? Software Engineer @ napofearth.com“Explore Music Visually” PRIVATE BETA (#ngmeetup)

Page 4: Integrating Angular js & three.js

TODAY

1. (v1) Angular & Three.js 3D Model Viewer

2. (v2) “Controller as” & prototypal Angular components

3. Grunt & Closure compilation approaches

4. (v3*) Scoped scene graph

Page 5: Integrating Angular js & three.js

WHY?Great pattern(s) with low barrier of entry

& high productivity

All web devs can easily be 3D web devs

Isolate THREE code from Angular UI/UX code!

Page 6: Integrating Angular js & three.js

THREE WHAT?threejs.org three features

● Renderers● Scene Graph● Cameras● Animation● Lights● Materials● Shaders● Objects● Geometry● Loaders● Utilities● Export/Import● Support● Examples

● WebVR● DIYVR

Started by Mr. Doob on April 23, 2010

Page 7: Integrating Angular js & three.js

ANGULAR WHO?

Page 8: Integrating Angular js & three.js

Demo v1

http://localhost:8000/v1/dist/

Page 9: Integrating Angular js & three.js

CONTROLLERFileLoaderController

CONTROLLERAppController

UI Elements and Controllers

DIRECTIVE INCLUDEfile-loader.html

DIRECTIVE INCLUDEabout.html

DIRECTIVE INCLUDEchrome.html

DIRECTIVE INCLUDEtoolbar.html

Page 10: Integrating Angular js & three.js

CONTROLLERFileLoaderController

CONTROLLERAppController

DIRECTIVE select

SERVICEStorageService

SERVICEMessageBus

FACTORYViewer

Dependency Injections Across Angular Components

Page 11: Integrating Angular js & three.js

Viewer.factory('ViewerFactory', … ) {

init() home = new Viewer.Scene()

animate () render ()

makeSelection () loadOBJMTL () loadGLTF () loadOBJ () loadJSON () scale () rotate ()

/** Translate the model along an axis * @param {number} x * @param {number} y * @param {number} z */ translate (x,y,z) home.wrangler.currentModel.position.set(x, y, z);

DIRECTIVE select● makeSelection ()

CONTROLLERAppController● init ()● rotate ()● scale ()● translate ()

SERVICEMessageBus

CONTROLLERFileLoaderController● loadOBJMTL ()● loadGLTF ()● loadOBJ ()● loadJSON ()

Viewer Factory Interface

Page 12: Integrating Angular js & three.js

Viewer Factory Singleton

Viewer.Scene()

this.sceneTHREE.Scene()

Viewer Factory Architecture

this.rendererTHREE.WebGLRenderer()

this.wranglerViewer.Wrangler()

this.camerasViewer.Cameras()

this.setupViewer.Setup()

this.controlsTHREE.OrbitControls()

this.raycasterTHREE.Raycaster()

function animate () { requestAnimationFrame(animate); render(); }

function init(params) { home = new Viewer.Scene(params); animate(); }

Page 13: Integrating Angular js & three.js

Angular Directive, <canvas select>

elem.on(tap, function(e) x = e.gesture.center.x;

y = e.gesture.center.y;

// creating NDC coordinates for ray intersection. mouseDown.x = (x / width) * 2 - 1; mouseDown.y = -(y / height) * 2 + 1; ViewerFactory.makeSelection(mouseDown);

Viewer Factory, makeSelection

makeSelection(mouse): var vector = new THREE.Vector3( mouse.x, mouse.y, 1).unproject(home.cameras.liveCam); home.raycaster.set(home.cameras.liveCam.position, vector.sub(home.cameras.liveCam.position).normalize());

var intersected = home.raycaster.intersectObjects(home.wrangler.currentModel, true);

MessageBus.trigger('objectSelected', intersected[0])

Angular Controller/Factory

$scope.$on(‘objectSelected’, function () { // Do Something. });

USE CASE - User Click, Intersect 3D Model, Return Model Information

Page 14: Integrating Angular js & three.js

MOST PROFITABLE MOVIE?

Page 15: Integrating Angular js & three.js

MOST PROFITABLE MOVIE?

THE SEQUEL!

Page 16: Integrating Angular js & three.js

STARRING

&“Controller as”

as ctrl

Annotationsas SNAFU

Page 17: Integrating Angular js & three.js

Sequel (v2)

http://localhost:8000/v2/dist/

Page 18: Integrating Angular js & three.js

Controller as<div id="file-loader" ng-controller="FileLoaderController as loader" ng-show=”loader.visible”> <input type="text" ng-model="loader.data.obj" placeholder="obj file url"> <input type="text" ng-model="loader.data.name" placeholder="unique name">

<button ng-click="otherLoader.loadOBJMTL()">Load OBJ/MTL</button> <button ng-click="loader.loadSampleOBJMTL()">SAMPLE OBJ-MTL</button>

Controller level scope:)

<div id="file-loader" ng-controller="FileLoaderController" ng-show=”visible”>- - -

<input type="text" ng-model="data.obj" placeholder="obj file url"> <input type="text" ng-model="data.mtl" placeholder="mtl file url">

<button ng-click="loadOBJMTL()">Load OBJ/MTL</button> <button ng-click="loadSampleOBJMTL()">SAMPLE OBJ-MTL</button>

nearest scope :(

Page 19: Integrating Angular js & three.js

Viewer.ViewerService

.prototypeinitlistenersanimaterendermakeSelectionloadOBJMTLloadOBJloadGLTFloadJSONrotatetranslatescale

● No More Factories○ closure pattern

● Instead, prototypal Service○ ‘new’ and this○ .bind() for callbacks

● Saves Memory, Time, Searches (sorry)

● Single Pattern For Everything!

● IMHO, the best way to code JS

Service, !Factory

Page 20: Integrating Angular js & three.js

/** @ngInject */Viewer.ViewerService = function($timeout, MessageBus){

this.timeout = $timeout;this.MessageBus = MessageBus;

};

Viewer.ViewerService.prototype.init = function (params){this.home = new Viewer.Scene(params);this.MessageBus.trigger(‘app-ready’);animate();

};

Viewer.factory('ViewerFactory', ['MessageBus', function (MessageBus)

function init () {}

function makeSelection() {}

return { init: init, makeSelection: makeSelection}

closure style,ng-annotate:\

prototypal:)

Prototypal Angular

Page 21: Integrating Angular js & three.js

Controller asAnnotations

/** Service which initiates the THREE.js scene and * provides methods to interact with that scene * * @param {angular.$timeout} $timeout * @param {!Viewer.MessageBus} MessageBus * @constructor * @ngInject */

Viewer.ViewerService = function($timeout, MessageBus){ this.timeout = $timeout; this.MessageBus = MessageBus; };

/** * Translate the model along an axis * @param {number} x * @param {number} y * @param {number} z */Viewer.ViewerService.prototype.translate = function(x, y, z){ this.home.wrangler.currentModel.position.set(x, y, z)};

/** * @param {number} s */Viewer.ViewerService.prototype.scale = function(s) { this.home.wrangler.currentModel.scale.set(s, s, s);};

The Closure Compiler can use data type information about JavaScript variables to provide enhanced optimization and warnings.

Page 22: Integrating Angular js & three.js

APP INIT (app.js)angular.module('ThreeViewer', ['ngHammer', 'ngRoute', 'LocalStorageModule']) .config(['localStorageServiceProvider',function(localStorageServiceProvider){

…. .config(['$locationProvider', function($locationProvider) {

…. $locationProvider.html5Mode(true); .config(['$routeProvider', function($routeProvider){

angular.module('ThreeViewer', ['ngRoute', 'LocalStorageModule']) .config(ThreeViewer.ConfigLocation)

…. .directive('select', ['ViewerService', ThreeViewer.SelectDirective.factory])

…. .filter('forceInt', ThreeViewer.ForceInt.factory)

…. .service('ViewerService', [MessageBus', ThreeViewer.ViewerService])

…. .controller('AppController', ['$scope', 'ViewerService', ThreeViewer.AppController]);

v2:)

v1:\

Page 23: Integrating Angular js & three.js

uglify: { ng3: { options: { compress: { drop_console: true }, sourceMap: true, }, files: { 'dist/app.min.js': ['<%= concat.ng3.dest %>'] } } },

command: 'java -jar closure/compiler.jar ' + '--compilation_level SIMPLE_OPTIMIZATIONS' + '--language_in ECMASCRIPT5_STRICT ' + '--angular_pass ' + '--externs closure/externs/angular-1.3.js ' + '--externs closure/externs/three.js ' + '--generate_exports ' + '--manage_closure_dependencies ' + '--js closure/library/base.js ' + '--js <%= app %> ' + '--js <%= ng %> ' + '--js <%= three %> ' + '--js_output_file dist/app.min.js'

Minify or Closure Compilation?

Closure Compiler● type checking● ngInject● goog.provide / require

Grunt ng-annotate● uglify● ng-annotate

Page 24: Integrating Angular js & three.js

NG to THREEONE APP, TWO PATTERNSV1

● Most Common Angular Pattern● Grunt uglify / minify● Factories● Services● Filters● Directives● Init controllers from DOM

V2

● Prototypal Pattern for Everything!● Bridge to Angular 2.0● Controller as (local scope)● Closure Compilation

○ type checking○ -- angular_pass○ dependency chains○ minification

● App.js Initialization● No closure pattern (factories)

Page 25: Integrating Angular js & three.js

NG to THREEJOIN US! Mobile Developer - Backend GuruUI/UX Designer - QAnapofearth.com/jobs #ngmeetup