.dg .c{
  color: black !important;
}
View Compiled
class Loader {
	static ASSETS = {};

	constructor() {
		Loader.ASSETS.models = {};
		this.manager = new THREE.LoadingManager();
		this.fbxLoader = new THREE.FBXLoader(this.manager);
	}


	load(callback) {
		this.fbxLoader.load('https://threejs.org/examples/models/fbx/Samba%20Dancing.fbx', fbx => {
			Loader.ASSETS.models.samba_dancing = fbx;
      callback();
		});
	}
}
class Gui {
	static DATA = {};

	constructor(renderer, scenarios) {
		const scenarioControllerOptions = [];
		this.gui = new dat.GUI();
		this.renderer = renderer;
		this.scenarios = scenarios;

		this.scenarios.forEach(object => {
			const scene = object.scene;
			if (object.isRendering) {
				Gui.DATA.scenario = object.name;
			}
			scenarioControllerOptions.push(scene.name);
		});

		this.gui
			.add(Gui.DATA, 'scenario', scenarioControllerOptions)
			.onChange(e => {
				this.scenarios.forEach(scenario => {
					if (scenario.name === e) this.renderer.setScenario(scenario);
				});
			})
			.listen();

		this.gui.updateDisplay();
	}
}
class Renderer {
	static CURRENT_SCENARIO;

	constructor() {
		// create renderer
		this.renderer = new THREE.WebGLRenderer({
			antialias: true,
			alpha: true,
		});
		this.renderer.setSize(window.innerWidth, window.innerHeight);
		this.renderer.context.getExtension('OES_standard_derivatives');
		this.renderer.autoClear = false;

		// DOM
		document.body.appendChild(this.renderer.domElement);

		// orbit controls
		this.camera = new THREE.PerspectiveCamera(
			75,
			window.innerWidth / window.innerHeight,
			0.1,
			1000
		);
		this.camera.position.set(0, 2, 10);
	}

	setScenario(scenario) {
		Gui.DATA.scenario = scenario.name;
		Renderer.CURRENT_SCENARIO = scenario;
	}

	onResize() {
		this.camera.aspect = window.innerWidth / window.innerHeight;
		this.camera.updateProjectionMatrix();
		this.renderer.setSize(window.innerWidth, window.innerHeight);
	}

	onRender() {
		this.renderer.render(Renderer.CURRENT_SCENARIO.scene, this.camera);
	}
}
class Scenario {
	constructor(name, showHelpers) {
		this.name = name;
		this.showHelpers = showHelpers;
		this.helpers = [];

		// scene
		this.scene = new THREE.Scene();
		this.scene.name = this.name;

		// helper
		this.gridHelper = new THREE.GridHelper(100, 100);
		this.gridHelper.visible = this.showHelpers;
		this.helpers.push(this.gridHelper);
		this.scene.add(this.gridHelper);
	}

	toggleHelpers(state) {
		this.showHelpers = state;
		this.helpers.forEach(helper => {
			helper.visible = state;
		});
	}
}
class Basic extends Scenario {
	constructor(name, showHelpers) {
		super(name, showHelpers);

		// cube
		const geometry = new THREE.BoxGeometry(2, 2, 2);
		const material = new THREE.MeshStandardMaterial();
		this.cube = new THREE.Mesh(geometry, material);
		this.cube.name = 'cube';

		this.scene.add(this.cube);
	}
}
class Animation extends Scenario {
	constructor(name, showHelpers) {
		super(name, showHelpers);

		// animation
		this.model = Loader.ASSETS.models.samba_dancing;
		this.model.scale.set(0.05, 0.05, 0.05);
		this.scene.add(this.model);
	}
}
class WebGLApp {
	static SHOW_HELPERS = true;

	constructor() {
		// scenarios
		this.scenarios = [];
		this.basic = new Basic('Basic', WebGLApp.SHOW_HELPERS);
		this.fbx = new Animation('FBX', WebGLApp.SHOW_HELPERS);
		this.scenarios.push(this.basic, this.fbx);

		// renderer
		this.renderer = new Renderer();
		this.renderer.setScenario(this.fbx);

		// event binding
		this.render = ::this.render;

		// ignite render
		this.render();

		// gui
		this.gui = new Gui(this.renderer, this.scenarios);
	}

	onToggleHelpers() {
		this.scenarios.forEach(scene => {
			scene.toggleHelpers(!WebGLApp.SHOW_HELPERS);
		});

		WebGLApp.SHOW_HELPERS = !WebGLApp.SHOW_HELPERS;
	}

	onResize() {
		this.renderer.onResize();
	}

	render() {
		requestAnimationFrame(this.render);

		this.renderer.onRender();
	}
}
class App {
	static STATE_LOADING = 'LOADING';
	static STATE_RUNNING = 'RUNNING';

	static STATE = App.STATE_LOADING;

	constructor() {
		// loader
		this.loader = new Loader();

		// event binding
		this.onAssetsLoaded = ::this.initMain;
		this.onKeyDown = ::this.onKeydown;
		this.onResize = ::this.onResize;
		this.initEvents();
	}

	initEvents() {
		this.loader.load(this.onAssetsLoaded);
	}

	onResize(e) {
		this.webglApp.onResize();
	}

	onKeydown(e) {
		// console.log(e.keyCode);
		switch (e.keyCode) {
			case 67:
				this.toggleCamera();
				break;
			case 81:
				this.toggleHelpers();
				break;
		}
	}

	initMain() {
		this.webglApp = new WebGLApp();
		window.addEventListener('resize', this.onResize);
		document.addEventListener('keydown', this.onKeyDown);
		App.STATE = App.STATE_RUNNING;
	}

	toggleHelpers() {
		if (App.STATE !== App.STATE_RUNNING) return;
		this.webglApp.onToggleHelpers();
		dat.GUI.toggleHide();
	}
}

new App();
View Compiled
Run Pen

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js
  2. https://threejs.org/examples/js/loaders/FBXLoader.js
  3. https://threejs.org/examples/js/libs/inflate.min.js
  4. https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
  5. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.js