1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00
trois/build/trois.js

2989 lines
82 KiB
JavaScript
Raw Normal View History

2021-03-04 04:49:22 +08:00
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
var three = require('three');
var OrbitControls_js = require('three/examples/jsm/controls/OrbitControls.js');
2021-03-08 04:17:46 +08:00
var RectAreaLightUniformsLib_js = require('three/examples/jsm/lights/RectAreaLightUniformsLib.js');
var RectAreaLightHelper_js = require('three/examples/jsm/helpers/RectAreaLightHelper.js');
2021-03-14 02:34:34 +08:00
var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
var FBXLoader_js = require('three/examples/jsm/loaders/FBXLoader.js');
2021-03-04 04:49:22 +08:00
var EffectComposer_js = require('three/examples/jsm/postprocessing/EffectComposer.js');
var RenderPass_js = require('three/examples/jsm/postprocessing/RenderPass.js');
var BokehPass_js = require('three/examples/jsm/postprocessing/BokehPass.js');
var FilmPass_js = require('three/examples/jsm/postprocessing/FilmPass.js');
var ShaderPass_js = require('three/examples/jsm/postprocessing/ShaderPass.js');
var FXAAShader_js = require('three/examples/jsm/shaders/FXAAShader.js');
var HalftonePass_js = require('three/examples/jsm/postprocessing/HalftonePass.js');
var SMAAPass_js = require('three/examples/jsm/postprocessing/SMAAPass.js');
2021-04-05 04:02:11 +08:00
var SSAOPass_js = require('three/examples/jsm/postprocessing/SSAOPass.js');
2021-03-04 04:49:22 +08:00
var UnrealBloomPass_js = require('three/examples/jsm/postprocessing/UnrealBloomPass.js');
2021-04-05 04:02:11 +08:00
function useRaycaster(options) {
const {
camera,
resetPosition = new three.Vector3(0, 0, 0),
} = options;
const raycaster = new three.Raycaster();
const position = resetPosition.clone();
const plane = new three.Plane(new three.Vector3(0, 0, 1), 0);
const updatePosition = (coords) => {
raycaster.setFromCamera(coords, camera);
camera.getWorldDirection(plane.normal);
raycaster.ray.intersectPlane(plane, position);
};
const intersect = (coords, objects) => {
raycaster.setFromCamera(coords, camera);
return raycaster.intersectObjects(objects);
};
return {
position,
updatePosition,
intersect,
};
}
function usePointer(options) {
const {
camera,
domElement,
intersectObjects,
touch = true,
resetOnEnd = false,
resetPosition = new three.Vector2(0, 0),
resetPositionV3 = new three.Vector3(0, 0, 0),
onEnter = () => {},
onMove = () => {},
onLeave = () => {},
onIntersectEnter = () => {},
onIntersectOver = () => {},
onIntersectMove = () => {},
onIntersectLeave = () => {},
onIntersectClick = () => {},
} = options;
const position = resetPosition.clone();
const positionN = new three.Vector2(0, 0);
const raycaster = useRaycaster({ camera });
const positionV3 = raycaster.position;
const obj = {
position,
positionN,
positionV3,
intersectObjects,
listeners: false,
addListeners,
removeListeners,
intersect,
};
return obj;
function reset() {
position.copy(resetPosition);
positionV3.copy(resetPositionV3);
}
function updatePosition(event) {
let x, y;
if (event.touches && event.touches.length > 0) {
x = event.touches[0].clientX;
y = event.touches[0].clientY;
} else {
x = event.clientX;
y = event.clientY;
}
const rect = domElement.getBoundingClientRect();
position.x = x - rect.left;
position.y = y - rect.top;
positionN.x = (position.x / rect.width) * 2 - 1;
positionN.y = -(position.y / rect.height) * 2 + 1;
raycaster.updatePosition(positionN);
}
function intersect() {
if (intersectObjects.length) {
const intersects = raycaster.intersect(positionN, intersectObjects);
const offObjects = [...intersectObjects];
const iMeshes = [];
intersects.forEach(intersect => {
const { object } = intersect;
const { component } = object;
// only once for InstancedMesh
if (object instanceof three.InstancedMesh) {
if (iMeshes.indexOf(object) !== -1) return;
iMeshes.push(object);
}
if (!object.over) {
object.over = true;
const overEvent = { type: 'pointerover', over: true, component, intersect };
const enterEvent = { ...overEvent, type: 'pointerenter' };
onIntersectOver(overEvent);
onIntersectEnter(enterEvent);
component.onPointerOver?.(overEvent);
component.onPointerEnter?.(enterEvent);
}
const moveEvent = { type: 'pointermove', component, intersect };
onIntersectMove(moveEvent);
component.onPointerMove?.(moveEvent);
offObjects.splice(offObjects.indexOf(object), 1);
});
offObjects.forEach(object => {
const { component } = object;
if (object.over) {
object.over = false;
const overEvent = { type: 'pointerover', over: false, component };
const leaveEvent = { ...overEvent, type: 'pointerleave' };
onIntersectOver(overEvent);
onIntersectLeave(leaveEvent);
component.onPointerOver?.(overEvent);
component.onPointerLeave?.(leaveEvent);
}
});
}
}
function pointerEnter(event) {
updatePosition(event);
onEnter({ type: 'pointerenter', position, positionN, positionV3 });
}
function pointerMove(event) {
updatePosition(event);
onMove({ type: 'pointermove', position, positionN, positionV3 });
intersect();
}
function pointerClick(event) {
updatePosition(event);
if (intersectObjects.length) {
const intersects = raycaster.intersect(positionN, intersectObjects);
const iMeshes = [];
intersects.forEach(intersect => {
const { object } = intersect;
const { component } = object;
// only once for InstancedMesh
if (object instanceof three.InstancedMesh) {
if (iMeshes.indexOf(object) !== -1) return;
iMeshes.push(object);
}
const event = { type: 'click', component, intersect };
onIntersectClick(event);
component.onClick?.(event);
});
}
}
function pointerLeave() {
if (resetOnEnd) reset();
onLeave({ type: 'pointerleave' });
}
function addListeners() {
domElement.addEventListener('mouseenter', pointerEnter);
domElement.addEventListener('mousemove', pointerMove);
domElement.addEventListener('mouseleave', pointerLeave);
domElement.addEventListener('click', pointerClick);
if (touch) {
domElement.addEventListener('touchstart', pointerEnter);
domElement.addEventListener('touchmove', pointerMove);
domElement.addEventListener('touchend', pointerLeave);
}
obj.listeners = true;
}
function removeListeners() {
domElement.removeEventListener('mouseenter', pointerEnter);
domElement.removeEventListener('mousemove', pointerMove);
domElement.removeEventListener('mouseleave', pointerLeave);
domElement.removeEventListener('click', pointerClick);
domElement.removeEventListener('touchstart', pointerEnter);
domElement.removeEventListener('touchmove', pointerMove);
domElement.removeEventListener('touchend', pointerLeave);
obj.listeners = false;
}}
2021-03-04 04:49:22 +08:00
/**
* Three.js helper
*/
function useThree() {
// default conf
2021-04-05 04:02:11 +08:00
const conf = {
2021-03-04 04:49:22 +08:00
canvas: null,
antialias: true,
alpha: false,
autoClear: true,
orbit_ctrl: false,
2021-04-05 04:02:11 +08:00
pointer: false,
resize: false,
width: 300,
height: 150,
2021-03-04 04:49:22 +08:00
};
// size
2021-04-05 04:02:11 +08:00
const size = {
2021-03-04 04:49:22 +08:00
width: 1, height: 1,
wWidth: 1, wHeight: 1,
ratio: 1,
};
// handlers
2021-04-05 04:02:11 +08:00
const afterInitCallbacks = [];
let afterResizeCallbacks = [];
let beforeRenderCallbacks = [];
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const intersectObjects = [];
2021-03-04 04:49:22 +08:00
// returned object
2021-04-05 04:02:11 +08:00
const obj = {
conf,
2021-03-04 04:49:22 +08:00
renderer: null,
camera: null,
cameraCtrl: null,
scene: null,
2021-04-05 04:02:11 +08:00
pointer: null,
size,
init,
dispose,
render,
renderC,
setSize,
onAfterInit,
onAfterResize, offAfterResize,
2021-04-07 03:46:35 +08:00
// onBeforeRender, offBeforeRender,
2021-04-05 04:02:11 +08:00
addIntersectObject, removeIntersectObject,
2021-03-04 04:49:22 +08:00
};
/**
* init three
*/
function init(params) {
if (params) {
2021-04-05 04:02:11 +08:00
Object.entries(params).forEach(([key, value]) => {
2021-03-04 04:49:22 +08:00
conf[key] = value;
});
}
if (!obj.scene) {
console.error('Missing Scene');
return;
}
if (!obj.camera) {
console.error('Missing Camera');
return;
}
obj.renderer = new three.WebGLRenderer({ canvas: conf.canvas, antialias: conf.antialias, alpha: conf.alpha });
obj.renderer.autoClear = conf.autoClear;
2021-04-05 04:02:11 +08:00
if (conf.resize) {
onResize();
window.addEventListener('resize', onResize);
} else {
setSize(conf.width, conf.height);
}
initPointer();
2021-03-04 04:49:22 +08:00
if (conf.orbit_ctrl) {
obj.orbitCtrl = new OrbitControls_js.OrbitControls(obj.camera, obj.renderer.domElement);
if (conf.orbit_ctrl instanceof Object) {
2021-04-05 04:02:11 +08:00
Object.entries(conf.orbit_ctrl).forEach(([key, value]) => {
2021-03-04 04:49:22 +08:00
obj.orbitCtrl[key] = value;
});
}
}
2021-04-05 04:02:11 +08:00
afterInitCallbacks.forEach(c => c());
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
return true;
}
function initPointer() {
let pointerConf = {
camera: obj.camera,
domElement: obj.renderer.domElement,
intersectObjects,
};
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
if (conf.pointer && conf.pointer instanceof Object) {
pointerConf = { ...pointerConf, ...conf.pointer };
2021-03-04 04:49:22 +08:00
}
2021-04-05 04:02:11 +08:00
obj.pointer = usePointer(pointerConf);
if (conf.pointer || intersectObjects.length) {
obj.pointer.addListeners();
if (conf.pointer.intersectMode === 'frame') {
onBeforeRender(() => {
obj.pointer.intersect();
});
}
}
2021-03-04 04:49:22 +08:00
}
2021-04-05 04:02:11 +08:00
2021-03-04 04:49:22 +08:00
/**
* add after init callback
*/
function onAfterInit(callback) {
afterInitCallbacks.push(callback);
}
/**
* add after resize callback
*/
function onAfterResize(callback) {
afterResizeCallbacks.push(callback);
}
/**
* remove after resize callback
*/
function offAfterResize(callback) {
2021-04-05 04:02:11 +08:00
afterResizeCallbacks = afterResizeCallbacks.filter(c => c !== callback);
2021-03-04 04:49:22 +08:00
}
/**
* add before render callback
*/
function onBeforeRender(callback) {
beforeRenderCallbacks.push(callback);
}
/**
* default render
*/
function render() {
2021-04-05 04:02:11 +08:00
if (obj.orbitCtrl) obj.orbitCtrl.update();
beforeRenderCallbacks.forEach(c => c());
2021-03-04 04:49:22 +08:00
obj.renderer.render(obj.scene, obj.camera);
}
/**
* composer render
*/
function renderC() {
2021-04-05 04:02:11 +08:00
if (obj.orbitCtrl) obj.orbitCtrl.update();
beforeRenderCallbacks.forEach(c => c());
2021-03-04 04:49:22 +08:00
obj.composer.render();
}
/**
* add intersect object
*/
function addIntersectObject(o) {
if (intersectObjects.indexOf(o) === -1) {
intersectObjects.push(o);
}
2021-04-05 04:02:11 +08:00
// add listeners if needed
if (obj.pointer && !obj.pointer.listeners) {
obj.pointer.addListeners();
}
2021-03-04 04:49:22 +08:00
}
/**
* remove intersect object
*/
function removeIntersectObject(o) {
2021-04-05 04:02:11 +08:00
const i = intersectObjects.indexOf(o);
2021-03-04 04:49:22 +08:00
if (i !== -1) {
intersectObjects.splice(i, 1);
}
2021-04-05 04:02:11 +08:00
// remove listeners if needed
if (obj.pointer && !conf.pointer && intersectObjects.length === 0) {
obj.pointer.removeListeners();
}
2021-03-04 04:49:22 +08:00
}
/**
2021-04-05 04:02:11 +08:00
* remove listeners and dispose
2021-03-04 04:49:22 +08:00
*/
function dispose() {
beforeRenderCallbacks = [];
window.removeEventListener('resize', onResize);
2021-04-05 04:02:11 +08:00
if (obj.pointer) obj.pointer.removeListeners();
if (obj.orbitCtrl) obj.orbitCtrl.dispose();
2021-04-07 03:46:35 +08:00
if (obj.renderer) obj.renderer.dispose();
2021-03-04 04:49:22 +08:00
}
/**
* resize listener
*/
function onResize() {
if (conf.resize === 'window') {
setSize(window.innerWidth, window.innerHeight);
} else {
2021-04-05 04:02:11 +08:00
const elt = obj.renderer.domElement.parentNode;
2021-03-04 04:49:22 +08:00
setSize(elt.clientWidth, elt.clientHeight);
}
2021-04-05 04:02:11 +08:00
afterResizeCallbacks.forEach(c => c());
2021-03-04 04:49:22 +08:00
}
/**
* update renderer size and camera
*/
function setSize(width, height) {
size.width = width;
size.height = height;
size.ratio = width / height;
obj.renderer.setSize(width, height, false);
obj.camera.aspect = size.ratio;
obj.camera.updateProjectionMatrix();
if (obj.composer) {
obj.composer.setSize(width, height);
}
if (obj.camera.type === 'OrthographicCamera') {
size.wWidth = obj.camera.right - obj.camera.left;
size.wHeight = obj.camera.top - obj.camera.bottom;
} else {
2021-04-05 04:02:11 +08:00
const wsize = getCameraSize();
2021-03-04 04:49:22 +08:00
size.wWidth = wsize[0]; size.wHeight = wsize[1];
}
}
/**
* calculate camera visible area size
*/
function getCameraSize() {
2021-04-05 04:02:11 +08:00
const vFOV = (obj.camera.fov * Math.PI) / 180;
const h = 2 * Math.tan(vFOV / 2) * Math.abs(obj.camera.position.z);
const w = h * obj.camera.aspect;
2021-03-04 04:49:22 +08:00
return [w, h];
}
return obj;
}
2021-04-05 04:02:11 +08:00
var Renderer = vue.defineComponent({
2021-03-08 04:17:46 +08:00
name: 'Renderer',
2021-03-04 04:49:22 +08:00
props: {
antialias: Boolean,
alpha: Boolean,
autoClear: { type: Boolean, default: true },
orbitCtrl: { type: [Boolean, Object], default: false },
2021-04-05 04:02:11 +08:00
pointer: { type: [Boolean, Object], default: false },
2021-03-05 16:17:16 +08:00
resize: { type: [Boolean, String], default: false },
2021-03-04 04:49:22 +08:00
shadow: Boolean,
width: String,
height: String,
2021-04-05 04:02:11 +08:00
xr: Boolean,
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
setup() {
2021-03-04 04:49:22 +08:00
return {
three: useThree(),
raf: true,
onMountedCallbacks: [],
2021-04-07 03:46:35 +08:00
beforeRenderCallbacks: [],
afterRenderCallbacks: [],
2021-03-04 04:49:22 +08:00
};
},
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
three: this.three,
// renderer: this.three.renderer,
rendererComponent: this,
};
},
2021-04-05 04:02:11 +08:00
mounted() {
const params = {
2021-03-04 04:49:22 +08:00
canvas: this.$el,
antialias: this.antialias,
alpha: this.alpha,
autoClear: this.autoClear,
orbit_ctrl: this.orbitCtrl,
2021-04-05 04:02:11 +08:00
pointer: this.pointer,
2021-03-04 04:49:22 +08:00
resize: this.resize,
width: this.width,
height: this.height,
};
if (this.three.init(params)) {
2021-03-08 04:17:46 +08:00
this.renderer = this.three.renderer;
this.renderer.shadowMap.enabled = this.shadow;
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
this._render = this.three.composer ? this.three.renderC : this.three.render;
2021-04-05 04:02:11 +08:00
if (this.xr) {
this.renderer.xr.enabled = true;
2021-04-07 03:46:35 +08:00
this.renderer.setAnimationLoop(this.render);
2021-04-05 04:02:11 +08:00
} else {
2021-04-07 03:46:35 +08:00
requestAnimationFrame(this.renderLoop);
2021-04-05 04:02:11 +08:00
}
2021-03-04 04:49:22 +08:00
}
2021-04-05 04:02:11 +08:00
this.onMountedCallbacks.forEach(c => c());
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
beforeUnmount() {
2021-04-07 03:46:35 +08:00
this.beforeRenderCallbacks = [];
this.afterRenderCallbacks = [];
2021-03-04 04:49:22 +08:00
this.raf = false;
this.three.dispose();
},
methods: {
2021-04-07 03:46:35 +08:00
onMounted(cb) {
this.onMountedCallbacks.push(cb);
},
onBeforeRender(cb) {
this.beforeRenderCallbacks.push(cb);
},
offBeforeRender(cb) {
this.beforeRenderCallbacks = this.beforeRenderCallbacks.filter(c => c !== cb);
2021-03-04 04:49:22 +08:00
},
2021-04-07 03:46:35 +08:00
onAfterRender(cb) {
this.afterRenderCallbacks.push(cb);
2021-03-04 04:49:22 +08:00
},
2021-04-07 03:46:35 +08:00
offAfterRender(cb) {
this.afterRenderCallbacks = this.afterRenderCallbacks.filter(c => c !== cb);
2021-03-04 04:49:22 +08:00
},
2021-04-07 03:46:35 +08:00
onAfterResize(cb) {
this.three.onAfterResize(cb);
2021-03-04 04:49:22 +08:00
},
2021-04-07 03:46:35 +08:00
offAfterResize(cb) {
this.three.offAfterResize(cb);
},
render(time) {
this.beforeRenderCallbacks.forEach(c => c({ time }));
this._render();
this.afterRenderCallbacks.forEach(c => c({ time }));
},
renderLoop(time) {
if (this.raf) requestAnimationFrame(this.renderLoop);
this.render(time);
2021-03-04 04:49:22 +08:00
},
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-04 04:49:22 +08:00
return vue.h('canvas', {}, this.$slots.default());
},
2021-03-08 04:17:46 +08:00
__hmrId: 'Renderer',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
function setFromProp(o, prop) {
if (prop instanceof Object) {
2021-04-05 04:02:11 +08:00
Object.entries(prop).forEach(([key, value]) => {
2021-03-04 04:49:22 +08:00
o[key] = value;
});
}
}
2021-03-14 02:34:34 +08:00
function bindProps(src, props, dst) {
2021-04-05 04:02:11 +08:00
props.forEach(prop => {
2021-03-14 02:34:34 +08:00
bindProp(src, prop, dst);
});
}
2021-03-08 04:17:46 +08:00
function bindProp(src, srcProp, dst, dstProp) {
2021-04-05 04:02:11 +08:00
if (!dstProp) dstProp = srcProp;
const ref = vue.toRef(src, srcProp);
2021-03-08 04:17:46 +08:00
if (ref.value instanceof Object) {
setFromProp(dst[dstProp], ref.value);
2021-04-05 04:02:11 +08:00
vue.watch(ref, (value) => { setFromProp(dst[dstProp], value); }, { deep: true });
2021-03-08 04:17:46 +08:00
} else {
2021-04-05 04:02:11 +08:00
if (ref.value) dst[dstProp] = src[srcProp];
vue.watch(ref, (value) => { dst[dstProp] = value; });
2021-03-08 04:17:46 +08:00
}
}
2021-03-04 04:49:22 +08:00
function propsValues(props, exclude) {
2021-04-05 04:02:11 +08:00
const values = {};
Object.entries(props).forEach(([key, value]) => {
2021-03-04 04:49:22 +08:00
if (!exclude || (exclude && !exclude.includes(key))) {
values[key] = value;
}
});
return values;
}
function lerp(value1, value2, amount) {
amount = amount < 0 ? 0 : amount;
amount = amount > 1 ? 1 : amount;
return value1 + (value2 - value1) * amount;
}
function lerpv2(v1, v2, amount) {
v1.x = lerp(v1.x, v2.x, amount);
v1.y = lerp(v1.y, v2.y, amount);
}
function lerpv3(v1, v2, amount) {
v1.x = lerp(v1.x, v2.x, amount);
v1.y = lerp(v1.y, v2.y, amount);
v1.z = lerp(v1.z, v2.z, amount);
}
function limit(val, min, max) {
return val < min ? min : (val > max ? max : val);
}
// from https://github.com/pmndrs/drei/blob/master/src/useMatcapTexture.tsx
2021-04-05 04:02:11 +08:00
const MATCAP_ROOT = 'https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d';
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
function getMatcapUrl(hash, format = 1024) {
const fileName = `${hash}${getMatcapFormatString(format)}.png`;
return `${MATCAP_ROOT}/${format}/${fileName}`;
2021-03-04 04:49:22 +08:00
}
function getMatcapFormatString(format) {
switch (format) {
case 64:
return '-64px';
case 128:
return '-128px';
case 256:
return '-256px';
case 512:
return '-512px';
default:
return '';
}
}
2021-04-05 04:02:11 +08:00
// import Object3D from '../core/Object3D.js';
2021-03-14 02:34:34 +08:00
2021-04-05 04:02:11 +08:00
var Camera = vue.defineComponent({
// TODO: eventually extend Object3D, for now: error 'injection "scene" not found'
// because camera is a sibling of scene in Trois
// extends: Object3D,
inject: ['three'],
render() {
return this.$slots.default ? this.$slots.default() : [];
},
});
2021-03-14 02:34:34 +08:00
2021-04-05 04:02:11 +08:00
var OrthographicCamera = vue.defineComponent({
extends: Camera,
2021-03-08 04:17:46 +08:00
name: 'OrthographicCamera',
2021-03-04 04:49:22 +08:00
inject: ['three'],
props: {
left: { type: Number, default: -1 },
right: { type: Number, default: 1 },
top: { type: Number, default: 1 },
bottom: { type: Number, default: -1 },
near: { type: Number, default: 0.1 },
far: { type: Number, default: 2000 },
zoom: { type: Number, default: 1 },
2021-03-08 04:17:46 +08:00
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.camera = new three.OrthographicCamera(this.left, this.right, this.top, this.bottom, this.near, this.far);
2021-03-08 04:17:46 +08:00
bindProp(this, 'position', this.camera);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'].forEach(p => {
vue.watch(() => this[p], () => {
this.camera[p] = this[p];
this.camera.updateProjectionMatrix();
2021-03-04 04:49:22 +08:00
});
});
this.three.camera = this.camera;
},
__hmrId: 'OrthographicCamera',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var PerspectiveCamera = vue.defineComponent({
extends: Camera,
2021-03-08 04:17:46 +08:00
name: 'PerspectiveCamera',
2021-03-04 04:49:22 +08:00
inject: ['three'],
props: {
aspect: { type: Number, default: 1 },
far: { type: Number, default: 2000 },
fov: { type: Number, default: 50 },
near: { type: Number, default: 0.1 },
2021-03-08 04:17:46 +08:00
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
lookAt: { type: Object, default: null },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.camera = new three.PerspectiveCamera(this.fov, this.aspect, this.near, this.far);
2021-03-08 04:17:46 +08:00
bindProp(this, 'position', this.camera);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
if (this.lookAt) this.camera.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z);
vue.watch(() => this.lookAt, (v) => { this.camera.lookAt(v.x, v.y, v.z); }, { deep: true });
2021-03-05 16:17:16 +08:00
2021-04-05 04:02:11 +08:00
['aspect', 'far', 'fov', 'near'].forEach(p => {
vue.watch(() => this[p], () => {
this.camera[p] = this[p];
this.camera.updateProjectionMatrix();
2021-03-04 04:49:22 +08:00
});
});
this.three.camera = this.camera;
},
__hmrId: 'PerspectiveCamera',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Object3D = vue.defineComponent({
2021-03-08 04:17:46 +08:00
name: 'Object3D',
inject: ['three', 'scene', 'rendererComponent'],
2021-04-05 04:02:11 +08:00
emits: ['created', 'ready'],
2021-03-04 04:49:22 +08:00
props: {
2021-03-08 04:17:46 +08:00
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
rotation: { type: Object, default: { x: 0, y: 0, z: 0 } },
scale: { type: Object, default: { x: 1, y: 1, z: 1 } },
lookAt: { type: Object, default: null },
2021-04-05 04:02:11 +08:00
autoRemove: { type: Boolean, default: true },
2021-04-07 03:46:35 +08:00
userData: { type: Object, default: () => ({}) },
2021-03-04 04:49:22 +08:00
},
2021-03-08 04:17:46 +08:00
// can't use setup because it will not be used in sub components
// setup() {},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.autoRemove) this.removeFromParent();
2021-03-04 04:49:22 +08:00
},
2021-03-08 04:17:46 +08:00
methods: {
2021-04-05 04:02:11 +08:00
initObject3D(o3d) {
2021-03-08 04:17:46 +08:00
this.o3d = o3d;
2021-04-07 03:46:35 +08:00
this.o3d.userData = this.userData;
2021-04-05 04:02:11 +08:00
this.$emit('created', this.o3d);
2021-03-04 06:23:57 +08:00
2021-03-08 04:17:46 +08:00
bindProp(this, 'position', this.o3d);
bindProp(this, 'rotation', this.o3d);
bindProp(this, 'scale', this.o3d);
2021-03-14 02:34:34 +08:00
// TODO : fix lookat.x
2021-04-05 04:02:11 +08:00
if (this.lookAt) this.o3d.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z);
vue.watch(() => this.lookAt, (v) => { this.o3d.lookAt(v.x, v.y, v.z); }, { deep: true });
2021-03-08 04:17:46 +08:00
2021-04-05 04:02:11 +08:00
this._parent = this.getParent();
if (this.addToParent()) this.$emit('ready', this);
else console.error('Missing parent (Scene, Group...)');
},
getParent() {
let parent = this.$parent;
2021-03-14 02:34:34 +08:00
while (parent) {
2021-04-05 04:02:11 +08:00
if (parent.add) return parent;
2021-03-14 02:34:34 +08:00
parent = parent.$parent;
}
2021-04-05 04:02:11 +08:00
return false;
},
addToParent(o) {
const o3d = o || this.o3d;
if (this._parent) {
this._parent.add(o3d);
return true;
}
return false;
2021-03-08 04:17:46 +08:00
},
2021-04-05 04:02:11 +08:00
removeFromParent(o) {
const o3d = o || this.o3d;
if (this._parent) {
this._parent.remove(o3d);
return true;
}
return false;
},
add(o) { this.o3d.add(o); },
remove(o) { this.o3d.remove(o); },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-08 04:17:46 +08:00
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: 'Object3D',
2021-04-05 04:02:11 +08:00
});
2021-03-08 04:17:46 +08:00
2021-04-05 04:02:11 +08:00
var Group = vue.defineComponent({
2021-03-08 04:17:46 +08:00
name: 'Group',
extends: Object3D,
2021-04-05 04:02:11 +08:00
created() {
2021-03-08 04:17:46 +08:00
this.group = new three.Group();
this.initObject3D(this.group);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'Group',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Scene = vue.defineComponent({
2021-03-08 04:17:46 +08:00
name: 'Scene',
2021-03-04 04:49:22 +08:00
inject: ['three'],
props: {
id: String,
background: [String, Number],
},
2021-04-05 04:02:11 +08:00
setup(props) {
const scene = new three.Scene();
if (props.background) scene.background = new three.Color(props.background);
vue.watch(() => props.background, (value) => { scene.background.set(value); });
return { scene };
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
scene: this.scene,
};
},
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
if (!this.three.scene) {
this.three.scene = this.scene;
}
},
methods: {
2021-04-05 04:02:11 +08:00
add(o) { this.scene.add(o); },
remove(o) { this.scene.remove(o); },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-08 04:17:46 +08:00
return this.$slots.default ? this.$slots.default() : [];
2021-03-04 04:49:22 +08:00
},
2021-03-08 04:17:46 +08:00
__hmrId: 'Scene',
2021-04-05 04:02:11 +08:00
});
var Raycaster = vue.defineComponent({
name: 'Raycaster',
inject: ['three', 'rendererComponent'],
props: {
onPointerEnter: { type: Function, default: () => {} },
onPointerOver: { type: Function, default: () => {} },
onPointerMove: { type: Function, default: () => {} },
onPointerLeave: { type: Function, default: () => {} },
onClick: { type: Function, default: () => {} },
intersectMode: { type: String, default: 'move' },
},
mounted() {
this.rendererComponent.onMounted(() => {
this.pointer = usePointer({
camera: this.three.camera,
domElement: this.three.renderer.domElement,
intersectObjects: this.getIntersectObjects(),
onIntersectEnter: this.onPointerEnter,
onIntersectOver: this.onPointerOver,
onIntersectMove: this.onPointerMove,
onIntersectLeave: this.onPointerLeave,
onIntersectClick: this.onClick,
});
this.pointer.addListeners();
if (this.intersectMode === 'frame') {
2021-04-07 03:46:35 +08:00
this.rendererComponent.onBeforeRender(this.pointer.intersect);
2021-04-05 04:02:11 +08:00
}
});
},
unmounted() {
if (this.pointer) {
this.pointer.removeListeners();
2021-04-07 03:46:35 +08:00
this.rendererComponent.offBeforeRender(this.pointer.intersect);
2021-04-05 04:02:11 +08:00
}
},
methods: {
getIntersectObjects() {
return this.three.scene.children.filter(e => e.type === 'Mesh');
},
},
render() {
return [];
},
__hmrId: 'Raycaster',
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const Geometry = vue.defineComponent({
2021-03-04 04:49:22 +08:00
inject: ['mesh'],
props: {
rotateX: Number,
rotateY: Number,
rotateZ: Number,
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
if (!this.mesh) {
console.error('Missing parent Mesh');
}
2021-03-08 04:17:46 +08:00
2021-03-04 04:49:22 +08:00
this.watchProps = [];
2021-04-05 04:02:11 +08:00
Object.entries(this.$props).forEach(e => this.watchProps.push(e[0]));
2021-03-08 04:17:46 +08:00
2021-03-04 04:49:22 +08:00
this.createGeometry();
this.rotateGeometry();
this.mesh.setGeometry(this.geometry);
2021-03-08 04:17:46 +08:00
2021-03-04 04:49:22 +08:00
this.addWatchers();
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-04 04:49:22 +08:00
this.geometry.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
addWatchers() {
this.watchProps.forEach(prop => {
vue.watch(() => this[prop], () => {
this.refreshGeometry();
2021-03-04 04:49:22 +08:00
});
});
},
2021-04-05 04:02:11 +08:00
rotateGeometry() {
if (this.rotateX) this.geometry.rotateX(this.rotateX);
if (this.rotateY) this.geometry.rotateY(this.rotateY);
if (this.rotateZ) this.geometry.rotateZ(this.rotateZ);
2021-03-08 04:17:46 +08:00
},
2021-04-05 04:02:11 +08:00
refreshGeometry() {
const oldGeo = this.geometry;
2021-03-04 04:49:22 +08:00
this.createGeometry();
this.rotateGeometry();
this.mesh.setGeometry(this.geometry);
oldGeo.dispose();
},
},
2021-04-05 04:02:11 +08:00
render() { return []; },
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
function geometryComponent(name, props, createGeometry) {
return vue.defineComponent({
name,
extends: Geometry,
props,
methods: {
createGeometry() {
this.geometry = createGeometry(this);
},
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
});
}
const props$h = {
size: Number,
width: { type: Number, default: 1 },
height: { type: Number, default: 1 },
depth: { type: Number, default: 1 },
widthSegments: { type: Number, default: 1 },
heightSegments: { type: Number, default: 1 },
depthSegments: { type: Number, default: 1 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$f(comp) {
if (comp.size) {
return new three.BoxGeometry(comp.size, comp.size, comp.size, comp.widthSegments, comp.heightSegments, comp.depthSegments);
} else {
return new three.BoxGeometry(comp.width, comp.height, comp.depth, comp.widthSegments, comp.heightSegments, comp.depthSegments);
}
}
var BoxGeometry = geometryComponent('BoxGeometry', props$h, createGeometry$f);
const props$g = {
radius: { type: Number, default: 1 },
segments: { type: Number, default: 8 },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$e(comp) {
return new three.CircleGeometry(comp.radius, comp.segments, comp.thetaStart, comp.thetaLength);
}
var CircleGeometry = geometryComponent('CircleGeometry', props$g, createGeometry$e);
const props$f = {
radius: { type: Number, default: 1 },
height: { type: Number, default: 1 },
radialSegments: { type: Number, default: 8 },
heightSegments: { type: Number, default: 1 },
openEnded: { type: Boolean, default: false },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$d(comp) {
return new three.ConeGeometry(comp.radius, comp.height, comp.radialSegments, comp.heightSegments, comp.openEnded, comp.thetaStart, comp.thetaLength);
}
var ConeGeometry = geometryComponent('ConeGeometry', props$f, createGeometry$d);
const props$e = {
radiusTop: { type: Number, default: 1 },
radiusBottom: { type: Number, default: 1 },
height: { type: Number, default: 1 },
radialSegments: { type: Number, default: 8 },
heightSegments: { type: Number, default: 1 },
openEnded: { type: Boolean, default: false },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$c(comp) {
return new three.CylinderGeometry(comp.radiusTop, comp.radiusBottom, comp.height, comp.radialSegments, comp.heightSegments, comp.openEnded, comp.thetaStart, comp.thetaLength);
}
var CylinderGeometry = geometryComponent('CylinderGeometry', props$e, createGeometry$c);
const props$d = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$b(comp) {
return new three.DodecahedronGeometry(comp.radius, comp.detail);
}
var DodecahedronGeometry = geometryComponent('DodecahedronGeometry', props$d, createGeometry$b);
const props$c = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$a(comp) {
return new three.IcosahedronGeometry(comp.radius, comp.detail);
}
var IcosahedronGeometry = geometryComponent('IcosahedronGeometry', props$c, createGeometry$a);
const props$b = {
points: Array,
segments: { type: Number, default: 12 },
phiStart: { type: Number, default: 0 },
phiLength: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$9(comp) {
return new three.LatheGeometry(comp.points, comp.segments, comp.phiStart, comp.phiLength);
}
var LatheGeometry = geometryComponent('LatheGeometry', props$b, createGeometry$9);
const props$a = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
function createGeometry$8(comp) {
return new three.OctahedronGeometry(comp.radius, comp.detail);
}
var OctahedronGeometry = geometryComponent('OctahedronGeometry', props$a, createGeometry$8);
const props$9 = {
2021-04-07 03:46:35 +08:00
width: { type: Number, default: 1 },
height: { type: Number, default: 1 },
widthSegments: { type: Number, default: 1 },
heightSegments: { type: Number, default: 1 },
};
function createGeometry$7(comp) {
return new three.PlaneGeometry(comp.width, comp.height, comp.widthSegments, comp.heightSegments);
}
var PlaneGeometry = geometryComponent('PlaneGeometry', props$9, createGeometry$7);
const props$8 = {
2021-04-05 04:02:11 +08:00
vertices: Array,
indices: Array,
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$6(comp) {
2021-04-05 04:02:11 +08:00
return new three.PolyhedronGeometry(comp.vertices, comp.indices, comp.radius, comp.detail);
}
2021-04-07 03:46:35 +08:00
var PolyhedronGeometry = geometryComponent('PolyhedronGeometry', props$8, createGeometry$6);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$7 = {
2021-04-05 04:02:11 +08:00
innerRadius: { type: Number, default: 0.5 },
outerRadius: { type: Number, default: 1 },
thetaSegments: { type: Number, default: 8 },
phiSegments: { type: Number, default: 1 },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$5(comp) {
2021-04-05 04:02:11 +08:00
return new three.RingGeometry(comp.innerRadius, comp.outerRadius, comp.thetaSegments, comp.phiSegments, comp.thetaStart, comp.thetaLength);
}
2021-04-07 03:46:35 +08:00
var RingGeometry = geometryComponent('RingGeometry', props$7, createGeometry$5);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$6 = {
2021-04-05 04:02:11 +08:00
radius: { type: Number, default: 1 },
widthSegments: { type: Number, default: 12 },
heightSegments: { type: Number, default: 12 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$4(comp) {
2021-04-05 04:02:11 +08:00
return new three.SphereGeometry(comp.radius, comp.widthSegments, comp.heightSegments);
}
2021-04-07 03:46:35 +08:00
var SphereGeometry = geometryComponent('SphereGeometry', props$6, createGeometry$4);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$5 = {
2021-04-05 04:02:11 +08:00
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$3(comp) {
2021-04-05 04:02:11 +08:00
return new three.TetrahedronGeometry(comp.radius, comp.detail);
}
2021-04-07 03:46:35 +08:00
var TetrahedronGeometry = geometryComponent('TetrahedronGeometry', props$5, createGeometry$3);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$4 = {
2021-04-05 04:02:11 +08:00
radius: { type: Number, default: 1 },
tube: { type: Number, default: 0.4 },
radialSegments: { type: Number, default: 8 },
tubularSegments: { type: Number, default: 6 },
arc: { type: Number, default: Math.PI * 2 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$2(comp) {
2021-04-05 04:02:11 +08:00
return new three.TorusGeometry(comp.radius, comp.tube, comp.radialSegments, comp.tubularSegments, comp.arc);
}
2021-04-07 03:46:35 +08:00
var TorusGeometry = geometryComponent('TorusGeometry', props$4, createGeometry$2);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$3 = {
2021-04-05 04:02:11 +08:00
radius: { type: Number, default: 1 },
tube: { type: Number, default: 0.4 },
tubularSegments: { type: Number, default: 64 },
radialSegments: { type: Number, default: 8 },
p: { type: Number, default: 2 },
q: { type: Number, default: 3 },
2021-03-04 04:49:22 +08:00
};
2021-04-07 03:46:35 +08:00
function createGeometry$1(comp) {
2021-04-05 04:02:11 +08:00
return new three.TorusKnotGeometry(comp.radius, comp.tube, comp.tubularSegments, comp.radialSegments, comp.p, comp.q);
}
2021-04-07 03:46:35 +08:00
var TorusKnotGeometry = geometryComponent('TorusKnotGeometry', props$3, createGeometry$1);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
const props$2 = {
2021-04-05 04:02:11 +08:00
points: Array,
path: three.Curve,
tubularSegments: { type: Number, default: 64 },
radius: { type: Number, default: 1 },
radialSegments: { type: Number, default: 8 },
closed: { type: Boolean, default: false },
};
2021-04-07 03:46:35 +08:00
function createGeometry(comp) {
2021-04-05 04:02:11 +08:00
let curve;
if (comp.points) {
curve = new three.CatmullRomCurve3(comp.points);
} else if (comp.path) {
curve = comp.path;
} else {
console.error('Missing path curve or points.');
}
return new three.TubeGeometry(curve, comp.tubularSegments, comp.radius, comp.radiusSegments, comp.closed);
}
var TubeGeometry = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Geometry,
2021-04-07 03:46:35 +08:00
props: props$2,
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createGeometry() {
2021-04-07 03:46:35 +08:00
this.geometry = createGeometry(this);
2021-04-05 04:02:11 +08:00
},
// update points (without using prop, faster)
updatePoints(points) {
updateTubeGeometryPoints(this.geometry, points);
2021-03-04 04:49:22 +08:00
},
},
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
function updateTubeGeometryPoints(tube, points) {
const curve = new three.CatmullRomCurve3(points);
const { radialSegments, radius, tubularSegments, closed } = tube.parameters;
const frames = curve.computeFrenetFrames(tubularSegments, closed);
tube.tangents = frames.tangents;
tube.normals = frames.normals;
tube.binormals = frames.binormals;
tube.parameters.path = curve;
const pArray = tube.attributes.position.array;
const nArray = tube.attributes.normal.array;
const normal = new three.Vector3();
let P;
for (let i = 0; i < tubularSegments; i++) {
updateSegment(i);
}
updateSegment(tubularSegments);
tube.attributes.position.needsUpdate = true;
tube.attributes.normal.needsUpdate = true;
function updateSegment(i) {
P = curve.getPointAt(i / tubularSegments, P);
const N = frames.normals[i];
const B = frames.binormals[i];
for (let j = 0; j <= radialSegments; j++) {
const v = j / radialSegments * Math.PI * 2;
const sin = Math.sin(v);
const cos = -Math.cos(v);
normal.x = (cos * N.x + sin * B.x);
normal.y = (cos * N.y + sin * B.y);
normal.z = (cos * N.z + sin * B.z);
normal.normalize();
const index = (i * (radialSegments + 1) + j) * 3;
nArray[index] = normal.x;
nArray[index + 1] = normal.y;
nArray[index + 2] = normal.z;
pArray[index] = P.x + radius * normal.x;
pArray[index + 1] = P.y + radius * normal.y;
pArray[index + 2] = P.z + radius * normal.z;
}
}
}
var Light = vue.defineComponent({
2021-03-08 04:17:46 +08:00
extends: Object3D,
name: 'Light',
2021-03-04 04:49:22 +08:00
props: {
2021-03-08 04:17:46 +08:00
color: { type: String, default: '#ffffff' },
intensity: { type: Number, default: 1 },
castShadow: { type: Boolean, default: false },
shadowMapSize: { type: Object, default: { x: 512, y: 512 } },
2021-03-14 02:34:34 +08:00
shadowCamera: { type: Object, default: {} },
2021-03-04 04:49:22 +08:00
},
// can't use setup because it will not be used in sub components
// setup() {},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.light.target) this.removeFromParent(this.light.target);
2021-03-04 05:59:51 +08:00
},
2021-03-08 04:17:46 +08:00
methods: {
2021-04-05 04:02:11 +08:00
initLight() {
2021-03-08 04:17:46 +08:00
if (this.light.target) {
bindProp(this, 'target', this.light.target, 'position');
}
2021-03-04 04:49:22 +08:00
2021-03-08 04:17:46 +08:00
if (this.light.shadow) {
this.light.castShadow = this.castShadow;
setFromProp(this.light.shadow.mapSize, this.shadowMapSize);
2021-03-14 02:34:34 +08:00
setFromProp(this.light.shadow.camera, this.shadowCamera);
2021-03-08 04:17:46 +08:00
}
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
['color', 'intensity', 'castShadow'].forEach(p => {
vue.watch(() => this[p], () => {
2021-03-08 04:17:46 +08:00
if (p === 'color') {
2021-04-05 04:02:11 +08:00
this.light.color.set(this.color);
2021-03-08 04:17:46 +08:00
} else {
2021-04-05 04:02:11 +08:00
this.light[p] = this[p];
2021-03-08 04:17:46 +08:00
}
});
2021-03-04 04:49:22 +08:00
});
2021-03-08 04:17:46 +08:00
this.initObject3D(this.light);
2021-04-05 04:02:11 +08:00
if (this.light.target) this.addToParent(this.light.target);
2021-03-08 04:17:46 +08:00
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'Light',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var AmbientLight = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Light,
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.light = new three.AmbientLight(this.color, this.intensity);
2021-03-08 04:17:46 +08:00
this.initLight();
2021-03-04 04:49:22 +08:00
},
__hmrId: 'AmbientLight',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var DirectionalLight = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Light,
props: {
target: Object,
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.light = new three.DirectionalLight(this.color, this.intensity);
2021-03-08 04:17:46 +08:00
this.initLight();
2021-03-04 04:49:22 +08:00
},
__hmrId: 'DirectionalLight',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var HemisphereLight = vue.defineComponent({
2021-03-08 04:17:46 +08:00
extends: Light,
props: {
2021-03-14 02:34:34 +08:00
groundColor: { type: String, default: '#444444' },
2021-03-08 04:17:46 +08:00
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-08 04:17:46 +08:00
this.light = new three.HemisphereLight(this.color, this.groundColor, this.intensity);
2021-04-05 04:02:11 +08:00
vue.watch(() => this.groundColor, (value) => { this.light.groundColor.set(value); });
2021-03-08 04:17:46 +08:00
this.initLight();
},
__hmrId: 'HemisphereLight',
2021-04-05 04:02:11 +08:00
});
2021-03-08 04:17:46 +08:00
2021-04-05 04:02:11 +08:00
var PointLight = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Light,
props: {
distance: {
type: Number,
default: 0,
},
decay: {
type: Number,
default: 1,
},
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.light = new three.PointLight(this.color, this.intensity, this.distance, this.decay);
2021-03-08 04:17:46 +08:00
this.initLight();
2021-03-04 04:49:22 +08:00
},
__hmrId: 'PointLight',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var RectAreaLight = vue.defineComponent({
2021-03-08 04:17:46 +08:00
extends: Light,
props: {
width: { type: Number, default: 10 },
height: { type: Number, default: 10 },
helper: Boolean,
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-08 04:17:46 +08:00
RectAreaLightUniformsLib_js.RectAreaLightUniformsLib.init();
this.light = new three.RectAreaLight(this.color, this.intensity, this.width, this.height);
2021-04-05 04:02:11 +08:00
['width', 'height'].forEach(p => {
vue.watch(() => this[p], () => {
this.light[p] = this[p];
2021-03-08 04:17:46 +08:00
});
});
if (this.helper) {
this.lightHelper = new RectAreaLightHelper_js.RectAreaLightHelper(this.light);
2021-04-05 04:02:11 +08:00
this.light.add(this.lightHelper);
2021-03-08 04:17:46 +08:00
}
this.initLight();
},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.lightHelper) this.removeFromParent(this.lightHelper);
2021-03-08 04:17:46 +08:00
},
__hmrId: 'RectAreaLight',
2021-04-05 04:02:11 +08:00
});
2021-03-08 04:17:46 +08:00
2021-04-05 04:02:11 +08:00
var SpotLight = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Light,
props: {
2021-03-08 04:17:46 +08:00
angle: { type: Number, default: Math.PI / 3 },
decay: { type: Number, default: 1 },
distance: { type: Number, default: 0 },
penumbra: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
target: Object,
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.light = new three.SpotLight(this.color, this.intensity, this.distance, this.angle, this.penumbra, this.decay);
2021-04-05 04:02:11 +08:00
['angle', 'decay', 'distance', 'penumbra'].forEach(p => {
vue.watch(() => this[p], () => {
this.light[p] = this[p];
2021-03-04 04:49:22 +08:00
});
});
2021-03-08 04:17:46 +08:00
this.initLight();
2021-03-04 04:49:22 +08:00
},
__hmrId: 'SpotLight',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Material = vue.defineComponent({
2021-03-04 04:49:22 +08:00
inject: ['three', 'mesh'],
props: {
color: { type: [String, Number], default: '#ffffff' },
depthTest: { type: Boolean, default: true },
depthWrite: { type: Boolean, default: true },
fog: { type: Boolean, default: true },
opacity: { type: Number, default: 1 },
side: { type: Number, default: three.FrontSide },
transparent: Boolean,
vertexColors: Boolean,
},
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
material: this,
};
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.createMaterial();
this.mesh.setMaterial(this.material);
2021-03-08 04:17:46 +08:00
2021-03-04 04:49:22 +08:00
this._addWatchers();
2021-04-05 04:02:11 +08:00
if (this.addWatchers) this.addWatchers();
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-04 04:49:22 +08:00
this.material.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
setProp(key, value, needsUpdate = false) {
2021-03-04 04:49:22 +08:00
this.material[key] = value;
this.material.needsUpdate = needsUpdate;
},
2021-04-05 04:02:11 +08:00
setTexture(texture, key = 'map') {
2021-03-04 04:49:22 +08:00
this.setProp(key, texture, true);
},
2021-04-05 04:02:11 +08:00
_addWatchers() {
['color', 'depthTest', 'depthWrite', 'fog', 'opacity', 'side', 'transparent'].forEach(p => {
vue.watch(() => this[p], () => {
2021-03-04 04:49:22 +08:00
if (p === 'color') {
2021-04-05 04:02:11 +08:00
this.material.color.set(this.color);
2021-03-04 04:49:22 +08:00
} else {
2021-04-05 04:02:11 +08:00
this.material[p] = this[p];
2021-03-04 04:49:22 +08:00
}
});
});
},
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-08 04:17:46 +08:00
return this.$slots.default ? this.$slots.default() : [];
2021-03-04 04:49:22 +08:00
},
__hmrId: 'Material',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const wireframeProps = {
2021-03-14 02:34:34 +08:00
wireframe: { type: Boolean, default: false },
// not needed for WebGL
// wireframeLinecap: { type: String, default: 'round' },
// wireframeLinejoin: { type: String, default: 'round' },
wireframeLinewidth: { type: Number, default: 1 }, // not really useful
};
2021-04-05 04:02:11 +08:00
var BasicMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
2021-04-05 04:02:11 +08:00
props: {
...wireframeProps,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshBasicMaterial(propsValues(this.$props));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
bindProps(this, Object.keys(wireframeProps), this.material);
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'BasicMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var LambertMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
2021-04-05 04:02:11 +08:00
props: {
...wireframeProps,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshLambertMaterial(propsValues(this.$props));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
bindProps(this, Object.keys(wireframeProps), this.material);
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'LambertMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var MatcapMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
props: {
src: String,
name: String,
2021-03-14 02:34:34 +08:00
flatShading: Boolean,
2021-03-04 04:49:22 +08:00
},
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
const src = this.name ? getMatcapUrl(this.name) : this.src;
const opts = propsValues(this.$props, ['src', 'name']);
2021-03-04 04:49:22 +08:00
opts.matcap = new three.TextureLoader().load(src);
this.material = new three.MeshMatcapMaterial(opts);
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
// TODO
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'MatcapMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var PhongMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
2021-04-05 04:02:11 +08:00
props: {
emissive: { type: [Number, String], default: 0 },
2021-03-04 04:49:22 +08:00
emissiveIntensity: { type: Number, default: 1 },
reflectivity: { type: Number, default: 1 },
shininess: { type: Number, default: 30 },
specular: { type: [String, Number], default: 0x111111 },
2021-04-05 04:02:11 +08:00
flatShading: Boolean,
...wireframeProps,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshPhongMaterial(propsValues(this.$props));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
// TODO : handle flatShading ?
2021-04-05 04:02:11 +08:00
['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular'].forEach(p => {
vue.watch(() => this[p], (value) => {
2021-03-04 04:49:22 +08:00
if (p === 'emissive' || p === 'specular') {
2021-04-05 04:02:11 +08:00
this.material[p].set(value);
2021-03-04 04:49:22 +08:00
} else {
2021-04-05 04:02:11 +08:00
this.material[p] = value;
2021-03-04 04:49:22 +08:00
}
});
});
2021-03-14 02:34:34 +08:00
bindProps(this, Object.keys(wireframeProps), this.material);
2021-03-04 04:49:22 +08:00
},
},
__hmrId: 'PhongMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
const props$1 = {
2021-03-04 04:49:22 +08:00
aoMapIntensity: { type: Number, default: 1 },
bumpScale: { type: Number, default: 1 },
displacementBias: { type: Number, default: 0 },
displacementScale: { type: Number, default: 1 },
emissive: { type: [Number, String], default: 0 },
emissiveIntensity: { type: Number, default: 1 },
envMapIntensity: { type: Number, default: 1 },
lightMapIntensity: { type: Number, default: 1 },
metalness: { type: Number, default: 0 },
2021-03-08 04:17:46 +08:00
normalScale: { type: Object, default: { x: 1, y: 1 } },
2021-03-04 04:49:22 +08:00
roughness: { type: Number, default: 1 },
refractionRatio: { type: Number, default: 0.98 },
2021-03-14 02:34:34 +08:00
flatShading: Boolean,
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
var StandardMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
2021-04-05 04:02:11 +08:00
props: {
2021-04-07 03:46:35 +08:00
...props$1,
2021-04-05 04:02:11 +08:00
...wireframeProps,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshStandardMaterial(propsValues(this.$props, ['normalScale']));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
// TODO : use setProp, handle flatShading ?
2021-04-07 03:46:35 +08:00
Object.keys(props$1).forEach(p => {
2021-04-05 04:02:11 +08:00
if (p === 'normalScale') return;
vue.watch(() => this[p], (value) => {
2021-03-04 04:49:22 +08:00
if (p === 'emissive') {
2021-04-05 04:02:11 +08:00
this.material[p].set(value);
2021-03-04 04:49:22 +08:00
} else {
2021-04-05 04:02:11 +08:00
this.material[p] = value;
2021-03-04 04:49:22 +08:00
}
});
});
2021-03-08 04:17:46 +08:00
bindProp(this, 'normalScale', this.material);
2021-03-14 02:34:34 +08:00
bindProps(this, Object.keys(wireframeProps), this.material);
2021-03-04 04:49:22 +08:00
},
},
__hmrId: 'StandardMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var PhysicalMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: StandardMaterial,
2021-03-14 02:34:34 +08:00
props: {
flatShading: Boolean,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshPhysicalMaterial(propsValues(this.$props));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
// TODO
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'PhysicalMaterial',
2021-04-05 04:02:11 +08:00
});
const defaultVertexShader = `
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}`;
const defaultFragmentShader = `
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv.x, vUv.y, 0., 1.0);
}`;
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var ShaderMaterial = vue.defineComponent({
2021-03-14 02:34:34 +08:00
inject: ['three', 'mesh'],
props: {
2021-04-05 04:02:11 +08:00
uniforms: { type: Object, default: () => { return {}; } },
2021-03-14 02:34:34 +08:00
vertexShader: { type: String, default: defaultVertexShader },
fragmentShader: { type: String, default: defaultFragmentShader },
},
2021-04-05 04:02:11 +08:00
provide() {
return {
material: this,
};
},
created() {
2021-03-14 02:34:34 +08:00
this.createMaterial();
2021-04-05 04:02:11 +08:00
['vertexShader', 'fragmentShader'].forEach(p => {
vue.watch(() => this[p], () => {
2021-03-14 02:34:34 +08:00
// recreate material if we change either shader
2021-04-05 04:02:11 +08:00
this.material.dispose();
this.createMaterial();
2021-03-14 02:34:34 +08:00
});
});
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-14 02:34:34 +08:00
this.material.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-14 02:34:34 +08:00
this.material = new three.ShaderMaterial(propsValues(this.$props));
this.mesh.setMaterial(this.material);
},
},
2021-04-05 04:02:11 +08:00
render() {
return this.$slots.default ? this.$slots.default() : [];
2021-03-14 02:34:34 +08:00
},
__hmrId: 'ShaderMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-14 02:34:34 +08:00
2021-03-04 04:49:22 +08:00
/**
* ------------------------------------------------------------------------------------------
* Subsurface Scattering shader
* Based on three/examples/jsm/shaders/SubsurfaceScatteringShader.js
* Based on GDC 2011 Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look
* https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/
*------------------------------------------------------------------------------------------
*/
function replaceAll(string, find, replace) {
return string.split(find).join(replace);
}
2021-04-05 04:02:11 +08:00
const meshphongFragHead = three.ShaderChunk.meshphong_frag.slice(0, three.ShaderChunk.meshphong_frag.indexOf('void main() {'));
const meshphongFragBody = three.ShaderChunk.meshphong_frag.slice(three.ShaderChunk.meshphong_frag.indexOf('void main() {'));
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const SubsurfaceScatteringShader = {
2021-03-04 04:49:22 +08:00
uniforms: three.UniformsUtils.merge([
three.ShaderLib.phong.uniforms,
{
2021-03-14 02:34:34 +08:00
thicknessColor: { value: new three.Color(0xffffff) },
2021-03-04 04:49:22 +08:00
thicknessDistortion: { value: 0.1 },
thicknessAmbient: { value: 0.0 },
thicknessAttenuation: { value: 0.1 },
thicknessPower: { value: 2.0 },
thicknessScale: { value: 10.0 },
2021-04-05 04:02:11 +08:00
},
]),
vertexShader: `
#define USE_UV
${three.ShaderChunk.meshphong_vert}
`,
fragmentShader: `
#define USE_UV
#define SUBSURFACE
${meshphongFragHead}
uniform float thicknessPower;
uniform float thicknessScale;
uniform float thicknessDistortion;
uniform float thicknessAmbient;
uniform float thicknessAttenuation;
uniform vec3 thicknessColor;
void RE_Direct_Scattering(const in IncidentLight directLight, const in vec2 uv, const in GeometricContext geometry, inout ReflectedLight reflectedLight) {
#ifdef USE_COLOR
vec3 thickness = vColor * thicknessColor;
#else
vec3 thickness = thicknessColor;
#endif
vec3 scatteringHalf = normalize(directLight.direction + (geometry.normal * thicknessDistortion));
float scatteringDot = pow(saturate(dot(geometry.viewDir, -scatteringHalf)), thicknessPower) * thicknessScale;
vec3 scatteringIllu = (scatteringDot + thicknessAmbient) * thickness;
reflectedLight.directDiffuse += scatteringIllu * thicknessAttenuation * directLight.color;
}
` + meshphongFragBody.replace(
2021-03-04 04:49:22 +08:00
'#include <lights_fragment_begin>',
replaceAll(
three.ShaderChunk.lights_fragment_begin,
'RE_Direct( directLight, geometry, material, reflectedLight );',
2021-04-05 04:02:11 +08:00
`
RE_Direct( directLight, geometry, material, reflectedLight );
#if defined( SUBSURFACE ) && defined( USE_UV )
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);
#endif
`
2021-03-04 04:49:22 +08:00
)
),
};
2021-04-05 04:02:11 +08:00
var SubSurfaceMaterial = vue.defineComponent({
2021-03-14 02:34:34 +08:00
inject: ['three', 'mesh'],
2021-03-04 04:49:22 +08:00
props: {
color: { type: String, default: '#ffffff' },
thicknessColor: { type: String, default: '#ffffff' },
thicknessDistortion: { type: Number, default: 0.4 },
thicknessAmbient: { type: Number, default: 0.01 },
thicknessAttenuation: { type: Number, default: 0.7 },
thicknessPower: { type: Number, default: 2 },
thicknessScale: { type: Number, default: 4 },
transparent: { type: Boolean, default: false },
opacity: { type: Number, default: 1 },
vertexColors: { type: Boolean, default: false },
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-14 02:34:34 +08:00
this.createMaterial();
this.mesh.setMaterial(this.material);
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-14 02:34:34 +08:00
this.material.dispose();
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
const params = SubsurfaceScatteringShader;
const uniforms = three.UniformsUtils.clone(params.uniforms);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
Object.entries(this.$props).forEach(([key, value]) => {
let _key = key, _value = value;
2021-03-04 04:49:22 +08:00
if (['color', 'thicknessColor'].includes(key)) {
2021-04-05 04:02:11 +08:00
if (key === 'color') _key = 'diffuse';
2021-03-04 04:49:22 +08:00
_value = new three.Color(value);
}
2021-03-08 04:17:46 +08:00
if (!['transparent', 'vertexColors'].includes(key)) {
2021-03-04 04:49:22 +08:00
uniforms[_key].value = _value;
}
});
2021-04-05 04:02:11 +08:00
this.material = new three.ShaderMaterial({
...params,
uniforms,
2021-03-04 04:49:22 +08:00
lights: true,
transparent: this.transparent,
2021-04-05 04:02:11 +08:00
vertexColors: this.vertexColors,
});
2021-03-04 04:49:22 +08:00
},
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-14 02:34:34 +08:00
return [];
},
2021-03-04 04:49:22 +08:00
__hmrId: 'SubSurfaceMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var ToonMaterial = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Material,
2021-04-05 04:02:11 +08:00
props: {
...wireframeProps,
},
2021-03-04 04:49:22 +08:00
methods: {
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-08 04:17:46 +08:00
this.material = new three.MeshToonMaterial(propsValues(this.$props));
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addWatchers() {
2021-03-14 02:34:34 +08:00
bindProps(this, Object.keys(wireframeProps), this.material);
},
2021-03-04 04:49:22 +08:00
},
__hmrId: 'ToonMaterial',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Texture = vue.defineComponent({
2021-03-04 04:49:22 +08:00
inject: ['material'],
emits: ['loaded'],
props: {
2021-04-05 04:02:11 +08:00
name: { type: String, default: 'map' },
uniform: { type: String, default: null },
2021-03-04 04:49:22 +08:00
src: String,
onLoad: Function,
onProgress: Function,
onError: Function,
2021-03-08 04:17:46 +08:00
mapping: { type: Number, default: three.UVMapping },
wrapS: { type: Number, default: three.ClampToEdgeWrapping },
wrapT: { type: Number, default: three.ClampToEdgeWrapping },
magFilter: { type: Number, default: three.LinearFilter },
minFilter: { type: Number, default: three.LinearMipmapLinearFilter },
repeat: { type: Object, default: { x: 1, y: 1 } },
rotation: { type: Number, default: 0 },
center: { type: Object, default: { x: 0, y: 0 } },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.refreshTexture();
2021-04-05 04:02:11 +08:00
vue.watch(() => this.src, this.refreshTexture);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.material && this.material.setTexture) this.material.setTexture(null, this.name);
2021-03-04 04:49:22 +08:00
this.texture.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
createTexture() {
2021-03-04 04:49:22 +08:00
this.texture = new three.TextureLoader().load(this.src, this.onLoaded, this.onProgress, this.onError);
2021-04-05 04:02:11 +08:00
const wathProps = ['mapping', 'wrapS', 'wrapT', 'magFilter', 'minFilter', 'repeat', 'rotation', 'rotation', 'center'];
wathProps.forEach(prop => {
bindProp(this, prop, this.texture);
2021-03-08 04:17:46 +08:00
});
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
refreshTexture() {
2021-03-04 04:49:22 +08:00
this.createTexture();
2021-04-05 04:02:11 +08:00
// handle standard material
if (this.material && this.material.setTexture) { this.material.setTexture(this.texture, this.name); }
// handle shader material
else if (this.material && this.material.material.type === "ShaderMaterial") {
// require a `uniform` prop so we know what to call the uniform
if (!this.uniform) {
console.warn('"uniform" prop required to use texture in a shader.');
return
}
this.material.uniforms[this.uniform] = { value: this.texture };
}
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
onLoaded() {
if (this.onLoad) this.onLoad();
2021-03-04 04:49:22 +08:00
this.$emit('loaded');
},
},
2021-04-05 04:02:11 +08:00
render() { return []; },
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var CubeTexture = vue.defineComponent({
2021-03-04 04:49:22 +08:00
inject: ['material'],
emits: ['loaded'],
props: {
path: String,
urls: {
type: Array,
default: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
},
onLoad: Function,
onProgress: Function,
onError: Function,
2021-04-05 04:02:11 +08:00
name: { type: String, default: 'envMap' },
2021-03-04 04:49:22 +08:00
refraction: Boolean,
// todo: remove ?
refractionRatio: { type: Number, default: 0.98 },
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.refreshTexture();
2021-04-05 04:02:11 +08:00
vue.watch(() => this.path, this.refreshTexture);
vue.watch(() => this.urls, this.refreshTexture);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
unmounted() {
this.material.setTexture(null, this.name);
2021-03-04 04:49:22 +08:00
this.texture.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
createTexture() {
2021-03-04 04:49:22 +08:00
this.texture = new three.CubeTextureLoader()
.setPath(this.path)
.load(this.urls, this.onLoaded, this.onProgress, this.onError);
},
2021-04-05 04:02:11 +08:00
refreshTexture() {
2021-03-04 04:49:22 +08:00
this.createTexture();
2021-04-05 04:02:11 +08:00
this.material.setTexture(this.texture, this.name);
2021-03-04 04:49:22 +08:00
if (this.refraction) {
this.texture.mapping = three.CubeRefractionMapping;
this.material.setProp('refractionRatio', this.refractionRatio);
}
},
2021-04-05 04:02:11 +08:00
onLoaded() {
if (this.onLoad) this.onLoad();
2021-03-04 04:49:22 +08:00
this.$emit('loaded');
},
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-04 04:49:22 +08:00
return [];
},
2021-04-05 04:02:11 +08:00
});
const pointerProps = {
onPointerEnter: Function,
onPointerOver: Function,
onPointerMove: Function,
onPointerLeave: Function,
onPointerDown: Function,
onPointerUp: Function,
onClick: Function,
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
const Mesh = vue.defineComponent({
2021-03-08 04:17:46 +08:00
name: 'Mesh',
2021-04-05 04:02:11 +08:00
extends: Object3D,
2021-03-04 04:49:22 +08:00
props: {
castShadow: Boolean,
receiveShadow: Boolean,
2021-04-05 04:02:11 +08:00
...pointerProps,
2021-03-04 04:49:22 +08:00
},
// can't use setup because it will not be used in sub components
// setup() {},
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
mesh: this,
};
},
2021-04-05 04:02:11 +08:00
mounted() {
if (!this.mesh && !this.loading) this.initMesh();
2021-03-04 04:49:22 +08:00
},
methods: {
2021-04-05 04:02:11 +08:00
initMesh() {
2021-03-04 04:49:22 +08:00
this.mesh = new three.Mesh(this.geometry, this.material);
2021-04-05 04:02:11 +08:00
this.mesh.component = this;
bindProp(this, 'castShadow', this.mesh);
bindProp(this, 'receiveShadow', this.mesh);
if (this.onPointerEnter ||
this.onPointerOver ||
this.onPointerMove ||
this.onPointerLeave ||
this.onPointerDown ||
this.onPointerUp ||
this.onClick) {
2021-03-04 04:49:22 +08:00
this.three.addIntersectObject(this.mesh);
}
2021-03-08 04:17:46 +08:00
this.initObject3D(this.mesh);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
addGeometryWatchers(props) {
Object.keys(props).forEach(prop => {
vue.watch(() => this[prop], () => {
this.refreshGeometry();
});
});
},
setGeometry(geometry) {
2021-03-04 04:49:22 +08:00
this.geometry = geometry;
2021-04-05 04:02:11 +08:00
if (this.mesh) this.mesh.geometry = geometry;
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
setMaterial(material) {
2021-03-04 04:49:22 +08:00
this.material = material;
2021-04-05 04:02:11 +08:00
if (this.mesh) this.mesh.material = material;
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
refreshGeometry() {
const oldGeo = this.geometry;
2021-03-04 04:49:22 +08:00
this.createGeometry();
this.mesh.geometry = this.geometry;
oldGeo.dispose();
},
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-08 04:17:46 +08:00
if (this.mesh) {
this.three.removeIntersectObject(this.mesh);
2021-04-05 04:02:11 +08:00
}
// for predefined mesh (geometry is not unmounted)
if (this.geometry) this.geometry.dispose();
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
__hmrId: 'Mesh',
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
function meshComponent(name, props, createGeometry) {
return vue.defineComponent({
name,
extends: Mesh,
props,
created() {
this.createGeometry();
this.addGeometryWatchers(props);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
methods: {
createGeometry() {
this.geometry = createGeometry(this);
},
},
__hmrId: name,
});
}
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Box = meshComponent('Box', props$h, createGeometry$f);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Circle = meshComponent('Circle', props$g, createGeometry$e);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Cone = meshComponent('Cone', props$f, createGeometry$d);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Cylinder = meshComponent('Cylinder', props$e, createGeometry$c);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Dodecahedron = meshComponent('Dodecahedron', props$d, createGeometry$b);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Icosahedron = meshComponent('Icosahedron', props$c, createGeometry$a);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Lathe = meshComponent('Lathe', props$b, createGeometry$9);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Octahedron = meshComponent('Octahedron', props$a, createGeometry$8);
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
var Plane = meshComponent('Plane', props$9, createGeometry$7);
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
var Polyhedron = meshComponent('Polyhedron', props$8, createGeometry$6);
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
var Ring = meshComponent('Ring', props$7, createGeometry$5);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
var Sphere = meshComponent('Sphere', props$6, createGeometry$4);
2021-04-05 04:02:11 +08:00
2021-04-07 03:46:35 +08:00
var Tetrahedron = meshComponent('Tetrahedron', props$5, createGeometry$3);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const props = {
2021-03-04 04:49:22 +08:00
text: String,
fontSrc: String,
size: { type: Number, default: 80 },
height: { type: Number, default: 5 },
depth: { type: Number, default: 1 },
curveSegments: { type: Number, default: 12 },
bevelEnabled: { type: Boolean, default: false },
bevelThickness: { type: Number, default: 10 },
bevelSize: { type: Number, default: 8 },
bevelOffset: { type: Number, default: 0 },
bevelSegments: { type: Number, default: 5 },
align: { type: [Boolean, String], default: false },
};
2021-04-05 04:02:11 +08:00
var Text = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Mesh,
2021-04-05 04:02:11 +08:00
props,
data() {
2021-03-08 04:17:46 +08:00
return {
loading: true,
};
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
// add watchers
2021-04-05 04:02:11 +08:00
const watchProps = [
2021-03-04 04:49:22 +08:00
'text', 'size', 'height', 'curveSegments',
'bevelEnabled', 'bevelThickness', 'bevelSize', 'bevelOffset', 'bevelSegments',
2021-04-05 04:02:11 +08:00
'align',
];
watchProps.forEach(p => {
vue.watch(() => this[p], () => {
if (this.font) this.refreshGeometry();
2021-03-04 04:49:22 +08:00
});
});
2021-04-05 04:02:11 +08:00
const loader = new three.FontLoader();
loader.load(this.fontSrc, (font) => {
this.loading = false;
this.font = font;
this.createGeometry();
this.initMesh();
2021-03-04 04:49:22 +08:00
});
},
methods: {
2021-04-05 04:02:11 +08:00
createGeometry() {
this.geometry = new three.TextGeometry(this.text, {
2021-03-04 04:49:22 +08:00
font: this.font,
size: this.size,
height: this.height,
depth: this.depth,
curveSegments: this.curveSegments,
bevelEnabled: this.bevelEnabled,
bevelThickness: this.bevelThickness,
bevelSize: this.bevelSize,
bevelOffset: this.bevelOffset,
bevelSegments: this.bevelSegments,
});
if (this.align === 'center') {
this.geometry.center();
}
},
},
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
var Torus = meshComponent('Torus', props$4, createGeometry$2);
2021-03-04 04:49:22 +08:00
2021-04-07 03:46:35 +08:00
var TorusKnot = meshComponent('TorusKnot', props$3, createGeometry$1);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Tube = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: Mesh,
2021-04-07 03:46:35 +08:00
props: props$2,
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.createGeometry();
2021-04-07 03:46:35 +08:00
this.addGeometryWatchers(props$2);
2021-03-04 04:49:22 +08:00
},
methods: {
2021-04-05 04:02:11 +08:00
createGeometry() {
2021-04-07 03:46:35 +08:00
this.geometry = createGeometry(this);
2021-03-08 04:17:46 +08:00
},
2021-03-10 01:25:02 +08:00
// update curve points (without using prop, faster)
2021-04-05 04:02:11 +08:00
updatePoints(points) {
2021-03-10 01:25:02 +08:00
updateTubeGeometryPoints(this.geometry, points);
2021-03-04 04:49:22 +08:00
},
},
__hmrId: 'Tube',
2021-04-05 04:02:11 +08:00
});
2021-03-08 04:17:46 +08:00
2021-04-05 04:02:11 +08:00
var Image = vue.defineComponent({
2021-03-04 04:49:22 +08:00
emits: ['loaded'],
extends: Mesh,
props: {
src: String,
width: Number,
height: Number,
keepSize: Boolean,
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.createGeometry();
this.createMaterial();
this.initMesh();
2021-04-05 04:02:11 +08:00
vue.watch(() => this.src, this.refreshTexture);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
['width', 'height'].forEach(p => {
vue.watch(() => this[p], this.resize);
2021-03-04 04:49:22 +08:00
});
2021-04-05 04:02:11 +08:00
if (this.keepSize) this.three.onAfterResize(this.resize);
2021-03-04 04:49:22 +08:00
},
methods: {
2021-04-05 04:02:11 +08:00
createGeometry() {
this.geometry = new three.PlaneGeometry(1, 1, 1, 1);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
createMaterial() {
2021-03-04 04:49:22 +08:00
this.material = new three.MeshBasicMaterial({ side: three.DoubleSide, map: this.loadTexture() });
},
2021-04-05 04:02:11 +08:00
loadTexture() {
2021-03-04 04:49:22 +08:00
return new three.TextureLoader().load(this.src, this.onLoaded);
},
2021-04-05 04:02:11 +08:00
refreshTexture() {
if (this.texture) this.texture.dispose();
2021-03-04 04:49:22 +08:00
this.material.map = this.loadTexture();
this.material.needsUpdate = true;
},
2021-04-05 04:02:11 +08:00
onLoaded(texture) {
2021-03-04 04:49:22 +08:00
this.texture = texture;
this.resize();
this.$emit('loaded');
},
2021-04-05 04:02:11 +08:00
resize() {
if (!this.texture) return;
const screen = this.three.size;
const iW = this.texture.image.width;
const iH = this.texture.image.height;
const iRatio = iW / iH;
let w, h;
2021-03-04 04:49:22 +08:00
if (this.width && this.height) {
w = this.width * screen.wWidth / screen.width;
h = this.height * screen.wHeight / screen.height;
} else if (this.width) {
w = this.width * screen.wWidth / screen.width;
h = w / iRatio;
} else if (this.height) {
h = this.height * screen.wHeight / screen.height;
w = h * iRatio;
}
this.mesh.scale.x = w;
this.mesh.scale.y = h;
},
},
__hmrId: 'Image',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var InstancedMesh = vue.defineComponent({
2021-03-08 04:17:46 +08:00
extends: Object3D,
2021-03-04 04:49:22 +08:00
props: {
castShadow: Boolean,
receiveShadow: Boolean,
2021-03-08 04:17:46 +08:00
count: Number,
2021-04-05 04:02:11 +08:00
...pointerProps,
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
mesh: this,
};
},
2021-04-05 04:02:11 +08:00
beforeMount() {
2021-03-04 04:49:22 +08:00
if (!this.$slots.default) {
console.error('Missing Geometry');
}
},
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
this.initMesh();
},
methods: {
2021-04-05 04:02:11 +08:00
initMesh() {
2021-03-04 04:49:22 +08:00
this.mesh = new three.InstancedMesh(this.geometry, this.material, this.count);
2021-04-05 04:02:11 +08:00
this.mesh.component = this;
bindProp(this, 'castShadow', this.mesh);
bindProp(this, 'receiveShadow', this.mesh);
if (this.onPointerEnter ||
this.onPointerOver ||
this.onPointerMove ||
this.onPointerLeave ||
this.onPointerDown ||
this.onPointerUp ||
this.onClick) {
this.three.addIntersectObject(this.mesh);
}
2021-03-04 04:49:22 +08:00
2021-03-08 04:17:46 +08:00
this.initObject3D(this.mesh);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
setGeometry(geometry) {
2021-03-04 04:49:22 +08:00
this.geometry = geometry;
2021-04-05 04:02:11 +08:00
if (this.mesh) this.mesh.geometry = geometry;
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
setMaterial(material) {
2021-03-04 04:49:22 +08:00
this.material = material;
2021-04-05 04:02:11 +08:00
this.material.instancingColor = true;
if (this.mesh) this.mesh.material = material;
2021-03-04 04:49:22 +08:00
},
},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.mesh) {
this.three.removeIntersectObject(this.mesh);
}
},
2021-03-04 04:49:22 +08:00
__hmrId: 'InstancedMesh',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Sprite = vue.defineComponent({
2021-03-08 04:17:46 +08:00
extends: Object3D,
emits: ['loaded'],
2021-03-04 04:49:22 +08:00
props: {
src: String,
},
2021-04-05 04:02:11 +08:00
data() {
2021-03-08 04:17:46 +08:00
return {
loading: true,
};
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
created() {
2021-03-04 04:49:22 +08:00
this.texture = new three.TextureLoader().load(this.src, this.onLoaded);
this.material = new three.SpriteMaterial({ map: this.texture });
this.sprite = new three.Sprite(this.material);
this.geometry = this.sprite.geometry;
2021-03-08 04:17:46 +08:00
this.initObject3D(this.sprite);
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-04 04:49:22 +08:00
this.texture.dispose();
this.material.dispose();
},
methods: {
2021-04-05 04:02:11 +08:00
onLoaded() {
2021-03-08 04:17:46 +08:00
this.loading = false;
2021-03-04 04:49:22 +08:00
this.updateUV();
this.$emit('loaded');
},
2021-04-05 04:02:11 +08:00
updateUV() {
2021-03-04 04:49:22 +08:00
this.iWidth = this.texture.image.width;
this.iHeight = this.texture.image.height;
this.iRatio = this.iWidth / this.iHeight;
2021-04-05 04:02:11 +08:00
let x = 0.5, y = 0.5;
2021-03-04 04:49:22 +08:00
if (this.iRatio > 1) {
y = 0.5 / this.iRatio;
} else {
x = 0.5 / this.iRatio;
}
2021-04-05 04:02:11 +08:00
const positions = this.geometry.attributes.position.array;
2021-03-04 04:49:22 +08:00
positions[0] = -x; positions[1] = -y;
positions[5] = x; positions[6] = -y;
positions[10] = x; positions[11] = y;
positions[15] = -x; positions[16] = y;
this.geometry.attributes.position.needsUpdate = true;
},
},
__hmrId: 'Sprite',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var Model = vue.defineComponent({
2021-03-14 02:34:34 +08:00
extends: Object3D,
2021-04-05 04:02:11 +08:00
emits: ['load', 'progress', 'error'],
data() {
return {
progress: 0,
};
},
methods: {
onLoad(model) {
this.$emit('load', model);
this.initObject3D(model);
},
onProgress(progress) {
this.progress = progress.loaded / progress.total;
this.$emit('progress', progress);
},
onError(error) {
this.$emit('error', error);
},
},
});
var GLTF = vue.defineComponent({
extends: Model,
2021-03-14 02:34:34 +08:00
props: {
src: String,
},
2021-04-05 04:02:11 +08:00
created() {
const loader = new GLTFLoader_js.GLTFLoader();
loader.load(this.src, (gltf) => {
this.onLoad(gltf.scene);
}, this.onProgress, this.onError);
2021-03-14 02:34:34 +08:00
},
2021-04-05 04:02:11 +08:00
});
2021-03-14 02:34:34 +08:00
2021-04-05 04:02:11 +08:00
var FBX = vue.defineComponent({
extends: Model,
2021-03-14 02:34:34 +08:00
props: {
src: String,
},
2021-04-05 04:02:11 +08:00
created() {
const loader = new FBXLoader_js.FBXLoader();
loader.load(this.src, (fbx) => {
this.onLoad(fbx);
}, this.onProgress, this.onError);
2021-03-14 02:34:34 +08:00
},
2021-04-05 04:02:11 +08:00
});
2021-03-14 02:34:34 +08:00
2021-04-05 04:02:11 +08:00
var EffectComposer = vue.defineComponent({
setup() {
2021-03-04 04:49:22 +08:00
return {
passes: [],
};
},
inject: ['three'],
2021-04-05 04:02:11 +08:00
provide() {
2021-03-04 04:49:22 +08:00
return {
passes: this.passes,
};
},
2021-04-05 04:02:11 +08:00
mounted() {
this.three.onAfterInit(() => {
this.composer = new EffectComposer_js.EffectComposer(this.three.renderer);
this.three.renderer.autoClear = false;
this.passes.forEach(pass => {
this.composer.addPass(pass);
2021-03-04 04:49:22 +08:00
});
2021-04-05 04:02:11 +08:00
this.three.composer = this.composer;
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
this.resize();
this.three.onAfterResize(this.resize);
2021-03-04 04:49:22 +08:00
});
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-04 04:49:22 +08:00
this.three.offAfterResize(this.resize);
},
methods: {
2021-04-05 04:02:11 +08:00
resize() {
2021-03-04 04:49:22 +08:00
this.composer.setSize(this.three.size.width, this.three.size.height);
},
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-04 04:49:22 +08:00
return this.$slots.default();
},
__hmrId: 'EffectComposer',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var EffectPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
inject: ['three', 'passes'],
2021-04-05 04:02:11 +08:00
emits: ['ready'],
beforeMount() {
2021-03-04 04:49:22 +08:00
if (!this.passes) {
console.error('Missing parent EffectComposer');
}
},
2021-04-05 04:02:11 +08:00
unmounted() {
if (this.pass.dispose) this.pass.dispose();
},
methods: {
completePass(pass) {
this.passes.push(pass);
this.pass = pass;
this.$emit('ready', pass);
},
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
render() {
2021-03-04 04:49:22 +08:00
return [];
},
__hmrId: 'EffectPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var RenderPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
if (!this.three.scene) {
console.error('Missing Scene');
}
if (!this.three.camera) {
console.error('Missing Camera');
}
2021-04-05 04:02:11 +08:00
const pass = new RenderPass_js.RenderPass(this.three.scene, this.three.camera);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'RenderPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var BokehPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
focus: {
type: Number,
default: 1,
},
aperture: {
type: Number,
default: 0.025,
},
maxblur: {
type: Number,
default: 0.01,
},
},
watch: {
2021-04-05 04:02:11 +08:00
focus() { this.pass.uniforms.focus.value = this.focus; },
aperture() { this.pass.uniforms.aperture.value = this.aperture; },
maxblur() { this.pass.uniforms.maxblur.value = this.maxblur; },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
if (!this.three.scene) {
console.error('Missing Scene');
}
if (!this.three.camera) {
console.error('Missing Camera');
}
2021-04-05 04:02:11 +08:00
const params = {
2021-03-04 04:49:22 +08:00
focus: this.focus,
aperture: this.aperture,
maxblur: this.maxblur,
width: this.three.size.width,
height: this.three.size.height,
};
2021-04-05 04:02:11 +08:00
const pass = new BokehPass_js.BokehPass(this.three.scene, this.three.camera, params);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'BokehPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var FilmPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
2021-04-05 04:02:11 +08:00
noiseIntensity: { type: Number, default: 0.5 },
scanlinesIntensity: { type: Number, default: 0.05 },
scanlinesCount: { type: Number, default: 4096 },
grayscale: { type: Number, default: 0 },
2021-03-04 04:49:22 +08:00
},
watch: {
2021-04-05 04:02:11 +08:00
noiseIntensity() { this.pass.uniforms.nIntensity.value = this.noiseIntensity; },
scanlinesIntensity() { this.pass.uniforms.sIntensity.value = this.scanlinesIntensity; },
scanlinesCount() { this.pass.uniforms.sCount.value = this.scanlinesCount; },
grayscale() { this.pass.uniforms.grayscale.value = this.grayscale; },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
mounted() {
const pass = new FilmPass_js.FilmPass(this.noiseIntensity, this.scanlinesIntensity, this.scanlinesCount, this.grayscale);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'FilmPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var FXAAPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
2021-04-05 04:02:11 +08:00
mounted() {
const pass = new ShaderPass_js.ShaderPass(FXAAShader_js.FXAAShader);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
// resize will be called in three init
this.three.onAfterResize(this.resize);
},
2021-04-05 04:02:11 +08:00
unmounted() {
2021-03-04 04:49:22 +08:00
this.three.offAfterResize(this.resize);
},
methods: {
2021-04-05 04:02:11 +08:00
resize() {
const { resolution } = this.pass.material.uniforms;
2021-03-04 04:49:22 +08:00
resolution.value.x = 1 / this.three.size.width;
resolution.value.y = 1 / this.three.size.height;
},
},
__hmrId: 'FXAAPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var HalftonePass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
shape: { type: Number, default: 1 },
radius: { type: Number, default: 4 },
rotateR: { type: Number, default: Math.PI / 12 * 1 },
rotateG: { type: Number, default: Math.PI / 12 * 2 },
rotateB: { type: Number, default: Math.PI / 12 * 3 },
scatter: { type: Number, default: 0 },
},
2021-04-05 04:02:11 +08:00
mounted() {
const pass = new HalftonePass_js.HalftonePass(this.three.size.width, this.three.size.height, {});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
['shape', 'radius', 'rotateR', 'rotateG', 'rotateB', 'scatter'].forEach(p => {
pass.uniforms[p].value = this[p];
vue.watch(() => this[p], () => {
pass.uniforms[p].value = this[p];
2021-03-04 04:49:22 +08:00
});
});
2021-04-05 04:02:11 +08:00
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'HalftonePass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var SMAAPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
// three size is not set yet, but this pass will be resized by effect composer
2021-04-05 04:02:11 +08:00
const pass = new SMAAPass_js.SMAAPass(this.three.size.width, this.three.size.height);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'SMAAPass',
2021-04-05 04:02:11 +08:00
});
var SSAOPass = vue.defineComponent({
extends: EffectPass,
props: {
scene: null,
camera: null,
options: {
type: Object,
default: () => ({}),
},
},
mounted() {
const pass = new SSAOPass_js.SSAOPass(
this.scene || this.three.scene,
this.camera || this.three.camera,
this.three.size.width,
this.three.size.height
);
for (const key of Object.keys(this.options)) {
pass[key] = this.options[key];
}
this.completePass(pass);
},
__hmrId: 'SSAOPass',
});
2021-03-04 04:49:22 +08:00
var DefaultShader = {
uniforms: {},
2021-04-05 04:02:11 +08:00
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`,
2021-03-04 04:49:22 +08:00
};
// From https://github.com/evanw/glfx.js
var TiltShift = {
uniforms: {
tDiffuse: { value: null },
blurRadius: { value: 0 },
gradientRadius: { value: 0 },
start: { value: new three.Vector2() },
end: { value: new three.Vector2() },
delta: { value: new three.Vector2() },
texSize: { value: new three.Vector2() },
},
vertexShader: DefaultShader.vertexShader,
2021-04-05 04:02:11 +08:00
fragmentShader: `
uniform sampler2D tDiffuse;
uniform float blurRadius;
uniform float gradientRadius;
uniform vec2 start;
uniform vec2 end;
uniform vec2 delta;
uniform vec2 texSize;
varying vec2 vUv;
float random(vec3 scale, float seed) {
/* use the fragment position for a different seed per-pixel */
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
vec4 color = vec4(0.0);
float total = 0.0;
/* randomize the lookup values to hide the fixed number of samples */
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
vec2 normal = normalize(vec2(start.y - end.y, end.x - start.x));
float radius = smoothstep(0.0, 1.0, abs(dot(vUv * texSize - start, normal)) / gradientRadius) * blurRadius;
for (float t = -30.0; t <= 30.0; t++) {
float percent = (t + offset - 0.5) / 30.0;
float weight = 1.0 - abs(percent);
vec4 texel = texture2D(tDiffuse, vUv + delta / texSize * percent * radius);
// vec4 texel2 = texture2D(tDiffuse, vUv + vec2(-delta.y, delta.x) / texSize * percent * radius);
/* switch to pre-multiplied alpha to correctly blur transparent images */
texel.rgb *= texel.a;
// texel2.rgb *= texel2.a;
color += texel * weight;
total += 2.0 * weight;
}
gl_FragColor = color / total;
/* switch back from pre-multiplied alpha */
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}
`,
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
var TiltShiftPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
blurRadius: { type: Number, default: 10 },
gradientRadius: { type: Number, default: 100 },
start: { type: Object, default: { x: 0, y: 100 } },
end: { type: Object, default: { x: 10, y: 100 } },
},
2021-04-05 04:02:11 +08:00
mounted() {
2021-03-04 04:49:22 +08:00
this.pass = new ShaderPass_js.ShaderPass(TiltShift);
this.passes.push(this.pass);
this.pass1 = new ShaderPass_js.ShaderPass(TiltShift);
this.passes.push(this.pass1);
2021-04-05 04:02:11 +08:00
const uniforms = this.uniforms = this.pass.uniforms;
const uniforms1 = this.uniforms1 = this.pass1.uniforms;
2021-03-04 04:49:22 +08:00
uniforms1.blurRadius = uniforms.blurRadius;
uniforms1.gradientRadius = uniforms.gradientRadius;
uniforms1.start = uniforms.start;
uniforms1.end = uniforms.end;
uniforms1.texSize = uniforms.texSize;
2021-03-08 04:17:46 +08:00
bindProp(this, 'blurRadius', uniforms.blurRadius, 'value');
bindProp(this, 'gradientRadius', uniforms.gradientRadius, 'value');
2021-03-04 04:49:22 +08:00
this.updateFocusLine();
2021-04-05 04:02:11 +08:00
['start', 'end'].forEach(p => {
vue.watch(() => this[p], this.updateFocusLine, { deep: true });
2021-03-04 04:49:22 +08:00
});
2021-04-05 04:02:11 +08:00
this.pass.setSize = (width, height) => {
2021-03-04 04:49:22 +08:00
uniforms.texSize.value.set(width, height);
};
2021-04-05 04:02:11 +08:00
// emit ready event with two passes - do so manually in this file instead
// of calling `completePass` like in other effect types
this.$emit('ready', [this.pass, this.pass1]);
2021-03-04 04:49:22 +08:00
},
methods: {
2021-04-05 04:02:11 +08:00
updateFocusLine() {
2021-03-04 04:49:22 +08:00
this.uniforms.start.value.copy(this.start);
this.uniforms.end.value.copy(this.end);
2021-04-05 04:02:11 +08:00
const dv = new three.Vector2().copy(this.end).sub(this.start).normalize();
2021-03-04 04:49:22 +08:00
this.uniforms.delta.value.copy(dv);
this.uniforms1.delta.value.set(-dv.y, dv.x);
},
},
__hmrId: 'TiltShiftPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
var UnrealBloomPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
strength: { type: Number, default: 1.5 },
radius: { type: Number, default: 0 },
threshold: { type: Number, default: 0 },
},
watch: {
2021-04-05 04:02:11 +08:00
strength() { this.pass.strength = this.strength; },
radius() { this.pass.radius = this.radius; },
threshold() { this.pass.threshold = this.threshold; },
2021-03-04 04:49:22 +08:00
},
2021-04-05 04:02:11 +08:00
mounted() {
const size = new three.Vector2(this.three.size.width, this.three.size.height);
const pass = new UnrealBloomPass_js.UnrealBloomPass(size, this.strength, this.radius, this.threshold);
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'UnrealBloomPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
// From https://github.com/evanw/glfx.js
var ZoomBlur = {
uniforms: {
tDiffuse: { value: null },
center: { value: new three.Vector2(0.5, 0.5) },
strength: { value: 0 },
},
vertexShader: DefaultShader.vertexShader,
2021-04-05 04:02:11 +08:00
fragmentShader: `
uniform sampler2D tDiffuse;
uniform vec2 center;
uniform float strength;
varying vec2 vUv;
float random(vec3 scale, float seed) {
/* use the fragment position for a different seed per-pixel */
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
vec4 color = vec4(0.0);
float total = 0.0;
vec2 toCenter = center - vUv;
/* randomize the lookup values to hide the fixed number of samples */
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
for (float t = 0.0; t <= 40.0; t++) {
float percent = (t + offset) / 40.0;
float weight = 4.0 * (percent - percent * percent);
vec4 texel = texture2D(tDiffuse, vUv + toCenter * percent * strength);
/* switch to pre-multiplied alpha to correctly blur transparent images */
texel.rgb *= texel.a;
color += texel * weight;
total += weight;
}
gl_FragColor = color / total;
/* switch back from pre-multiplied alpha */
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}
`,
2021-03-04 04:49:22 +08:00
};
2021-04-05 04:02:11 +08:00
var ZoomBlurPass = vue.defineComponent({
2021-03-04 04:49:22 +08:00
extends: EffectPass,
props: {
center: { type: Object, default: { x: 0.5, y: 0.5 } },
strength: { type: Number, default: 0.5 },
},
2021-04-05 04:02:11 +08:00
mounted() {
const pass = new ShaderPass_js.ShaderPass(ZoomBlur);
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
const uniforms = this.uniforms = pass.uniforms;
2021-03-08 04:17:46 +08:00
bindProp(this, 'center', uniforms.center, 'value');
bindProp(this, 'strength', uniforms.strength, 'value');
2021-04-05 04:02:11 +08:00
this.completePass(pass);
2021-03-04 04:49:22 +08:00
},
__hmrId: 'ZoomBlurPass',
2021-04-05 04:02:11 +08:00
});
2021-03-04 04:49:22 +08:00
var TROIS = /*#__PURE__*/Object.freeze({
__proto__: null,
Renderer: Renderer,
OrthographicCamera: OrthographicCamera,
PerspectiveCamera: PerspectiveCamera,
Camera: PerspectiveCamera,
Group: Group,
Scene: Scene,
2021-04-05 04:02:11 +08:00
Object3D: Object3D,
Raycaster: Raycaster,
2021-03-04 04:49:22 +08:00
BoxGeometry: BoxGeometry,
CircleGeometry: CircleGeometry,
ConeGeometry: ConeGeometry,
CylinderGeometry: CylinderGeometry,
DodecahedronGeometry: DodecahedronGeometry,
IcosahedronGeometry: IcosahedronGeometry,
LatheGeometry: LatheGeometry,
OctahedronGeometry: OctahedronGeometry,
2021-04-07 03:46:35 +08:00
PlaneGeometry: PlaneGeometry,
2021-03-04 04:49:22 +08:00
PolyhedronGeometry: PolyhedronGeometry,
RingGeometry: RingGeometry,
SphereGeometry: SphereGeometry,
TetrahedronGeometry: TetrahedronGeometry,
TorusGeometry: TorusGeometry,
TorusKnotGeometry: TorusKnotGeometry,
TubeGeometry: TubeGeometry,
AmbientLight: AmbientLight,
DirectionalLight: DirectionalLight,
2021-03-08 04:17:46 +08:00
HemisphereLight: HemisphereLight,
2021-03-04 04:49:22 +08:00
PointLight: PointLight,
2021-03-08 04:17:46 +08:00
RectAreaLight: RectAreaLight,
2021-03-04 04:49:22 +08:00
SpotLight: SpotLight,
BasicMaterial: BasicMaterial,
LambertMaterial: LambertMaterial,
MatcapMaterial: MatcapMaterial,
PhongMaterial: PhongMaterial,
PhysicalMaterial: PhysicalMaterial,
2021-03-14 02:34:34 +08:00
ShaderMaterial: ShaderMaterial,
2021-03-04 04:49:22 +08:00
StandardMaterial: StandardMaterial,
SubSurfaceMaterial: SubSurfaceMaterial,
ToonMaterial: ToonMaterial,
Texture: Texture,
CubeTexture: CubeTexture,
Mesh: Mesh,
Box: Box,
Circle: Circle,
Cone: Cone,
Cylinder: Cylinder,
Dodecahedron: Dodecahedron,
Icosahedron: Icosahedron,
Lathe: Lathe,
Octahedron: Octahedron,
Plane: Plane,
Polyhedron: Polyhedron,
Ring: Ring,
Sphere: Sphere,
Tetrahedron: Tetrahedron,
Text: Text,
Torus: Torus,
TorusKnot: TorusKnot,
Tube: Tube,
Image: Image,
InstancedMesh: InstancedMesh,
Sprite: Sprite,
2021-03-14 02:34:34 +08:00
GLTFModel: GLTF,
FBXModel: FBX,
2021-03-04 04:49:22 +08:00
EffectComposer: EffectComposer,
RenderPass: RenderPass,
BokehPass: BokehPass,
FilmPass: FilmPass,
FXAAPass: FXAAPass,
HalftonePass: HalftonePass,
SMAAPass: SMAAPass,
2021-04-05 04:02:11 +08:00
SSAOPass: SSAOPass,
2021-03-04 04:49:22 +08:00
TiltShiftPass: TiltShiftPass,
UnrealBloomPass: UnrealBloomPass,
ZoomBlurPass: ZoomBlurPass,
setFromProp: setFromProp,
2021-03-14 02:34:34 +08:00
bindProps: bindProps,
2021-03-08 04:17:46 +08:00
bindProp: bindProp,
2021-03-04 04:49:22 +08:00
propsValues: propsValues,
lerp: lerp,
lerpv2: lerpv2,
lerpv3: lerpv3,
limit: limit,
2021-04-05 04:02:11 +08:00
getMatcapUrl: getMatcapUrl
2021-03-04 04:49:22 +08:00
});
2021-04-05 04:02:11 +08:00
const TroisJSVuePlugin = {
install: (app) => {
const comps = [
2021-03-04 04:49:22 +08:00
'Camera',
'OrthographicCamera',
'PerspectiveCamera',
2021-04-05 04:02:11 +08:00
'Raycaster',
2021-03-04 04:49:22 +08:00
'Renderer',
'Scene',
'Group',
'AmbientLight',
'DirectionalLight',
2021-03-08 04:17:46 +08:00
'HemisphereLight',
2021-03-04 04:49:22 +08:00
'PointLight',
2021-03-08 04:17:46 +08:00
'RectAreaLight',
2021-03-04 04:49:22 +08:00
'SpotLight',
'BasicMaterial',
'LambertMaterial',
'MatcapMaterial',
'PhongMaterial',
'PhysicalMaterial',
'ShaderMaterial',
'StandardMaterial',
'SubSurfaceMaterial',
'ToonMaterial',
'Texture',
'CubeTexture',
'Mesh',
2021-03-14 02:34:34 +08:00
'Box', 'BoxGeometry',
'Circle', 'CircleGeometry',
'Cone', 'ConeGeometry',
'Cylinder', 'CylinderGeometry',
'Dodecahedron', 'DodecahedronGeometry',
'Icosahedron', 'IcosahedronGeometry',
'Lathe', 'LatheGeometry',
'Octahedron', 'OctahedronGeometry',
2021-04-07 03:46:35 +08:00
'Plane', 'PlaneGeometry',
2021-03-14 02:34:34 +08:00
'Polyhedron', 'PolyhedronGeometry',
'Ring', 'RingGeometry',
'Sphere', 'SphereGeometry',
'Tetrahedron', 'TetrahedronGeometry',
2021-03-04 04:49:22 +08:00
'Text',
2021-03-14 02:34:34 +08:00
'Torus', 'TorusGeometry',
'TorusKnot', 'TorusKnotGeometry',
'Tube', 'TubeGeometry',
2021-03-04 04:49:22 +08:00
'Image',
'InstancedMesh',
'Sprite',
2021-03-14 02:34:34 +08:00
'FBXModel',
'GLTFModel',
2021-03-04 04:49:22 +08:00
'BokehPass',
'EffectComposer',
'FilmPass',
'FXAAPass',
'HalftonePass',
'RenderPass',
'SAOPass',
'SMAAPass',
2021-04-05 04:02:11 +08:00
'SSAOPass',
2021-03-04 04:49:22 +08:00
'TiltShiftPass',
'UnrealBloomPass',
'ZoomBlurPass',
2021-04-05 04:02:11 +08:00
'GLTFViewer',
];
2021-03-04 04:49:22 +08:00
2021-04-05 04:02:11 +08:00
comps.forEach(comp => {
2021-03-04 04:49:22 +08:00
app.component(comp, TROIS[comp]);
});
},
};
2021-03-08 04:17:46 +08:00
function createApp(params) {
return vue.createApp(params).use(TroisJSVuePlugin);
}
2021-03-04 04:49:22 +08:00
exports.AmbientLight = AmbientLight;
exports.BasicMaterial = BasicMaterial;
exports.BokehPass = BokehPass;
exports.Box = Box;
exports.BoxGeometry = BoxGeometry;
exports.Camera = PerspectiveCamera;
exports.Circle = Circle;
exports.CircleGeometry = CircleGeometry;
exports.Cone = Cone;
exports.ConeGeometry = ConeGeometry;
exports.CubeTexture = CubeTexture;
exports.Cylinder = Cylinder;
exports.CylinderGeometry = CylinderGeometry;
exports.DirectionalLight = DirectionalLight;
exports.Dodecahedron = Dodecahedron;
exports.DodecahedronGeometry = DodecahedronGeometry;
exports.EffectComposer = EffectComposer;
2021-03-14 02:34:34 +08:00
exports.FBXModel = FBX;
2021-03-04 04:49:22 +08:00
exports.FXAAPass = FXAAPass;
exports.FilmPass = FilmPass;
2021-03-14 02:34:34 +08:00
exports.GLTFModel = GLTF;
2021-03-04 04:49:22 +08:00
exports.Group = Group;
exports.HalftonePass = HalftonePass;
2021-03-08 04:17:46 +08:00
exports.HemisphereLight = HemisphereLight;
2021-03-04 04:49:22 +08:00
exports.Icosahedron = Icosahedron;
exports.IcosahedronGeometry = IcosahedronGeometry;
exports.Image = Image;
exports.InstancedMesh = InstancedMesh;
exports.LambertMaterial = LambertMaterial;
exports.Lathe = Lathe;
exports.LatheGeometry = LatheGeometry;
exports.MatcapMaterial = MatcapMaterial;
exports.Mesh = Mesh;
2021-04-05 04:02:11 +08:00
exports.Object3D = Object3D;
2021-03-04 04:49:22 +08:00
exports.Octahedron = Octahedron;
exports.OctahedronGeometry = OctahedronGeometry;
exports.OrthographicCamera = OrthographicCamera;
exports.PerspectiveCamera = PerspectiveCamera;
exports.PhongMaterial = PhongMaterial;
exports.PhysicalMaterial = PhysicalMaterial;
exports.Plane = Plane;
2021-04-07 03:46:35 +08:00
exports.PlaneGeometry = PlaneGeometry;
2021-03-04 04:49:22 +08:00
exports.PointLight = PointLight;
exports.Polyhedron = Polyhedron;
exports.PolyhedronGeometry = PolyhedronGeometry;
2021-04-05 04:02:11 +08:00
exports.Raycaster = Raycaster;
2021-03-08 04:17:46 +08:00
exports.RectAreaLight = RectAreaLight;
2021-03-04 04:49:22 +08:00
exports.RenderPass = RenderPass;
exports.Renderer = Renderer;
exports.Ring = Ring;
exports.RingGeometry = RingGeometry;
exports.SMAAPass = SMAAPass;
2021-04-05 04:02:11 +08:00
exports.SSAOPass = SSAOPass;
2021-03-04 04:49:22 +08:00
exports.Scene = Scene;
2021-03-14 02:34:34 +08:00
exports.ShaderMaterial = ShaderMaterial;
2021-03-04 04:49:22 +08:00
exports.Sphere = Sphere;
exports.SphereGeometry = SphereGeometry;
exports.SpotLight = SpotLight;
exports.Sprite = Sprite;
exports.StandardMaterial = StandardMaterial;
exports.SubSurfaceMaterial = SubSurfaceMaterial;
exports.Tetrahedron = Tetrahedron;
exports.TetrahedronGeometry = TetrahedronGeometry;
exports.Text = Text;
exports.Texture = Texture;
exports.TiltShiftPass = TiltShiftPass;
exports.ToonMaterial = ToonMaterial;
exports.Torus = Torus;
exports.TorusGeometry = TorusGeometry;
exports.TorusKnot = TorusKnot;
exports.TorusKnotGeometry = TorusKnotGeometry;
exports.TroisJSVuePlugin = TroisJSVuePlugin;
exports.Tube = Tube;
exports.TubeGeometry = TubeGeometry;
exports.UnrealBloomPass = UnrealBloomPass;
exports.ZoomBlurPass = ZoomBlurPass;
2021-03-08 04:17:46 +08:00
exports.bindProp = bindProp;
2021-03-14 02:34:34 +08:00
exports.bindProps = bindProps;
2021-03-08 04:17:46 +08:00
exports.createApp = createApp;
2021-03-04 04:49:22 +08:00
exports.getMatcapUrl = getMatcapUrl;
exports.lerp = lerp;
exports.lerpv2 = lerpv2;
exports.lerpv3 = lerpv3;
exports.limit = limit;
exports.propsValues = propsValues;
exports.setFromProp = setFromProp;