w3d
Version:
Framework to create 3D web pages.
193 lines (161 loc) • 4.96 kB
JavaScript
/*
* engine.js
* Copyright 2017 Lucas Neves <lcneves@gmail.com>
*
* Engine for the Livre project based on WebGL and three.js
*/
;
const THREE = require('three');
const theme = require('./theme.js');
const Object3D = require('./object3d.js');
const Body = require('./body.js');
const Camera = require('./camera.js');
const windowUtils = require('./window-utils.js');
const messages = require('./messages.js');
const far =
theme.worldWidth / (2 * Math.tan(theme.hfov / 2 * Math.PI / 180 ));
const dimensions = {
width: theme.worldWidth ? theme.worldWidth : 100,
far: far,
near: far * theme.nearFarRatio
};
windowUtils.init(
theme.worldWidth,
dimensions.far - dimensions.near,
window.innerWidth,
window.innerHeight
);
var updatables = [];
var scene;
var camera = new Camera(
window.innerWidth / window.innerHeight,
theme.hfov,
dimensions
);
var body = new Body();
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Resize canvas on window resize
window.addEventListener('resize', function () {
var aspectRatio = window.innerWidth / window.innerHeight;
windowUtils.windowWidth = window.innerWidth;
windowUtils.windowHeight = window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
for (let updatable of updatables) {
updatable._update();
}
if (camera) {
camera.aspectRatio = aspectRatio;
}
if (body) {
messages.setMessage('needsArrange', body);
}
});
require('./utils/click.js')(THREE, renderer, camera, body);
function arrangeObjects () {
var objectToArrange = messages.getMessage('needsArrange');
if (typeof objectToArrange === 'object' &&
typeof objectToArrange.arrange === 'function')
{
objectToArrange.arrange();
objectToArrange.alignChildren();
messages.setMessage('needsArrange', false);
}
}
function render () {
arrangeObjects();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function resetScene () {
scene = new THREE.Scene();
if (theme.background) {
scene.background = new THREE.Color(theme.background);
}
function configDirectionalLight (light) {
light.position.set(
dimensions.width / 2,
- dimensions.width / (2 * windowUtils.aspectRatio),
dimensions.near
);
light.shadow.camera.left = - dimensions.width / 2;
light.shadow.camera.right = dimensions.width / 2;
light.shadow.camera.bottom = - dimensions.width /
(2 * windowUtils.aspectRatio);
light.shadow.camera.top = dimensions.width /
(2 * windowUtils.aspectRatio);
light.shadow.camera.near = 0;
light.shadow.camera.far = dimensions.far - dimensions.near;
light.shadow.camera.updateProjectionMatrix();
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
}
function configLightTarget (target) {
target.position.set(
dimensions.width / 2,
- dimensions.width / (2 * windowUtils.aspectRatio),
0
);
}
for (let light of theme.lights) {
let newLight;
switch (light.type) {
case 'ambient':
newLight = new THREE.AmbientLight(
light.color ? light.color : 0xffffff,
light.intensity ? light.intensity : 0.6
);
break;
case 'directional': {
newLight = new THREE.DirectionalLight(
light.color ? light.color : 0xffffff,
light.intensity ? light.intensity : 0.4
);
newLight.castShadow = true;
newLight._update = function () { configDirectionalLight(this); };
updatables.push(newLight);
newLight._update();
let targetObject = new THREE.Object3D();
targetObject._update = function () { configLightTarget(this); };
updatables.push(targetObject);
targetObject._update();
scene.add(targetObject);
newLight.target = targetObject;
break;
}
case 'point':
// PointLight( color, intensity, distance, decay )
newLight = new THREE.PointLight(
light.color ? light.color : 0xffffff,
light.intensity ? light.intensity : 0.2,
light.distance ? light.distance : 0,
light.decay ? light.decay : 0
);
newLight.position.set(-10, 10, 100);
newLight.castShadow = true;
break;
}
if (newLight) {
scene.add(newLight);
}
}
body = new Body(window.innerWidth / window.innerHeight, dimensions);
scene.add(body);
render();
}
function importTemplate(templateName, parentObject) {
parentObject = parentObject || body;
parentObject.add(new Object3D({
template: templateName,
setParent: parentObject
}), { rearrange: true });
}
module.exports = {
reset: resetScene,
importTemplate: importTemplate
};