iv-3d-lib
Version:
A reusable ThreeJS library providing features for Ivee 3D Editor.
1,226 lines (1,219 loc) • 85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WglUtil = void 0;
const THREE = require("three");
const dat = require("dat-gui");
const stats_1 = require("./stats");
const cfg = require("./wgl-util-cfgs");
const OrbitControls = require("three-orbitcontrols");
// import OrbitControls from 'three-orbitcontrols';
const TrackballControls = require("three-trackballcontrols");
// import TrackballControls from 'three-trackballcontrols';
const leapControls = require("threeleapcontrols");
const StereoEffect = require("three-stereoeffect");
const AnaglyphEffect = require("three-anaglypheffect");
const AsciiEffect = require("three-asciieffect");
const css3d = require("three-css3drenderer");
const wgl_util_content_changed_args_1 = require("./wgl-util-content-changed-args");
const OBJLoader_js_1 = require("three/examples/js/loaders/OBJLoader.js");
class WglUtil {
constructor() {
this.leapObjectsControls = [];
this.objects = [];
this.parent = null;
this.mirrorCube = new THREE.Mesh;
this.cameraCfg = {
fov: 50, aspect: window.innerWidth / window.innerHeight, near: 0.1, far: 10000,
position: { x: 200, y: 200, z: 200 }
};
this.rendererCfg = {
color: 0xFF0000, alpha: 0.5, width: window.innerWidth, height: window.innerHeight, shadowMapEnabled: true, antialias: true,
useCanvas: false
};
this.sceneCfg = {
useFog: true, fogColor: 0xffffff, fogMistDensity: 0.015, showAxis: true, axisSize: 20, useAxisArrows: true, axisArrowHeadLength: 2,
showGrid: true, gridSize: 10, gridDivisions: 10, gridColorCenterLine: 0x444444, gridColor: 0x888888
};
this.orbitCfg = {
minDistance: -10000, maxDistance: 10000
};
this.trackballCfg = {
rotateSpeed: 1.0,
zoomSpeed: 1.2,
panSpeed: 0.8,
noZoom: false,
noPan: false,
staticMoving: true,
dynamicDampingFactor: 0.3
};
this.lightCfg = {
color: 0x0c0c0c, intensity: 0xffffff
};
this.dirLightCfg = {
color: 0xFFFFFF, intensity: 1.5, position: { x: 40, y: 60, z: -10 }, shadowCameraFov: 70, castShadow: true, showHelper: true, showHelperRuntime: false, size: 5
};
this.pointLightCfg = {
color: 0x00FF00, intensity: 3, distance: 150, position: { x: 70, y: 5, z: 70 }, helperSphereSize: 3, showHelper: true, showHelperRuntime: false
};
this.hemisphereLightCfg = {
skyColor: 0xFFFFFF, groundColor: 0xFFFFFF, intensity: 1, position: { x: 40, y: 60, z: -10 }, showHelper: true, showHelperRuntime: false
};
this.spotLightCfg = {
color: 0xFFFFFF, intensity: 3, distance: 150, position: { x: 70, y: 5, z: 70 }, showHelper: true, showHelperRuntime: false, angle: Math.PI / 2, penumbra: 0, decay: 0
};
this.lineCfg = {
start: { x: 0, y: 0, z: 0 }, end: { x: 10, y: 10, z: 10 }, color: Math.random() * 0xFFFFFF
};
this.planeCfg = {
width: 60, height: 20, widthSegments: 1, heightSegments: 1, color: Math.random() * 0xFFFFFF, position: { x: 0, y: 0, z: 0 },
receiveShadow: true
};
this.circleCfg = {
radius: 4, segments: 20, thetaStart: 0, thetaLength: 2 * Math.PI, color: Math.random() * 0xFFFFFF, wireframe: false, position: { x: 20, y: 4, z: 2 },
castShadow: true, rotation: { x: 0, y: 0, z: 0 }
};
this.cubeCfg = {
width: 4, height: 4, depth: 4, color: Math.random() * 0xFF0000, wireframe: false, position: { x: -4, y: 3, z: 0 },
widthSegments: 1, heightSegments: 1, depthSegments: 1,
castShadow: true, rotation: { x: 0, y: 0, z: 0 }, rotationSpeed: 0.5
};
this.sphereCfg = {
radius: 4, widthSegments: 20, heightSegments: 20, phiStart: 0, phiLength: 2 * Math.PI, thetaStart: 0, thetaLength: 2 * Math.PI,
color: Math.random() * 0xFF0000, wireframe: false, position: { x: 20, y: 4, z: 2 },
castShadow: true, rotation: { x: 0, y: 0, z: 0 }
};
this.cylinderCfg = {
radiusTop: 20, radiusBottom: 20, height: 100, radiusSegments: 8, heightSegments: 1, openEnded: false, thetaStart: 0, thetaLength: 2 * Math.PI, color: Math.random() * 0xFFFFFF,
position: { x: 0, y: 0, z: 0 }
};
this.torusCfg = {
radius: 8, tube: 4, radialSegments: 8, tubularSegments: 6, arc: 2 * Math.PI
};
this.torusKnotCfg = {
radius: 8, tube: 4, radialSegments: 8, tubularSegments: 6, p: 2, q: 3
};
this.pointsCfg = {
color: Math.random() * 0xFFFFFF, radius: 0.2, transparent: true, offset: { x: -15, y: -15, z: -15 }, step: { x: 30, y: 30, z: 30 }
};
this.pointsFromGeomCfg = {
color: 0x000000, size: 0.1, scale: 1
};
this.particleCfg = {
count: 100, size: 1, range: 500, transparent: true, opacity: 0.5, vertexColors: [], sizeAttenuation: true, color: 0xFF0000
};
this.textureCfg = {
srcDir: 'assets/textures/', position: { x: 0, y: 0, z: 0 }, width: 100, height: 100, autoplay: true, loop: true, video: null, texture: null,
canvas: { width: 200, height: 50, font: '24px Arial', text: '', textColor: '#000', backgroundColor: '#fff' }
};
this.shadersCfg = {
vertexShaderId: 'vertexShader', fragmentShaderId: 'fragmentShader', uniforms: {}, attributes: {}, srcDir: 'assets/shaders/glsl/'
};
this.skyBoxCfg = {
srcFile: 'assets/textures/skyboxsun25degtest.png', srcDir: 'assets/textures/sky1/', px: 'px.jpg', py: 'py.jpg', pz: 'pz.jpg', nx: 'nx.jpg', ny: 'ny.jpg', nz: 'nz.jpg', size: 1024,
width: 5000, height: 5000, depth: 5000
};
this.objModelCfg = {
srcDir: 'assets/models/'
};
this.textCfg = {
text: '',
height: 10, size: 50, hover: 30, curveSegments: 4, bevelEnabled: true, bevelThickness: 2, bevelSize: 1.5, bevelSegments: 3,
font: 'optimer',
weight: 'bold',
style: 'normal',
material: 0, extrudeMaterial: 1,
useMirror: false,
textMaterial: null,
textMesh: null, textMeshMirror: null,
offsetX: 0,
frontColor: null,
sideColor: null
};
/*
public gridHelperCfg: cfg.GridHelperCfg = <cfg.GridHelperCfg>{
size: 10,
divisions: 10,
colorCenterLine: 0x444444,
colorGrid: 0x888888
}
*/
this.matCfg = {
color: 0x000000, wireframe: false
};
this.spriteCfg = {
map: null, color: 0x000000
};
this.mirrorCubeCfg = {
near: 0.1, far: 10000, resolution: 1024,
dimension: { x: 4, y: 4, z: 1 },
position: { x: 100, y: 100, z: 100 }
};
this.mousePosition = new THREE.Vector2();
this.dndPlane = new THREE.Plane();
this.dndOffset = new THREE.Vector3();
this.dndIntersection = new THREE.Vector3();
this.Android = () => {
return navigator.userAgent.match(/Android/i);
};
this.BlackBerry = () => {
return navigator.userAgent.match(/BlackBerry/i);
};
this.iOS = () => {
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
};
this.Opera = () => {
return navigator.userAgent.match(/Opera Mini/i);
};
this.Windows = () => {
return navigator.userAgent.match(/IEMobile/i);
};
console.log(OBJLoader_js_1.OBJLoader);
this.cfg = {
useAxis: true,
useOrbit: true,
useTrackball: false,
useStats: true,
useDatGui: true,
statsId: 'stats',
canvasId: 'canvas',
useAsciiEffect: false,
useAnaglyphEffect: false,
anaglyphFocalLength: 125,
useGridHelper: false,
useStereoEffect: false,
useCssRender: false
};
this.glScene = null;
this.camera = null;
this.glRenderer = null;
this.raycaster = null;
this.orbitControls = null;
this.trackballControls = null;
this.axis = null;
this.stats = null;
this.dndSelectedObject = null;
this.dndIntersectedObject = null;
this.dndSelectedObjectBoxHelper = null;
}
copyCfg(srcCfg, destCfg) {
for (let p in srcCfg) {
if (destCfg.hasOwnProperty(p)) {
destCfg[p] = srcCfg[p];
}
}
}
isMobile() {
return {
Android: this.Android(),
Blackberry: this.BlackBerry(),
iOS: this.iOS(),
Opera: this.Opera(),
Windows: this.Windows(),
any: () => {
return (this.Android() || this.BlackBerry() || this.iOS() || this.Opera() || this.Windows());
}
};
}
static detectWebGL() {
try {
let canvas = document.createElement('canvas');
return !!(window['WebGLRenderingContext'] && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
}
catch (e) {
console.log('WglUtil.detectWebGL: ', e);
return false;
}
}
setOptions(cfg) {
if (cfg) {
this.copyCfg(cfg, this.cfg);
}
}
setOption(name, value) {
if (this.cfg.hasOwnProperty(name)) {
this.cfg[name] = value;
}
}
getUrl(url, onSuccess, onError) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
// Success!
// var data = JSON.parse(request.responseText);
let data = request.responseText;
if (onSuccess) {
onSuccess(data);
}
}
else {
let errMsg = 'Error returned from server';
console.error(errMsg, request);
if (onError) {
onError(new Error(errMsg));
}
}
};
request.onerror = (err) => {
console.error('Error returned from server', err);
if (onError) {
onError(err);
}
};
request.send();
}
init(sceneConfig, cameraConfig, rendererConfig, orbitCfg, trackballCfg) {
if (sceneConfig) {
this.copyCfg(sceneConfig, this.sceneCfg);
}
if (cameraConfig) {
this.copyCfg(cameraConfig, this.cameraCfg);
}
if (rendererConfig) {
this.copyCfg(rendererConfig, this.rendererCfg);
}
THREE.ImageUtils.crossOrigin = '';
this.glScene = new THREE.Scene();
if (this.rendererCfg.useCanvas) {
this.glRenderer = null; // new THREE.CanvasRenderer();
}
else {
this.glRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: this.rendererCfg.antialias });
}
this.glRenderer.setClearColor(this.rendererCfg.color, this.rendererCfg.alpha);
this.glRenderer.setSize(this.rendererCfg.width ? this.rendererCfg.width : window.innerWidth, this.rendererCfg.height ? this.rendererCfg.height : window.innerHeight); //renderer.width, renderer.height);
if (this.glRenderer.shadowMap)
this.glRenderer.shadowMap.enabled = this.rendererCfg.shadowMapEnabled;
this.setScene(sceneConfig);
this.camera = new THREE.PerspectiveCamera(this.cameraCfg.fov, this.cameraCfg.aspect, this.cameraCfg.near, this.cameraCfg.far);
this.setCamera(cameraConfig);
if (this.cfg.useOrbit)
this.initOrbit(orbitCfg);
if (this.cfg.useTrackball)
this.initTrackball(trackballCfg);
//if (this.cfg.useLeapCamera)
this.initLeapCamera(null);
this.raycaster = new THREE.Raycaster();
if (this.raycaster.setFromCamera)
this.raycaster.setFromCamera(this.mousePosition, this.camera);
if (this.cfg.useCssRender) {
this.setCssRenderer();
}
let canvas = document.getElementById(this.cfg.canvasId);
while (canvas.firstChild) {
canvas.removeChild(canvas.firstChild);
}
if (this.cfg.useAsciiEffect) {
this.setAsciiEffect();
}
else if (this.cfg.useAnaglyphEffect) {
this.setAnaglyphEffect();
}
else if (this.cfg.useStereoEffect) {
this.setStereoEffect();
}
else if (this.cfg.useCssRender) {
canvas.appendChild(this.cssRenderer.domElement);
this.cssRenderer.domElement.appendChild(this.glRenderer.domElement);
}
else {
canvas.appendChild(this.glRenderer.domElement);
}
// this.projector = new THREE.Projector();
this.render();
if (this.cfg.useDatGui) {
this.initDatGui();
}
if (this.cfg.useStats) {
this.initStats();
}
}
render() {
if (this.cfg.useAsciiEffect && this.asciiEffect) {
this.asciiEffect.render(this.glScene, this.camera);
}
else if (this.cfg.useAnaglyphEffect && this.anaglyphEffect) {
this.anaglyphEffect.render(this.glScene, this.camera);
}
else if (this.cfg.useStereoEffect && this.stereoEffect) {
this.stereoEffect.render(this.glScene, this.camera);
}
else if (this.cfg.useCssRender) {
this.glRenderer.render(this.glScene, this.camera);
this.cssRenderer.render(this.cssScene, this.camera);
}
else {
this.glRenderer.render(this.glScene, this.camera);
}
}
setCamera(cameraCfg, orbitCfg, trackballCfg) {
if (cameraCfg) {
this.copyCfg(cameraCfg, this.cameraCfg);
}
this.camera.fov = this.cameraCfg.fov;
this.camera.aspect = this.cameraCfg.aspect;
this.camera.near = this.cameraCfg.near;
this.camera.far = this.cameraCfg.far;
this.camera.position.x = this.cameraCfg.position.x;
this.camera.position.y = this.cameraCfg.position.y;
this.camera.position.z = this.cameraCfg.position.z;
//this.camera.lookAt(this.scene.position); //new THREE.Vector3(10, 0, 0)); //scene.position);
this.cameraHelper = new THREE.CameraHelper(this.camera);
this.cameraHelper.update();
// this.add(this.cameraHelper, null, false, false);
this.cameraHelper.visible = this.cameraCfg.showHelper;
}
setScene(sceneCfg) {
if (this.glScene.fog) {
this.glScene.fog = null;
}
if (sceneCfg) {
this.copyCfg(sceneCfg, this.sceneCfg);
}
if (this.sceneCfg.useFog) {
this.setFog(this.sceneCfg);
}
if (this.grid) {
this.removeGridHelper();
}
if (this.sceneCfg.showGrid) {
this.addGridHelper(this.sceneCfg);
}
if (this.axis) {
this.removeAxisHelper();
}
if (this.sceneCfg.showAxis) {
this.addAxisHelper(this.sceneCfg);
}
}
convertHex(hex, opacity) {
hex = hex.replace('#', '');
let r = parseInt(hex.substring(0, 2), 16);
let g = parseInt(hex.substring(2, 4), 16);
let b = parseInt(hex.substring(4, 6), 16);
let result = 'rgba(' + r + ',' + g + ',' + b + ',' + opacity / 100 + ')';
return result;
}
initStats() {
this.stats = new stats_1.Stats();
this.stats.setMode(0);
this.stats.domElement.style.position = 'absolute';
this.stats.domElement.style.left = '0px';
this.stats.domElement.style.top = '0px';
let statsElem = document.getElementById(this.cfg.statsId);
if (statsElem) {
statsElem.appendChild(this.stats.domElement);
}
return this.stats;
}
initOrbit(cfg) {
if (cfg) {
this.copyCfg(cfg, this.orbitCfg);
}
// Orbit controls
this.orbitControls = new OrbitControls(this.camera, this.glRenderer.domElement);
this.orbitControls.minDistance = this.orbitCfg.minDistance;
this.orbitControls.maxDistance = this.orbitCfg.maxDistance;
}
initTrackball(cfg) {
if (cfg) {
this.copyCfg(cfg, this.trackballCfg);
}
this.trackballControls = new TrackballControls(this.camera, this.glRenderer.domElement);
this.trackballControls.rotateSpeed = this.trackballCfg.rotateSpeed;
this.trackballControls.zoomSpeed = this.trackballCfg.zoomSpeed;
this.trackballControls.panSpeed = this.trackballCfg.panSpeed;
this.trackballControls.noZoom = this.trackballCfg.noZoom;
this.trackballControls.noPan = this.trackballCfg.noPan;
this.trackballControls.staticMoving = this.trackballCfg.staticMoving;
this.trackballControls.dynamicDampingFactor = this.trackballCfg.dynamicDampingFactor;
this.trackballControls.target.set(0, 0, 0);
}
initLeapCamera(cfg) {
//if(cfg) {
// this.copyCfg(cfg, this.leapCfg);
//}
// Leap camera controls
this.leapCameraControls = new leapControls.LeapCameraControls(this.camera);
}
initDatGui() {
this.guiControls = new function () {
//this.prop = 0;
};
this.datGui = new dat.GUI();
//datGui.add(controls, 'prop', 0, 0.5);
return this.guiControls;
}
addGuiFolder(name) {
var folder = this.datGui.addFolder(name);
return folder;
}
addGuiProp(folder, propName, value, min, max, values) {
this.guiControls[propName] = !cfg.U.isEmpty(value) ? value : '';
if (folder) {
if (!cfg.U.isEmpty(min) && !cfg.U.isEmpty(max))
return folder.add(this.guiControls, propName, min, max);
if (!cfg.U.isEmpty(min))
return folder.add(this.guiControls, propName, min);
if (values && values.length > 0)
return folder.add(this.guiControls, propName, values);
return folder.add(this.guiControls, propName);
}
else {
return this.datGui.add(this.guiControls, propName, min, max);
}
}
addGuiColorProp(folder, propName, value) {
this.guiControls[propName] = value;
if (folder) {
return folder.addColor(this.guiControls, propName);
}
else {
return this.datGui.add(this.guiControls, propName);
}
}
addGuiMethod(folder, methodName) {
let wglUtil = this;
if (folder) {
return folder.add(this.guiControls, methodName);
}
else {
return this.datGui.add(this.guiControls, methodName);
}
}
addGuiButton(folder, name, handler) {
let obj = {};
let wglUtil = this;
let parent = this.parent;
obj[name] = () => {
handler(wglUtil, parent);
};
if (folder) {
return folder.add(obj, name);
}
else {
return this.datGui.add(obj, name);
}
}
addGuiPropValues(folder, propName, value, values) {
this.guiControls[propName] = value;
if (folder) {
return folder.add(this.guiControls, propName, values);
}
else {
return this.datGui.add(this.guiControls, propName, values);
}
}
refreshGui() {
WglUtil.refreshDatGui(this.datGui);
/*
for (var i = 0; i < Object.keys(this.datGui.__folders).length; i++) {
var key = Object.keys(this.datGui.__folders)[i];
for (var j = 0; j < this.datGui.__folders[key].__controllers.length; j++) {
this.datGui.__folders[key].__controllers[j].updateDisplay();
}
}
*/
}
static refreshDatGui(datGui) {
for (var i = 0; i < Object.keys(datGui.__folders).length; i++) {
var key = Object.keys(datGui.__folders)[i];
for (var j = 0; j < datGui.__folders[key].__controllers.length; j++) {
datGui.__folders[key].__controllers[j].updateDisplay();
}
}
}
getGuiFolder(folderName) {
for (var i = 0; i < Object.keys(this.datGui.__folders).length; i++) {
var key = Object.keys(this.datGui.__folders)[i];
if (key === folderName) {
return this.datGui.__folders[i];
}
}
return null;
}
getGuiController(folderName, propName) {
let folder = this.getGuiFolder(folderName);
if (folder) {
for (var j = 0; j < folder.__controllers.length; j++) {
if (folder.__controllers[j].property === propName) {
return folder.__controllers[j];
}
}
}
return null;
}
removeDatGuiFolder(name) {
WglUtil.removeDatGuiFolder(this.datGui, name);
}
static removeDatGuiFolder(datGui, name) {
let folder = datGui.__folders[name];
if (!folder) {
return;
}
folder.close();
datGui.__ul.removeChild(folder.domElement.parentNode);
delete datGui.__folders[name];
datGui.onResize();
}
addAxisHelper(sceneCfg) {
if (this.axis) {
this.removeAxisHelper();
}
if (sceneCfg) {
this.copyCfg(sceneCfg, this.sceneCfg);
}
this.axis = new THREE.AxisHelper(this.sceneCfg.axisSize);
this.glScene.add(this.axis);
if (this.sceneCfg.useAxisArrows) {
this.axisArrowX = this.addAxisArrow({ x: 1, y: 0, z: 0 });
this.axisArrowY = this.addAxisArrow({ x: 0, y: 1, z: 0 });
this.axisArrowZ = this.addAxisArrow({ x: 0, y: 0, z: 1 });
}
}
addAxisArrow(axis) {
if (this.sceneCfg.useAxisArrows) {
let dir = new THREE.Vector3(axis.x, axis.y, axis.z);
let origin = new THREE.Vector3(0, 0, 0);
let length = this.sceneCfg.axisSize;
let hex = 0xffffff;
if (axis.x)
hex = 0xff0000;
if (axis.y)
hex = 0x00ff00;
if (axis.z)
hex = 0x0000ff;
let headLength = this.sceneCfg.axisArrowHeadLength;
let arrowHelper = new THREE.ArrowHelper(dir, origin, length, hex, headLength);
this.glScene.add(arrowHelper);
return arrowHelper;
}
}
removeAxisHelper() {
if (this.axis) {
this.remove(this.axis);
this.remove(this.axisArrowX);
this.remove(this.axisArrowY);
this.remove(this.axisArrowZ);
this.axis = null;
}
}
addDirLight(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.dirLightCfg);
}
let dirLightHelper = this.genDirLight(cfg);
this.add(dirLightHelper.light, group);
this.add(dirLightHelper, group);
return dirLightHelper;
}
addPointLight(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.pointLightCfg);
}
var pointLightHelper = this.genPointLight(cfg);
this.add(pointLightHelper.light, group);
this.add(pointLightHelper, group);
return pointLightHelper;
}
addHemisphereLight(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.hemisphereLightCfg);
}
let hemisphereLightHelper = this.genHemisphereLight(cfg);
this.add(hemisphereLightHelper.light, group);
this.add(hemisphereLightHelper, group);
return hemisphereLightHelper;
}
addSpotLight(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.spotLightCfg);
}
var spotLightHelper = this.genSpotLight(cfg);
this.add(spotLightHelper.light, group);
this.add(spotLightHelper, group);
return spotLightHelper;
}
getJson(group) {
let json = {};
try {
if (group) {
json = group.toJSON();
}
else {
json = this.glScene.toJSON();
}
}
catch (e) {
json = { error: e };
}
return json;
}
onContentChanged(object, group, type) {
let json = this.getJson(group);
let canvas = document.getElementById(this.cfg.canvasId);
if (!canvas)
return;
let args = new wgl_util_content_changed_args_1.WglUtilContentChangedArgs();
args.group = group;
args.object = object;
args.json = json;
args.type = type;
this.contentChanged = new CustomEvent('contentChanged', { 'detail': args });
canvas.dispatchEvent(this.contentChanged);
}
add(obj, group, raiseContentChanged = true, isSelectable = true) {
if (group) {
group.add(obj);
}
else {
this.glScene.add(obj);
}
if (isSelectable) {
this.objects.push(obj);
if (obj.children.length > 0) {
for (let child of obj.children) {
this.objects.push(child);
}
}
this.initLeapObjectControls(obj);
}
if (raiseContentChanged) {
this.onContentChanged(obj, group, wgl_util_content_changed_args_1.ContentChangedType.add);
}
}
addLight(lightHelper, group, raiseContentChanged = true, isSelectable = true) {
if (lightHelper) {
this.add(lightHelper.light, group, raiseContentChanged, isSelectable);
if (lightHelper.visible) {
this.add(lightHelper, group, raiseContentChanged, isSelectable);
}
}
}
remove(obj, group, raiseContentChanged = true) {
if (group) {
group.remove(obj);
}
else {
this.glScene.remove(obj);
}
if (obj.geometry && obj.geometry.dispose)
obj.geometry.dispose();
if (obj.material) {
if (obj.material.type !== 'MultiMaterial') {
if (obj.material.dispose)
obj.material.dispose();
}
else {
for (let mat of obj.material.materials) {
if (mat.dispose)
mat.dispose();
}
}
}
let index = this.objects.indexOf(obj);
if (index >= 0) {
this.objects.splice(index, 1);
}
delete obj.userData;
obj = null;
if (raiseContentChanged) {
this.onContentChanged(obj, group, wgl_util_content_changed_args_1.ContentChangedType.delete);
}
}
removeLight(lightHelper, group, raiseContentChanged = true) {
if (lightHelper) {
this.remove(lightHelper.light, group, raiseContentChanged);
this.remove(lightHelper, group, raiseContentChanged);
}
}
clear(group) {
let container = group ? group : this.glScene;
while (container.children.length > 0) {
container.remove(container.children[container.children.length - 1]);
}
this.onContentChanged(null, group, wgl_util_content_changed_args_1.ContentChangedType.clear);
}
genPlaneGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.planeCfg);
}
var geomPlane = new THREE.PlaneGeometry(this.planeCfg.width, this.planeCfg.height, this.planeCfg.widthSegments, this.planeCfg.heightSegments);
return geomPlane;
}
genCircleGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.circleCfg);
}
let geomCircle;
if (this.circleCfg.thetaStart && this.circleCfg.thetaLength) {
geomCircle = new THREE.CircleGeometry(this.circleCfg.radius, this.circleCfg.segments, this.circleCfg.thetaStart, this.circleCfg.thetaLength);
}
else {
geomCircle = new THREE.CircleGeometry(this.circleCfg.radius, this.circleCfg.segments);
}
return geomCircle;
}
genCubeGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.cubeCfg);
}
var geomCube = new THREE.BoxGeometry(this.cubeCfg.width, this.cubeCfg.height, this.cubeCfg.depth);
if (this.cubeCfg.widthSegments) {
geomCube.parameters.widthSegments = this.cubeCfg.widthSegments;
}
if (this.cubeCfg.heightSegments) {
geomCube.parameters.heightSegments = this.cubeCfg.heightSegments;
}
if (this.cubeCfg.depthSegments) {
geomCube.parameters.depthSegments = this.cubeCfg.depthSegments;
}
return geomCube;
}
genSphereGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.sphereCfg);
}
let geomSphere;
if (this.sphereCfg.phiStart && this.sphereCfg.phiLength && this.sphereCfg.thetaStart && this.sphereCfg.thetaLength) {
geomSphere = new THREE.SphereGeometry(this.sphereCfg.radius, this.sphereCfg.widthSegments, this.sphereCfg.heightSegments, this.sphereCfg.phiStart, this.sphereCfg.phiLength, this.sphereCfg.thetaStart, this.sphereCfg.thetaLength);
return geomSphere;
}
if (this.sphereCfg.phiStart && this.sphereCfg.phiLength) {
geomSphere = new THREE.SphereGeometry(this.sphereCfg.radius, this.sphereCfg.widthSegments, this.sphereCfg.heightSegments, this.sphereCfg.phiStart, this.sphereCfg.phiLength);
return geomSphere;
}
geomSphere = new THREE.SphereGeometry(this.sphereCfg.radius, this.sphereCfg.widthSegments, this.sphereCfg.heightSegments);
return geomSphere;
}
genCylinderGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.cylinderCfg);
}
var geomCylinder = new THREE.CylinderGeometry(this.cylinderCfg.radiusTop, this.cylinderCfg.radiusBottom, this.cylinderCfg.height, this.cylinderCfg.radiusSegments, this.cylinderCfg.heightSegments, this.cylinderCfg.openEnded, this.cylinderCfg.thetaStart, this.cylinderCfg.thetaLength);
//cylinderCfg.segmentsX, cylinderCfg.segmentsY);
geomCylinder.parameters.height = this.cylinderCfg.height;
return geomCylinder;
}
genTorusGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.torusCfg);
}
var geomTorus = new THREE.TorusGeometry(this.torusCfg.radius, this.torusCfg.tube, this.torusCfg.radialSegments, this.torusCfg.tubularSegments, this.torusCfg.arc);
return geomTorus;
}
genTorusKnotGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.torusKnotCfg);
}
var geomTorusKnot = new THREE.TorusKnotGeometry(this.torusKnotCfg.radius, this.torusKnotCfg.tube, this.torusKnotCfg.radialSegments, this.torusKnotCfg.tubularSegments, this.torusKnotCfg.p, this.torusKnotCfg.q);
return geomTorusKnot;
}
genLineGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.lineCfg);
}
var geomLine = new THREE.BufferGeometry();
geomLine.vertices.push(new THREE.Vector3(this.lineCfg.start.x, this.lineCfg.start.y, this.lineCfg.start.z), new THREE.Vector3(this.lineCfg.end.x, this.lineCfg.end.y, this.lineCfg.end.z));
return geomLine;
}
genTextGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.textCfg);
}
var textGeom = new THREE.TextGeometry(this.textCfg.text, {
size: this.textCfg.size,
height: this.textCfg.height,
curveSegments: this.textCfg.curveSegments,
font: this.textCfg.font,
// weight: this.textCfg.weight,
// style: this.textCfg.style,
bevelThickness: this.textCfg.bevelThickness,
bevelSize: this.textCfg.bevelSize,
bevelEnabled: this.textCfg.bevelEnabled,
});
textGeom.computeBoundingBox();
textGeom.computeVertexNormals();
this.textCfg.geometry = textGeom;
// 'fix' side normals by removing z-component of normals for side faces
// (this doesn't work well for beveled geometry as then we lose nice curvature around z-axis)
if (!this.textCfg.bevelEnabled) {
console.log('bevel disabled not yet supported');
return textGeom;
/*
var triangleAreaHeuristics = 0.1 * (this.textCfg.height * this.textCfg.size);
for (var i = 0; i < textGeom.faces.length; i++) {
var face = textGeom.faces[i];
if (face.materialIndex == 1) {
for (var j = 0; j < face.vertexNormals.length; j++) {
face.vertexNormals[j].z = 0;
face.vertexNormals[j].normalize();
}
var va = textGeom.vertices[face.a];
var vb = textGeom.vertices[face.b];
var vc = textGeom.vertices[face.c];
var s = THREE.GeometryUtils.triangleArea(va, vb, vc);
if (s > triangleAreaHeuristics) {
for (var j = 0; j < face.vertexNormals.length; j++) {
face.vertexNormals[j].copy(face.normal);
}
}
}
}
*/
}
return textGeom;
}
genParticleGeom(cfg) {
if (cfg) {
this.copyCfg(cfg, this.particleCfg);
}
var geom = new THREE.BufferGeometry();
var range = this.particleCfg.range;
var vertices = [];
var colors = [];
for (var i = 0; i < this.particleCfg.count; i++) {
// var particle = new THREE.Vector3(
// Math.random() * range - range / 2,
// Math.random() * range - range / 2,
// Math.random() * range - range / 2
// );
let x = Math.random() * range - range / 2;
let y = Math.random() * range - range / 2;
let z = Math.random() * range - range / 2;
// particle.userData = 'Particle ' + i;
vertices.push(x, y, z);
var color = new THREE.Color(this.particleCfg.color);
color.setHSL(Math.random(), 1.0, 0.5);
colors.push(color.r, color.g, color.b);
}
geom.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
geom.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
return geom;
}
genMeshBasicMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.matCfg);
}
var matCube = new THREE.MeshBasicMaterial({ color: this.matCfg.color, wireframe: this.matCfg.wireframe });
return matCube;
}
genMeshLambertMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.matCfg);
}
var matCube = new THREE.MeshLambertMaterial({ color: this.matCfg.color, wireframe: this.matCfg.wireframe });
return matCube;
}
genMeshPhongMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.matCfg);
}
var matCube = new THREE.MeshPhongMaterial({ color: this.matCfg.color, wireframe: this.matCfg.wireframe });
return matCube;
}
genLineBasicMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.matCfg);
}
var matLine = new THREE.LineBasicMaterial({ color: this.matCfg.color });
return matLine;
}
genLineDashedMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.matCfg);
}
var matLine = new THREE.LineDashedMaterial({ color: this.matCfg.color });
return matLine;
}
genTextMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.textCfg);
}
let mat = new THREE.MultiMaterial([
new THREE.MeshPhongMaterial({ color: this.textCfg.frontColor !== null ? this.textCfg.frontColor : Math.random() * 0xffffff, shading: THREE.FlatShading }),
new THREE.MeshPhongMaterial({ color: this.textCfg.sideColor !== null ? this.textCfg.sideColor : 0xffffff, shading: THREE.SmoothShading }) // side
]);
if (this.textCfg.textMaterial == null) {
this.textCfg.textMaterial = mat;
}
return mat;
}
genParticleMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.particleCfg);
}
var material = new THREE.PointsMaterial({
size: this.particleCfg.size,
transparent: this.particleCfg.transparent,
opacity: this.particleCfg.opacity,
vertexColors: THREE.VertexColors,
sizeAttenuation: this.particleCfg.sizeAttenuation,
// color: color,
//, map: THREE.ImageUtils.loadTexture('assets/textures/heart2.png'),
blending: THREE.AdditiveBlending,
alphaTest: 0.5
});
// material.color = new THREE.Color(0xFF0000); // .setHSL( 1.0, 0.3, 0.7 );
return material;
}
genSpriteMat(cfg) {
if (cfg) {
this.copyCfg(cfg, this.spriteCfg);
}
let oCfg = {};
if (this.spriteCfg.map)
oCfg['map'] = this.spriteCfg.map;
if (this.spriteCfg.color)
oCfg['color'] = this.spriteCfg.color;
let mat = new THREE.SpriteMaterial(oCfg);
return mat;
}
genPointLight(cfg) {
if (cfg) {
this.copyCfg(cfg, this.pointLightCfg);
}
var pointLight = new THREE.PointLight(this.pointLightCfg.color, this.pointLightCfg.intensity, this.pointLightCfg.distance);
pointLight.position.set(this.pointLightCfg.position.x, this.pointLightCfg.position.y, this.pointLightCfg.position.z);
this.pointLightCfg.helper = new THREE.PointLightHelper(pointLight, this.pointLightCfg.helperSphereSize);
this.pointLightCfg.helper.visible = this.pointLightCfg.showHelper;
return this.pointLightCfg.helper;
}
genDirLight(cfg) {
if (cfg) {
this.copyCfg(cfg, this.dirLightCfg);
}
var dirLight = new THREE.DirectionalLight(this.dirLightCfg.color, this.dirLightCfg.intensity);
dirLight.position.set(this.dirLightCfg.position.x, this.dirLightCfg.position.y, this.dirLightCfg.position.z);
// dirLight.shadow.camera.fov = this.dirLightCfg.shadowCameraFov;
dirLight.castShadow = this.dirLightCfg.castShadow;
this.dirLightCfg.helper = new THREE.DirectionalLightHelper(dirLight, this.dirLightCfg.size);
this.dirLightCfg.helper.visible = this.dirLightCfg.showHelper;
return this.dirLightCfg.helper;
}
genHemisphereLight(cfg) {
if (cfg) {
this.copyCfg(cfg, this.hemisphereLightCfg);
}
var hempisphereLight = new THREE.HemisphereLight(this.hemisphereLightCfg.skyColor, this.hemisphereLightCfg.groundColor, this.hemisphereLightCfg.intensity);
hempisphereLight.position.set(this.hemisphereLightCfg.position.x, this.hemisphereLightCfg.position.y, this.hemisphereLightCfg.position.z);
this.hemisphereLightCfg.helper = new THREE.HemisphereLightHelper(hempisphereLight, this.hemisphereLightCfg.helperSphereSize);
this.hemisphereLightCfg.helper.visible = this.hemisphereLightCfg.showHelper;
return this.hemisphereLightCfg.helper;
}
genSpotLight(cfg) {
if (cfg) {
this.copyCfg(cfg, this.spotLightCfg);
}
var spotLight = new THREE.SpotLight(this.spotLightCfg.color, this.spotLightCfg.intensity, this.spotLightCfg.distance);
spotLight.position.set(this.spotLightCfg.position.x, this.spotLightCfg.position.y, this.spotLightCfg.position.z);
this.spotLightCfg.helper = new THREE.SpotLightHelper(spotLight);
this.spotLightCfg.helper.visible = this.spotLightCfg.showHelper;
return this.spotLightCfg.helper;
}
addLine(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.lineCfg);
}
var geomLine = this.genLineGeom(cfg);
var matLine = this.genLineBasicMat(cfg);
var line = new THREE.Line(geomLine, matLine);
this.add(line, group);
return line;
}
addPlane(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.planeCfg);
}
// var geomPlane = new THREE.PlaneBufferGeometry(this.planeCfg.width, this.planeCfg.height, this.planeCfg.widthSegments, this.planeCfg.heightSegments);
var geomPlane = this.genPlaneGeom(cfg);
var matPlane = this.genMeshBasicMat(cfg);
var plane = new THREE.Mesh(geomPlane, matPlane);
//plane.rotation.x = -0.5 * Math.PI;
plane.position.x = this.planeCfg.position.x;
plane.position.y = this.planeCfg.position.y;
plane.position.z = this.planeCfg.position.z;
plane.receiveShadow = this.planeCfg.receiveShadow;
this.add(plane, group);
return plane;
}
addCircle(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.circleCfg);
}
var geomCircle = this.genCircleGeom(cfg);
var matCircle = this.genMeshBasicMat(cfg);
var circle = new THREE.Mesh(geomCircle, matCircle);
circle.position.x = this.circleCfg.position.x;
circle.position.y = this.circleCfg.position.y;
circle.position.z = this.circleCfg.position.z;
circle.castShadow = this.circleCfg.castShadow;
if (this.circleCfg.rotation) {
circle.rotation.x = this.circleCfg.rotation.x;
circle.rotation.y = this.circleCfg.rotation.y;
circle.rotation.z = this.circleCfg.rotation.z;
}
this.add(circle, group);
return circle;
}
addCube(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.cubeCfg);
}
var geomCube = this.genCubeGeom(cfg); // new THREE.BoxGeometry(cubeCfg.width, cubeCfg.height, cubeCfg.depth);
var matCube = this.genMeshBasicMat(cfg);
var cube = new THREE.Mesh(geomCube, matCube);
cube.position.x = this.cubeCfg.position.x;
cube.position.y = this.cubeCfg.position.y;
cube.position.z = this.cubeCfg.position.z;
cube.castShadow = this.cubeCfg.castShadow;
if (this.cubeCfg.rotation) {
cube.rotation.x = this.cubeCfg.rotation.x;
cube.rotation.y = this.cubeCfg.rotation.y;
cube.rotation.z = this.cubeCfg.rotation.z;
}
this.add(cube, group);
return cube;
}
addSphere(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.sphereCfg);
}
var geomSphere = this.genSphereGeom(cfg); // new THREE.SphereGeometry(sphereCfg.radius, sphereCfg.widthSegments, sphereCfg.heightSegments);
var matSphere = this.genMeshBasicMat(cfg);
var sphere = new THREE.Mesh(geomSphere, matSphere);
sphere.position.x = this.sphereCfg.position.x;
sphere.position.y = this.sphereCfg.position.y;
sphere.position.z = this.sphereCfg.position.z;
sphere.castShadow = this.sphereCfg.castShadow;
this.add(sphere, group);
return sphere;
}
addCylinder(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.cylinderCfg);
}
var geomCylinder = this.genCylinderGeom(cfg);
var matCylinder = this.genMeshBasicMat(cfg);
var cylinder = new THREE.Mesh(geomCylinder, matCylinder);
cylinder.position.x = this.cylinderCfg.position.x;
cylinder.position.y = this.cylinderCfg.position.y;
cylinder.position.z = this.cylinderCfg.position.z;
cylinder.castShadow = this.cylinderCfg.castShadow;
this.add(cylinder, group);
return cylinder;
}
addTorus(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.torusCfg);
}
var geomTorus = this.genTorusGeom(cfg);
var matTorus = this.genMeshBasicMat(cfg);
var torus = new THREE.Mesh(geomTorus, matTorus);
this.add(torus, group);
return torus;
}
addTorusKnot(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.torusCfg);
}
var geomTorusKnot = this.genTorusKnotGeom(cfg);
var matTorusKnot = this.genMeshBasicMat(cfg);
var torusKnot = new THREE.Mesh(geomTorusKnot, matTorusKnot);
this.add(torusKnot, group);
return torusKnot;
}
addParticles(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.particleCfg);
}
let geom = this.genParticleGeom(cfg);
let material = this.genParticleMat(cfg);
let system = new THREE.Points(geom, material);
this.add(system, group);
return system;
}
addSprite(cfg, group) {
if (cfg) {
this.copyCfg(cfg, this.spriteCfg);
}
var matSprite = this.genSpriteMat(cfg);
var sprite = new THREE.Sprite(matSprite);
sprite.position.x = this.spriteCfg.position.x;
sprite.position.y = this.spriteCfg.position.y;
sprite.position.z = this.spriteCfg.position.z;
this.add(sprite, group);
return sprite;
}
addTextSprite(spriteCfg, textureCfg, group) {
let texture = this.createCanvasTexture(null, textureCfg);
spriteCfg.map = texture;
let matSprite = this.genSpriteMat(spriteCfg);
let sprite = new THREE.Sprite(matSprite);
var textObject = new THREE.Object3D();
let textWidth = textureCfg.canvas.width;
let textHeight = textureCfg.canvas.height;
let fontSize = textureCfg.canvas.fontSize;
// textObject.textHeight = fontSize;
// textObject.textWidth = (textWidth / textHeight) * textObject.textHeight;
sprite.scale.set(textWidth / textHeight * fontSize, fontSize, 1);
// sprite.position.set(10,10,0);
textObject.add(sprite);
this.add(textObject, group);
sprite.position.x = spriteCfg.position.x;
sprite.position.y = spriteCfg.position.y;
sprite.position.z = spriteCfg.position.z;
// this.add(sprite, group);
// return textObject;
return sprite;
}
addMesh(geom, mat, group) {
let mesh = new THREE.Mesh(geom, mat);
this.add(mesh, group);
return mesh;
}
addParticleMesh(geom, mat, group) {
let particles = new THREE.Points(geom, mat);
this.add(particles, group);
return particles;
}
setAsciiEffect() {
this.asciiEffect = new AsciiEffect(this.glRenderer);
this.asciiEffect.setSize(window.innerWidth, window.innerHeight);
let canvas = document.getElementById(this.cfg.canvasId);
while (canvas.children.length > 0) {
canvas.removeChild(canvas.children[0]);
}
canvas.appendChild(this.asciiEffect.domElement);
}
setAnaglyphEffect() {
var width = window.innerWidth || 2;
var height = window.innerHeight || 2;
this.anaglyphEffect = new AnaglyphEffect(this.glRenderer, this.cfg.anaglyphFocalLength, window.innerWidth, window.innerHeight);
this.anaglyphEffect.setSize(width, height);
let canvas = document.getElementById(this.cfg.canvasId);
canvas.appendChild(this.glRenderer.domElement);
}
setStereoEffect() {
let width = window.innerWidth;
let height = window.innerHeight;
this.stereoEffect = new StereoEffect(this.glRenderer);
this.stereoEffect.eyeSeparation = 1;
this.stereoEffect.setSize(width, height);
let canvas = document.getElementById(this.cfg.canvasId);
canvas.appendChild(this.glRenderer.domElement);
}
unsetEffects() {
let width = window.innerWidth;
let height = window.innerHeight;
this.glRenderer.setViewport(0, 0, width, height);
}
setFog(sceneConfig) {
if (this.glScene.fog) {
this.glScene.fog;
this.glScene.fog = null;
}
if (sceneConfig) {
this.copyCfg(sceneConfig, this.sceneCfg);
}
if (this.sceneCfg.useFog