diff --git a/src/js/app.js b/src/js/app.js index 92cdc4c..c3cd116 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -2,7 +2,7 @@ import Config from './data/config'; import Detector from './utils/detector'; import Main from './app/main'; -// verify environment. +// Check environment and set the Config helper if(__ENV__ == 'dev') { console.log('----- RUNNING IN DEV ENVIRONMENT! -----'); @@ -10,6 +10,7 @@ if(__ENV__ == 'dev') { } function init() { + // Check for webGL capabilities if(!Detector.webgl) { Detector.addGetWebGLMessage(); } else { @@ -18,4 +19,4 @@ function init() { } } -window.onload = init; +init(); diff --git a/src/js/app/components/camera.js b/src/js/app/components/camera.js index 3754bce..3fa9228 100644 --- a/src/js/app/components/camera.js +++ b/src/js/app/components/camera.js @@ -12,11 +12,12 @@ export default class Camera { this.updateSize(renderer); - // listeners + // Listeners window.addEventListener('resize', () => this.updateSize(renderer), false); } updateSize(renderer) { + // Multiply by dpr in case it is retina device this.threeCamera.aspect = renderer.domElement.width * Config.dpr / renderer.domElement.height * Config.dpr; this.threeCamera.updateProjectionMatrix(); } diff --git a/src/js/app/components/controls.js b/src/js/app/components/controls.js index c5f0157..f81a453 100644 --- a/src/js/app/components/controls.js +++ b/src/js/app/components/controls.js @@ -5,6 +5,7 @@ import Config from '../../data/config'; export default class Controls { constructor(camera, container) { + // Orbit controls first needs to pass in THREE to constructor const orbitControls = new OrbitControls(THREE); this.threeControls = new orbitControls(camera, container); diff --git a/src/js/app/components/renderer.js b/src/js/app/components/renderer.js index 85ec761..3f70d7b 100644 --- a/src/js/app/components/renderer.js +++ b/src/js/app/components/renderer.js @@ -4,29 +4,27 @@ import Config from '../../data/config'; export default class Renderer { constructor(scene, container) { + // Properties this.scene = scene; this.container = container; + // Create WebGL renderer and set its antialias this.threeRenderer = new THREE.WebGLRenderer({antialias: true}); - //this.renderer.setClearColor(0x000000, 0); + // Set clear color to fog to enable fog or to color this.threeRenderer.setClearColor(scene.fog.color); - this.threeRenderer.setPixelRatio(window.devicePixelRatio); + this.threeRenderer.setPixelRatio(window.devicePixelRatio); // For retina container.appendChild(this.threeRenderer.domElement); - this.threeRenderer.gammaInput = true; - this.threeRenderer.gammaOutput = true; - - // shadow + // Shadow map options this.threeRenderer.shadowMap.enabled = true; this.threeRenderer.shadowMap.type = THREE.PCFSoftShadowMap; - this.threeRenderer.shadowMapSoft = true; - - this.threeRenderer.autoClear = false; + // Get anisotropy for textures Config.maxAnisotropy = this.threeRenderer.getMaxAnisotropy(); + // Initial size update set to canvas container this.updateSize(); // Listeners @@ -39,6 +37,7 @@ export default class Renderer { } render(scene, camera) { + // Renders scene to canvas target this.threeRenderer.render(scene, camera); } } diff --git a/src/js/app/helpers/geometry.js b/src/js/app/helpers/geometry.js index d31e06f..664579d 100644 --- a/src/js/app/helpers/geometry.js +++ b/src/js/app/helpers/geometry.js @@ -2,6 +2,7 @@ import * as THREE from 'three'; import Config from '../../data/config'; +// This helper class can be used to create and then place geometry in the scene export default class Geometry { constructor(scene) { this.scene = scene; @@ -20,12 +21,12 @@ export default class Geometry { const material = new THREE.MeshStandardMaterial({ color: 0xCCCCCC, side: THREE.DoubleSide }); const mesh = new THREE.Mesh(this.geo, material); + // Use ES6 spread to set position and rotation from passed in array mesh.position.set(...position); mesh.rotation.set(...rotation); if(Config.shadow.enabled) { mesh.receiveShadow = true; - mesh.castShadow = true; } this.scene.add(mesh); diff --git a/src/js/app/helpers/material.js b/src/js/app/helpers/material.js index c32c7ba..19c1382 100644 --- a/src/js/app/helpers/material.js +++ b/src/js/app/helpers/material.js @@ -2,20 +2,23 @@ import * as THREE from 'three'; import Config from '../../data/config'; +// USe this class as a Helper to set up some default materials export default class Material { constructor() { this.emissive = new THREE.MeshBasicMaterial({ color: 0xeeeeee, - side: THREE.DoubleSide, - fog: false + side: THREE.DoubleSide }); this.standard = new THREE.MeshStandardMaterial({ shading: THREE.FlatShading, roughness: 1, metalness: 0, - side: THREE.DoubleSide, - fog: false + side: THREE.DoubleSide + }); + + this.phong = new THREE.MeshPhongMaterial({ + }); this.wire = new THREE.MeshBasicMaterial({wireframe: true}); diff --git a/src/js/app/main.js b/src/js/app/main.js index 6cb6a42..54443a4 100644 --- a/src/js/app/main.js +++ b/src/js/app/main.js @@ -22,13 +22,13 @@ import DatGUI from './managers/datGUI'; // data import Config from './../data/config'; -// -- End imports +// -- End of imports // Local vars for rStats let rS, bS, glS, tS; -// This is the main class that ties all of the components together and renders the loop +// This class instantiates and ties all of the components together, starts the loading process and renders the main loop export default class Main { constructor(container) { // Set container property to container element @@ -41,7 +41,7 @@ export default class Main { this.scene = new THREE.Scene(); this.scene.fog = new THREE.FogExp2(Config.fog.color, Config.fog.near); - // Get Device Pixel Ratio first + // Get Device Pixel Ratio first for retina if(window.devicePixelRatio) { Config.dpr = window.devicePixelRatio; } @@ -62,7 +62,7 @@ export default class Main { // Create and place geo in scene this.geometry = new Geometry(this.scene); - this.geometry.make('plane')(100, 100, 10, 10); + this.geometry.make('plane')(150, 150, 10, 10); this.geometry.place([0, -20, 0], [Math.PI/2, 0, 0]); // Set up rStats if dev environment @@ -72,7 +72,7 @@ export default class Main { tS = new threeStats(this.renderer.threeRenderer); rS = new rStats({ - CSSPath: '/assets/css/', + CSSPath: './assets/css/', userTimingAPI: true, values: { frame: { caption: 'Total frame time (ms)', over: 16, average: true, avgMs: 100 }, @@ -96,7 +96,7 @@ export default class Main { // Instantiate texture class this.texture = new Texture(); - // Start loading the textures + // Start loading the textures and then go on to load the model after the texture Promises have resolved this.texture.load().then(() => { this.manager = new THREE.LoadingManager(); @@ -104,23 +104,24 @@ export default class Main { this.model = new Model(this.scene, this.manager, this.texture.textures); this.model.load(); - // onProgress + // onProgress callback this.manager.onProgress = (item, loaded, total) => { console.log(`${item}: ${loaded} ${total}`); }; - // All loaders done + // All loaders done now this.manager.onLoad = () => { - // Set up interaction manager with app now that the model is finished loading + // Set up interaction manager with the app now that the model is finished loading new Interaction(this.renderer.threeRenderer, this.scene, this.camera.threeCamera, this.controls.threeControls); - // Add dat.GUI controls if dev as helper + // Add dat.GUI controls if dev if(Config.isDev) { new DatGUI(this, this.model.obj); } - // Fully loaded + // Everything is now fully loaded Config.isLoaded = true; + this.container.querySelector('#loading').style.display = 'none'; }; }); @@ -129,8 +130,6 @@ export default class Main { } render() { - const delta = this.clock.getDelta(); - // Render rStats if Dev if(Config.isDev) { rS('frame').start(); @@ -142,20 +141,24 @@ export default class Main { rS('render').start(); } - // Clear renderer and re-render - this.renderer.threeRenderer.clear(); + // Call render function and pass in created scene and camera this.renderer.render(this.scene, this.camera.threeCamera); + // rStats has finished determining render call now if(Config.isDev) { rS('render').end(); // render finished rS('frame').end(); // frame finished + // Local rStats update rS('rStats').start(); rS().update(); rS('rStats').end(); } - // Updates section + // Delta time is sometimes needed for certain updates + //const delta = this.clock.getDelta(); + + // Call any vendor or module updates here TWEEN.update(); this.controls.threeControls.update(); diff --git a/src/js/app/managers/datGUI.js b/src/js/app/managers/datGUI.js index 2e24f6f..001d0c7 100644 --- a/src/js/app/managers/datGUI.js +++ b/src/js/app/managers/datGUI.js @@ -144,7 +144,7 @@ export default class DatGUI { shadowFolder.add(Config.shadow, 'helperEnabled').name('Helper Enabled').onChange((value) => { this.light.directionalLightHelper.visible = value; }); - const shadowNearGui = shadowFolder.add(Config.shadow, 'near', 0, 100).name('Near'); + const shadowNearGui = shadowFolder.add(Config.shadow, 'near', 0, 400).name('Near'); shadowNearGui.onChange((value) => { this.controls.enableRotate = false; diff --git a/src/js/app/managers/interaction.js b/src/js/app/managers/interaction.js index 2599620..e94886c 100644 --- a/src/js/app/managers/interaction.js +++ b/src/js/app/managers/interaction.js @@ -10,18 +10,20 @@ export default class Interaction { this.camera = camera; this.controls = controls; + this.timeout = null; + // Instantiate keyboard helper this.keyboard = new Keyboard(); // Listeners // Mouse events - this.renderer.domElement.addEventListener('mouseup', (event) => this.onMouseUp(event), false); this.renderer.domElement.addEventListener('mousemove', (event) => Helpers.throttle(this.onMouseMove(event), 250), false); this.renderer.domElement.addEventListener('mouseleave', (event) => this.onMouseLeave(event), false); this.renderer.domElement.addEventListener('mouseover', (event) => this.onMouseOver(event), false); // Keyboard events this.keyboard.domElement.addEventListener('keydown', (event) => { + // Only once if(event.repeat) { return; } @@ -47,7 +49,9 @@ export default class Interaction { onMouseMove(event) { event.preventDefault(); - setTimeout(function() { + clearTimeout(this.timeout); + + this.timeout = setTimeout(function() { Config.isMouseMoving = false; }, 200);