kopia lustrzana https://github.com/robhawkes/vizicities
240 wiersze
6.1 KiB
JavaScript
240 wiersze
6.1 KiB
JavaScript
/* globals window, _, VIZI, THREE */
|
|
|
|
/**
|
|
* 3D scene controller
|
|
* @author Robin Hawkes - vizicities.com
|
|
*/
|
|
|
|
(function() {
|
|
"use strict";
|
|
|
|
VIZI.Scene = function(options) {
|
|
if (VIZI.DEBUG) console.log("Initialising VIZI.Scene");
|
|
|
|
var self = this;
|
|
|
|
self.options = options || {};
|
|
|
|
_.defaults(self.options, {
|
|
antialias: false,
|
|
fogColour: 0xffffff,
|
|
suppressRenderer: false,
|
|
picking: false
|
|
});
|
|
|
|
if (!self.options.viewport) {
|
|
throw new Error("Required viewport option missing");
|
|
}
|
|
|
|
self.scene = self.createScene();
|
|
self.renderer = self.createRenderer();
|
|
|
|
self.pickingScene;
|
|
self.pickingTexture;
|
|
self.pickingMaterial;
|
|
self.pickingGeom;
|
|
self.pickingMesh;
|
|
self.pickingColourID;
|
|
self.pickingColour;
|
|
self.pickingRef;
|
|
|
|
if (self.options.picking) {
|
|
self.pickingScene = new THREE.Scene();
|
|
|
|
self.pickingTexture = new THREE.WebGLRenderTarget(self.options.viewport.clientWidth, self.options.viewport.clientHeight);
|
|
self.pickingTexture.generateMipmaps = false;
|
|
|
|
self.pickingMaterial = new THREE.MeshBasicMaterial({
|
|
vertexColors: THREE.VertexColors,
|
|
// TODO: Remove reliance on making things double-sided to make up for meshes created with incorrect wising
|
|
side: THREE.DoubleSide
|
|
});
|
|
|
|
self.pickingGeom = new THREE.Geometry();
|
|
self.pickingMesh;
|
|
|
|
// Start at 1 because default pixel value is 0 (black)
|
|
self.pickingColourID = 1;
|
|
self.pickingColour = new THREE.Color();
|
|
self.pickingRef = {};
|
|
}
|
|
};
|
|
|
|
VIZI.Scene.prototype.createScene = function() {
|
|
var self = this;
|
|
|
|
var scene = new THREE.Scene();
|
|
|
|
// TODO: Fog distance should be an option
|
|
scene.fog = new THREE.Fog(self.options.fogColour, 1, 15000);
|
|
|
|
// TODO: Make this more customisable, perhaps as a "day/night" option
|
|
// - I'm sure people would want to add their own lighting too
|
|
// TODO: Should this even be in here?
|
|
var directionalLight = new THREE.DirectionalLight( 0x999999 );
|
|
directionalLight.intesity = 0.1;
|
|
directionalLight.position.x = 1;
|
|
directionalLight.position.y = 1;
|
|
directionalLight.position.z = 1;
|
|
|
|
scene.add(directionalLight);
|
|
|
|
var directionalLight2 = new THREE.DirectionalLight( 0x999999 );
|
|
directionalLight2.intesity = 0.1;
|
|
directionalLight2.position.x = -1;
|
|
directionalLight2.position.y = 1;
|
|
directionalLight2.position.z = -1;
|
|
|
|
scene.add(directionalLight2);
|
|
|
|
return scene;
|
|
};
|
|
|
|
VIZI.Scene.prototype.createRenderer = function() {
|
|
var self = this;
|
|
|
|
var renderer;
|
|
|
|
if (self.options.suppressRenderer) {
|
|
// Mock renderer for tests
|
|
// TODO: Should really remove this or fix the tests
|
|
renderer = {
|
|
setSize: function(){},
|
|
setClearColor: function(){},
|
|
render: function(){},
|
|
domElement: document.createElement("canvas")
|
|
};
|
|
} else {
|
|
renderer = new THREE.WebGLRenderer({
|
|
antialias: self.options.antialias,
|
|
domElement: document.createElement("canvas")
|
|
});
|
|
}
|
|
|
|
renderer.setSize(self.options.viewport.clientWidth, self.options.viewport.clientHeight);
|
|
renderer.setClearColor(self.scene.fog.color, 1);
|
|
|
|
// Gamma settings make things look 'nicer' for some reason
|
|
renderer.gammaInput = true;
|
|
renderer.gammaOutput = true;
|
|
|
|
self.options.viewport.appendChild(renderer.domElement);
|
|
|
|
return renderer;
|
|
};
|
|
|
|
VIZI.Scene.prototype.add = function(object) {
|
|
var self = this;
|
|
self.scene.add(object);
|
|
};
|
|
|
|
VIZI.Scene.prototype.addPickable = function(mesh, id) {
|
|
var self = this;
|
|
|
|
if (!self.options.picking) {
|
|
return;
|
|
}
|
|
|
|
// Generate unique colour
|
|
self.pickingColour.setHex(self.pickingColourID);
|
|
|
|
// Apply colour to geom
|
|
// TODO: Does this cause issues with anything else using the geom reference?
|
|
self.applyVertexColors(mesh.geometry, self.pickingColour);
|
|
|
|
// Remove mesh from picking scene
|
|
self.pickingScene.remove(self.pickingMesh);
|
|
|
|
// Add geom to merged geom
|
|
self.pickingGeom.merge(mesh.geometry, mesh.matrix);
|
|
|
|
// Store reference to id and colour
|
|
self.pickingRef[self.pickingColourID] = {
|
|
id: id,
|
|
mesh: mesh
|
|
};
|
|
|
|
self.pickingMesh = new THREE.Mesh(self.pickingGeom, self.pickingMaterial);
|
|
|
|
// Update mesh in picking scene
|
|
self.pickingScene.add(self.pickingMesh);
|
|
|
|
// Increment picking colour ID
|
|
self.pickingColourID++;
|
|
};
|
|
|
|
VIZI.Scene.prototype.removePickable = function(id) {
|
|
var self = this;
|
|
|
|
if (!self.options.picking) {
|
|
return;
|
|
}
|
|
|
|
// TODO: Remove pickable geom from merged geom
|
|
// TODO: Remove reference to id and colour
|
|
// TODO: Update mesh in picking scene
|
|
};
|
|
|
|
VIZI.Scene.prototype.getPickable = function(id) {
|
|
var self = this;
|
|
|
|
if (!self.options.picking) {
|
|
return;
|
|
}
|
|
|
|
return self.pickingRef[id];
|
|
};
|
|
|
|
VIZI.Scene.prototype.remove = function(object) {
|
|
var self = this;
|
|
self.scene.remove(object);
|
|
};
|
|
|
|
VIZI.Scene.prototype.render = function(camera) {
|
|
var self = this;
|
|
|
|
if (!self.scene) {
|
|
throw new Error("Scene is required for render");
|
|
}
|
|
|
|
if (!camera) {
|
|
throw new Error("Camera is required for render");
|
|
}
|
|
|
|
self.renderer.render(self.scene, camera.camera);
|
|
};
|
|
|
|
VIZI.Scene.prototype.renderPicking = function(camera) {
|
|
var self = this;
|
|
|
|
if (!self.options.picking) {
|
|
return;
|
|
}
|
|
|
|
if (!self.pickingScene) {
|
|
throw new Error("Picking scene is required for render");
|
|
}
|
|
|
|
if (!camera) {
|
|
throw new Error("Camera is required for render");
|
|
}
|
|
|
|
self.renderer.render(self.pickingScene, camera.camera, self.pickingTexture);
|
|
};
|
|
|
|
// TODO: Update picking scene on resize
|
|
VIZI.Scene.prototype.resize = function(width, height) {
|
|
var self = this;
|
|
self.renderer.setSize(width, height);
|
|
};
|
|
|
|
// TODO: This is duplicated from VIZI.Layer, find a way to merge
|
|
VIZI.Scene.prototype.applyVertexColors = function( geom, colour ) {
|
|
geom.faces.forEach( function( f ) {
|
|
var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
|
|
for( var j = 0; j < n; j ++ ) {
|
|
f.vertexColors[ j ] = colour;
|
|
}
|
|
} );
|
|
};
|
|
})(); |