awv3
Version:
⚡ AWV3 embedded CAD
198 lines (174 loc) • 6.58 kB
JavaScript
import * as THREE from 'three';
import Object3 from '../three/object3';
import { Pool } from '../session/helpers';
import { exponential } from '../animation/easing';
export default class Presentation extends Pool {
constructor(args) {
super(args);
this.options = {
shadows: true,
lights: true,
ambient: 0,
light: 0.95,
shadowHeight: 0.9,
shadowFactor: 1.2,
...args
};
this._objects = new Objects({ pool: this });
super.add(this._objects);
if (this.options.shadows) {
this._stage = new Stage({ pool: this });
super.add(this._stage);
}
if (this.options.lights) {
this._lights = new Lights({ pool: this });
super.add(this._lights);
}
}
add(args) {
this._objects.add(args);
}
addAsync(args) {
return this._objects.addAsync(args);
}
remove(args) {
this._objects.remove(args);
}
removeAsync(args) {
return this._objects.removeAsync(args);
}
update() {
if (this.view) {
this._objects.update();
this.options.lights && this._lights.update();
this.options.shadows && this._stage.update();
}
}
}
class Lights extends THREE.Group {
constructor({ pool }) {
super();
this.name = 'presentation.lights';
this.pool = pool;
this.interactive = false;
this.tweens = false;
this.measurable = false;
if (this.pool.options.ambient) {
this.ambient = new THREE.AmbientLight(0xffffff, this.pool.options.ambient);
this.add(this.ambient);
}
this.point1 = new THREE.DirectionalLight(0xffffff);
this.point1.target = pool._objects;
this.add(this.point1);
this.point2 = new THREE.DirectionalLight(0xffffff);
this.point2.target = pool._objects;
this.add(this.point2);
this.point3 = new THREE.DirectionalLight(0xffffff);
this.point3.target = pool._objects;
this.add(this.point3);
this.point4 = new THREE.DirectionalLight(0xffffff);
this.point4.target = pool._objects;
this.add(this.point4);
this.spot1 = new THREE.SpotLight(0xffffff);
this.add(this.spot1);
this.spot2 = new THREE.SpotLight(0xffffff);
this.spot2.target = pool._objects;
this.spot2.castShadow = true;
this.spot2.penumbra = 1;
this.spot2.shadow = new THREE.LightShadow(new THREE.PerspectiveCamera(20, 1, 100, 1000));
this.spot2.shadow.mapSize.width = 2048;
this.spot2.shadow.mapSize.height = 2048;
this.add(this.spot2);
}
update() {
if (this.pool.parent) {
this.quaternion.setFromUnitVectors(this.up, this.pool.view.camera.up);
if (this.pool.options.ambient) {
this.ambient.intensity = this.pool.options.ambient;
}
let radius = this.pool._objects.radius;
let intensity = this.pool.options.light;
let vec = this.pool.parent.worldToLocal(new THREE.Vector3(-radius / 2, radius, radius / 2));
this.point1.intensity = intensity / 2;
this.point1.setPosition(-radius, 0, 0);
this.point2.intensity = intensity / 2;
this.point2.setPosition(radius, 0, 0);
this.point3.intensity = intensity / 2;
this.point3.setPosition(0, radius, 0);
this.point4.intensity = intensity / 2;
this.point4.setPosition(0, 0, radius);
this.spot1.intensity = intensity / 2;
this.spot1.setPosition(0, -radius, -radius * 2);
this.spot2.intensity = intensity * 3;
this.spot2.position.copy(vec);
this.spot2.shadow.camera.far = radius * 1.5;
this.spot2.shadow.camera.updateProjectionMatrix();
this.spot2.insensity = intensity;
this.spot2.distance = radius * 1.5;
this.spot2.angle = Math.PI / 6;
}
}
}
class Stage extends THREE.Group {
constructor({ pool }) {
super();
this.name = 'presentation.stage';
this.pool = pool;
this.interactive = false;
this.tweens = false;
this.measurable = false;
}
update() {
this.destroy();
if (!isNaN(this.pool._objects.width) && !isNaN(this.pool._objects.depth)) {
this.quaternion.setFromUnitVectors(new THREE.Vector3(0, 0, 1), this.pool.view.camera.up);
this.position.copy(this.pool._objects.getCenter());
this.position.addScaledVector(this.pool.view.camera.up, -this.pool._objects.height * this.pool.options.shadowHeight);
var shadowGeo = new THREE.PlaneBufferGeometry(
this.pool._objects.width * this.pool.options.shadowFactor,
this.pool._objects.depth * this.pool.options.shadowFactor,
1,
1
);
var mesh = new THREE.Mesh(shadowGeo, shadowMaterial);
this.add(mesh);
}
}
}
class Objects extends THREE.Group {
constructor({ pool }) {
super();
this.name = 'presentation.objects';
this.pool = pool;
}
update() {
this.updateBounds();
this.min = this.bounds.box.min;
this.max = this.bounds.box.max;
this.width = this.max.distanceTo(new THREE.Vector3(this.min.x, this.max.y, this.max.z));
this.height = this.max.distanceTo(new THREE.Vector3(this.max.x, this.min.y, this.max.z));
this.depth = this.max.distanceTo(new THREE.Vector3(this.max.x, this.max.y, this.min.z));
this.radius = this.getRadius() * 6;
}
}
function createShadowMaterial() {
var canvas2d = document.createElement('canvas');
canvas2d.width = 128;
canvas2d.height = 128;
var context = canvas2d.getContext('2d');
var gradient = context.createRadialGradient(
canvas2d.width / 2,
canvas2d.height / 2,
0,
canvas2d.width / 2,
canvas2d.height / 2,
canvas2d.width / 2
);
gradient.addColorStop(0.1, 'rgba(0,0,0,0.15)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
context.fillStyle = gradient;
context.fillRect(0, 0, canvas2d.width, canvas2d.height);
var shadowTexture = new THREE.CanvasTexture(canvas2d);
return new THREE.MeshBasicMaterial({ map: shadowTexture, transparent: true });
}
const shadowMaterial = createShadowMaterial();