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

3117 lines
90 KiB
JavaScript
Raw Normal View History

2023-04-07 01:39:47 +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');
var RectAreaLightUniformsLib_js = require('three/examples/jsm/lights/RectAreaLightUniformsLib.js');
var RectAreaLightHelper_js = require('three/examples/jsm/helpers/RectAreaLightHelper.js');
var TextGeometry_js = require('three/examples/jsm/geometries/TextGeometry.js');
var FontLoader_js = require('three/examples/jsm/loaders/FontLoader.js');
var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
var FBXLoader_js = require('three/examples/jsm/loaders/FBXLoader.js');
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');
var SSAOPass_js = require('three/examples/jsm/postprocessing/SSAOPass.js');
var UnrealBloomPass_js = require('three/examples/jsm/postprocessing/UnrealBloomPass.js');
function applyObjectProps(dst, options, setter) {
if (options instanceof Object) {
Object.entries(options).forEach(([key, value]) => {
if (setter)
setter(dst, key, value);
else
dst[key] = value;
});
}
}
function bindObjectProp(src, prop, dst, apply = true, setter) {
if (apply)
applyObjectProps(dst, src[prop], setter);
const r = vue.toRef(src, prop);
return vue.watch(r, (value) => {
applyObjectProps(dst, value, setter);
});
}
function bindObjectProps(src, dst, apply = true, setter) {
if (apply)
applyObjectProps(dst, src, setter);
const r = vue.ref(src);
return vue.watch(r, (value) => {
applyObjectProps(dst, value, setter);
}, { deep: true });
}
function setFromProp(o, prop) {
if (prop instanceof Object) {
Object.entries(prop).forEach(([key, value]) => {
o[key] = value;
});
}
}
function bindProps(src, props, dst) {
props.forEach((prop) => {
bindProp(src, prop, dst, prop);
});
}
function bindProp(src, srcProp, dst, dstProp) {
const _dstProp = dstProp || srcProp;
const ref2 = vue.toRef(src, srcProp);
if (ref2.value instanceof Object) {
setFromProp(dst[_dstProp], ref2.value);
vue.watch(ref2, (value) => {
setFromProp(dst[_dstProp], value);
}, { deep: true });
} else {
if (ref2.value !== void 0)
dst[_dstProp] = src[srcProp];
vue.watch(ref2, (value) => {
dst[_dstProp] = value;
});
}
}
function propsValues(props, exclude = []) {
const values = {};
Object.entries(props).forEach(([key, value]) => {
if (!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 limit(val, min, max) {
return val < min ? min : val > max ? max : val;
}
const MATCAP_ROOT = "https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d";
const DEFAULT_MATCAP = "0404E8_0404B5_0404CB_3333FC";
function getMatcapUrl(hash = DEFAULT_MATCAP, format = 1024) {
const fileName = `${hash}${getMatcapFormatString(format)}.png`;
return `${MATCAP_ROOT}/${format}/${fileName}`;
}
function getMatcapFormatString(format) {
switch (format) {
case 64:
return "-64px";
case 128:
return "-128px";
case 256:
return "-256px";
case 512:
return "-512px";
default:
return "";
}
}
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, recursive = false) => {
raycaster.setFromCamera(coords, camera);
return raycaster.intersectObjects(objects, recursive);
};
return {
position,
updatePosition,
intersect
};
}
function usePointer(options) {
const {
camera,
domElement,
intersectObjects,
intersectRecursive = false,
touch = true,
resetOnEnd = false,
onEnter = () => {
},
onMove = () => {
},
onLeave = () => {
},
onClick = () => {
},
onIntersectEnter = () => {
},
onIntersectOver = () => {
},
onIntersectMove = () => {
},
onIntersectLeave = () => {
},
onIntersectClick = () => {
}
} = options;
const position = new three.Vector2(0, 0);
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.set(0, 0);
positionN.set(0, 0);
positionV3.set(0, 0, 0);
}
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() {
const _intersectObjects = getIntersectObjects();
if (_intersectObjects.length) {
const intersects = raycaster.intersect(positionN, _intersectObjects, intersectRecursive);
const offObjects = [..._intersectObjects];
const iMeshes = [];
intersects.forEach((intersect2) => {
var _a, _b, _c;
const { object } = intersect2;
const component = getComponent(object);
if (object instanceof three.InstancedMesh) {
if (iMeshes.indexOf(object) !== -1)
return;
iMeshes.push(object);
}
if (!object.userData.over) {
object.userData.over = true;
const overEvent = { type: "pointerover", over: true, component, intersect: intersect2 };
const enterEvent = { ...overEvent, type: "pointerenter" };
onIntersectOver(overEvent);
onIntersectEnter(enterEvent);
(_a = component == null ? void 0 : component.onPointerOver) == null ? void 0 : _a.call(component, overEvent);
(_b = component == null ? void 0 : component.onPointerEnter) == null ? void 0 : _b.call(component, enterEvent);
}
const moveEvent = { type: "pointermove", component, intersect: intersect2 };
onIntersectMove(moveEvent);
(_c = component == null ? void 0 : component.onPointerMove) == null ? void 0 : _c.call(component, moveEvent);
offObjects.splice(offObjects.indexOf(object), 1);
});
offObjects.forEach((object) => {
var _a, _b;
const component = getComponent(object);
if (object.userData.over) {
object.userData.over = false;
const overEvent = { type: "pointerover", over: false, component };
const leaveEvent = { ...overEvent, type: "pointerleave" };
onIntersectOver(overEvent);
onIntersectLeave(leaveEvent);
(_a = component == null ? void 0 : component.onPointerOver) == null ? void 0 : _a.call(component, overEvent);
(_b = component == null ? void 0 : component.onPointerLeave) == null ? void 0 : _b.call(component, 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);
const _intersectObjects = getIntersectObjects();
if (_intersectObjects.length) {
const intersects = raycaster.intersect(positionN, _intersectObjects, intersectRecursive);
const iMeshes = [];
intersects.forEach((intersect2) => {
var _a;
const { object } = intersect2;
const component = getComponent(object);
if (object instanceof three.InstancedMesh) {
if (iMeshes.indexOf(object) !== -1)
return;
iMeshes.push(object);
}
const event2 = { type: "click", component, intersect: intersect2 };
onIntersectClick(event2);
(_a = component == null ? void 0 : component.onClick) == null ? void 0 : _a.call(component, event2);
});
}
onClick({ type: "click", position, positionN, positionV3 });
}
function pointerLeave() {
if (resetOnEnd)
reset();
onLeave({ type: "pointerleave" });
}
function getComponent(object) {
if (object.userData.component)
return object.userData.component;
let parent = object.parent;
while (parent) {
if (parent.userData.component) {
return parent.userData.component;
}
parent = parent.parent;
}
return void 0;
}
function getIntersectObjects() {
if (typeof intersectObjects === "function") {
return intersectObjects();
} else
return intersectObjects;
}
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;
}
}
function useThree(params) {
const config = {
antialias: true,
alpha: false,
autoClear: true,
orbitCtrl: false,
pointer: false,
resize: false,
width: 300,
height: 150
};
if (params) {
Object.entries(params).forEach(([key, value]) => {
config[key] = value;
});
}
const size = {
width: 1,
height: 1,
wWidth: 1,
wHeight: 1,
ratio: 1
};
const beforeRenderCallbacks = [];
const intersectObjects = [];
const renderer = createRenderer();
const obj = {
config,
renderer,
size,
init,
dispose,
render,
renderC,
setSize,
addIntersectObject,
removeIntersectObject
};
return obj;
function createRenderer() {
const renderer2 = new three.WebGLRenderer({ canvas: config.canvas, antialias: config.antialias, alpha: config.alpha, ...config.params });
renderer2.autoClear = config.autoClear;
return renderer2;
}
function init() {
if (!obj.scene) {
console.error("Missing Scene");
return false;
}
if (!obj.camera) {
console.error("Missing Camera");
return false;
}
if (config.resize) {
onResize();
window.addEventListener("resize", onResize);
} else if (config.width && config.height) {
setSize(config.width, config.height);
}
initPointer();
if (config.orbitCtrl) {
const cameraCtrl = new OrbitControls_js.OrbitControls(obj.camera, obj.renderer.domElement);
if (config.orbitCtrl instanceof Object) {
Object.entries(config.orbitCtrl).forEach(([key, value]) => {
cameraCtrl[key] = value;
});
}
onBeforeRender(() => {
cameraCtrl.update();
});
obj.cameraCtrl = cameraCtrl;
}
return true;
}
function initPointer() {
let pointerConf = {
camera: obj.camera,
domElement: obj.renderer.domElement,
intersectObjects
};
if (config.pointer && config.pointer instanceof Object) {
pointerConf = { ...pointerConf, ...config.pointer };
}
const pointer = obj.pointer = usePointer(pointerConf);
if (config.pointer || intersectObjects.length) {
pointer.addListeners();
if (pointerConf.intersectMode === "frame") {
onBeforeRender(pointer.intersect);
}
}
}
function onBeforeRender(cb) {
beforeRenderCallbacks.push(cb);
}
function render() {
beforeRenderCallbacks.forEach((c) => c());
obj.renderer.render(obj.scene, obj.camera);
}
function renderC() {
beforeRenderCallbacks.forEach((c) => c());
obj.composer.render();
}
function addIntersectObject(o) {
if (intersectObjects.indexOf(o) === -1) {
intersectObjects.push(o);
}
if (obj.pointer && !obj.pointer.listeners) {
obj.pointer.addListeners();
}
}
function removeIntersectObject(o) {
const i = intersectObjects.indexOf(o);
if (i !== -1) {
intersectObjects.splice(i, 1);
}
if (obj.pointer && !config.pointer && intersectObjects.length === 0) {
obj.pointer.removeListeners();
}
}
function dispose() {
window.removeEventListener("resize", onResize);
if (obj.pointer)
obj.pointer.removeListeners();
if (obj.cameraCtrl)
obj.cameraCtrl.dispose();
if (obj.renderer)
obj.renderer.dispose();
}
function onResize() {
var _a;
if (config.resize === "window") {
setSize(window.innerWidth, window.innerHeight);
} else {
const elt = obj.renderer.domElement.parentNode;
if (elt)
setSize(elt.clientWidth, elt.clientHeight);
}
(_a = config.onResize) == null ? void 0 : _a.call(config, size);
}
function setSize(width, height) {
size.width = width;
size.height = height;
size.ratio = width / height;
obj.renderer.setSize(width, height, false);
const camera = obj.camera;
if (camera.type === "PerspectiveCamera") {
const pCamera = camera;
pCamera.aspect = size.ratio;
pCamera.updateProjectionMatrix();
}
if (camera.type === "OrthographicCamera") {
const oCamera = camera;
size.wWidth = oCamera.right - oCamera.left;
size.wHeight = oCamera.top - oCamera.bottom;
} else {
const wsize = getCameraSize();
size.wWidth = wsize[0];
size.wHeight = wsize[1];
}
}
function getCameraSize() {
const camera = obj.camera;
const vFOV = camera.fov * Math.PI / 180;
const h = 2 * Math.tan(vFOV / 2) * Math.abs(camera.position.z);
const w = h * camera.aspect;
return [w, h];
}
}
const RendererInjectionKey = Symbol("Renderer");
var Renderer = vue.defineComponent({
name: "Renderer",
props: {
params: { type: Object, default: () => ({}) },
antialias: Boolean,
alpha: Boolean,
autoClear: { type: Boolean, default: true },
orbitCtrl: { type: [Boolean, Object], default: false },
pointer: { type: [Boolean, Object], default: false },
resize: { type: [Boolean, String], default: false },
shadow: Boolean,
width: String,
height: String,
pixelRatio: Number,
xr: Boolean,
props: { type: Object, default: () => ({}) },
onReady: Function
},
inheritAttrs: false,
setup(props, { attrs }) {
const initCallbacks = [];
const mountedCallbacks = [];
const beforeRenderCallbacks = [];
const afterRenderCallbacks = [];
const resizeCallbacks = [];
const canvas = document.createElement("canvas");
Object.entries(attrs).forEach(([key, value]) => {
const matches = key.match(/^on([A-Z][a-zA-Z]*)$/);
if (matches) {
canvas.addEventListener(matches[1].toLowerCase(), value);
} else {
canvas.setAttribute(key, value);
}
});
const config = {
canvas,
params: props.params,
antialias: props.antialias,
alpha: props.alpha,
autoClear: props.autoClear,
orbitCtrl: props.orbitCtrl,
pointer: props.pointer,
resize: props.resize
};
if (props.width)
config.width = parseInt(props.width);
if (props.height)
config.height = parseInt(props.height);
const three = useThree(config);
bindObjectProp(props, "props", three.renderer);
vue.watchEffect(() => {
if (props.pixelRatio)
three.renderer.setPixelRatio(props.pixelRatio);
});
const renderFn = () => {
};
return {
canvas,
three,
renderer: three.renderer,
size: three.size,
renderFn,
raf: true,
initCallbacks,
mountedCallbacks,
beforeRenderCallbacks,
afterRenderCallbacks,
resizeCallbacks
};
},
computed: {
camera: {
get: function() {
return this.three.camera;
},
set: function(camera) {
this.three.camera = camera;
}
},
scene: {
get: function() {
return this.three.scene;
},
set: function(scene) {
this.three.scene = scene;
}
},
composer: {
get: function() {
return this.three.composer;
},
set: function(composer) {
this.three.composer = composer;
}
}
},
provide() {
return {
[RendererInjectionKey]: this
};
},
mounted() {
var _a;
this.$el.parentNode.insertBefore(this.canvas, this.$el);
if (this.three.init()) {
if (this.three.pointer) {
this.$pointer = this.three.pointer;
}
this.three.config.onResize = (size) => {
this.resizeCallbacks.forEach((e) => e({ type: "resize", renderer: this, size }));
};
if (this.shadow) {
this.renderer.shadowMap.enabled = true;
}
this.renderFn = this.three.composer ? this.three.renderC : this.three.render;
this.initCallbacks.forEach((e) => e({ type: "init", renderer: this }));
(_a = this.onReady) == null ? void 0 : _a.call(this, this);
if (this.xr) {
this.renderer.xr.enabled = true;
this.renderer.setAnimationLoop(this.render);
} else {
requestAnimationFrame(this.renderLoop);
}
}
this.mountedCallbacks.forEach((e) => e({ type: "mounted", renderer: this }));
},
beforeUnmount() {
this.canvas.remove();
this.beforeRenderCallbacks = [];
this.afterRenderCallbacks = [];
this.raf = false;
this.three.dispose();
},
methods: {
onInit(cb) {
this.addListener("init", cb);
},
onMounted(cb) {
this.addListener("mounted", cb);
},
onBeforeRender(cb) {
this.addListener("beforerender", cb);
},
offBeforeRender(cb) {
this.removeListener("beforerender", cb);
},
onAfterRender(cb) {
this.addListener("afterrender", cb);
},
offAfterRender(cb) {
this.removeListener("afterrender", cb);
},
onResize(cb) {
this.addListener("resize", cb);
},
offResize(cb) {
this.removeListener("resize", cb);
},
addListener(type, cb) {
const callbacks = this.getCallbacks(type);
callbacks.push(cb);
},
removeListener(type, cb) {
const callbacks = this.getCallbacks(type);
const index = callbacks.indexOf(cb);
if (index !== -1)
callbacks.splice(index, 1);
},
getCallbacks(type) {
if (type === "init") {
return this.initCallbacks;
} else if (type === "mounted") {
return this.mountedCallbacks;
} else if (type === "beforerender") {
return this.beforeRenderCallbacks;
} else if (type === "afterrender") {
return this.afterRenderCallbacks;
} else {
return this.resizeCallbacks;
}
},
render(time) {
this.beforeRenderCallbacks.forEach((e) => e({ type: "beforerender", renderer: this, time }));
this.renderFn({ renderer: this, time });
this.afterRenderCallbacks.forEach((e) => e({ type: "afterrender", renderer: this, time }));
},
renderLoop(time) {
if (this.raf)
requestAnimationFrame(this.renderLoop);
this.render(time);
}
},
render() {
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: "Renderer"
});
var Camera = vue.defineComponent({
props: {
props: { type: Object, default: () => ({}) }
},
render() {
return this.$slots.default ? this.$slots.default() : [];
}
});
function cameraSetProp(camera, key, value, updateProjectionMatrix = true) {
camera[key] = value;
if (updateProjectionMatrix)
camera.updateProjectionMatrix();
}
var OrthographicCamera = vue.defineComponent({
extends: Camera,
name: "OrthographicCamera",
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: 2e3 },
zoom: { type: Number, default: 1 },
position: { type: Object, default: () => ({ x: 0, y: 0, z: 0 }) }
},
setup(props) {
const renderer = vue.inject(RendererInjectionKey);
if (!renderer) {
console.error("Renderer not found");
return;
}
const camera = new three.OrthographicCamera(props.left, props.right, props.top, props.bottom, props.near, props.far);
renderer.camera = camera;
bindProp(props, "position", camera);
bindObjectProp(props, "props", camera, true, cameraSetProp);
["left", "right", "top", "bottom", "near", "far", "zoom"].forEach((p) => {
vue.watch(() => props[p], (value) => {
cameraSetProp(camera, p, value);
});
});
return { renderer, camera };
},
__hmrId: "OrthographicCamera"
});
var PerspectiveCamera = vue.defineComponent({
extends: Camera,
name: "PerspectiveCamera",
props: {
aspect: { type: Number, default: 1 },
far: { type: Number, default: 2e3 },
fov: { type: Number, default: 50 },
near: { type: Number, default: 0.1 },
position: { type: Object, default: () => ({ x: 0, y: 0, z: 0 }) },
lookAt: { type: Object, default: null }
},
setup(props) {
var _a;
const renderer = vue.inject(RendererInjectionKey);
if (!renderer) {
console.error("Renderer not found");
return;
}
const camera = new three.PerspectiveCamera(props.fov, props.aspect, props.near, props.far);
renderer.camera = camera;
bindProp(props, "position", camera);
if (props.lookAt)
camera.lookAt((_a = props.lookAt.x) != null ? _a : 0, props.lookAt.y, props.lookAt.z);
vue.watch(() => props.lookAt, (v) => {
var _a2;
camera.lookAt((_a2 = v.x) != null ? _a2 : 0, v.y, v.z);
}, { deep: true });
bindObjectProp(props, "props", camera, true, cameraSetProp);
["aspect", "far", "fov", "near"].forEach((p) => {
vue.watch(() => props[p], (value) => {
cameraSetProp(camera, p, value);
});
});
return { renderer, camera };
},
__hmrId: "PerspectiveCamera"
});
const SceneInjectionKey = Symbol("Scene");
var Scene = vue.defineComponent({
name: "Scene",
props: {
background: [String, Number, Object]
},
setup(props) {
const renderer = vue.inject(RendererInjectionKey);
const scene = new three.Scene();
if (!renderer) {
console.error("Renderer not found");
return;
}
renderer.scene = scene;
vue.provide(SceneInjectionKey, scene);
const setBackground = (value) => {
if (!value)
return;
if (typeof value === "string" || typeof value === "number") {
if (scene.background instanceof three.Color)
scene.background.set(value);
else
scene.background = new three.Color(value);
} else if (value instanceof three.Texture) {
scene.background = value;
}
};
setBackground(props.background);
vue.watch(() => props.background, setBackground);
const add = (o) => {
scene.add(o);
};
const remove = (o) => {
scene.remove(o);
};
return { scene, add, remove };
},
render() {
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: "Scene"
});
const pointerProps = {
onPointerEnter: Function,
onPointerOver: Function,
onPointerMove: Function,
onPointerLeave: Function,
onPointerDown: Function,
onPointerUp: Function,
onClick: Function
};
var Object3D = vue.defineComponent({
name: "Object3D",
inject: {
renderer: RendererInjectionKey,
scene: SceneInjectionKey
},
emits: ["created", "ready"],
props: {
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, order: "XYZ" }) },
lookAt: { type: Object, default: null },
userData: { type: Object, default: () => ({}) },
visible: { type: Boolean, default: true },
props: { type: Object, default: () => ({}) },
disableAdd: { type: Boolean, default: false },
disableRemove: { type: Boolean, default: false },
...pointerProps
},
setup() {
return {};
},
created() {
if (!this.renderer) {
console.error("Missing parent Renderer");
}
if (!this.scene) {
console.error("Missing parent Scene");
}
},
unmounted() {
if (!this.disableRemove)
this.removeFromParent();
if (this.o3d) {
if (this.renderer)
this.renderer.three.removeIntersectObject(this.o3d);
}
},
methods: {
initObject3D(o3d) {
var _a;
this.o3d = o3d;
o3d.userData.component = this;
if (this.onPointerEnter || this.onPointerOver || this.onPointerMove || this.onPointerLeave || this.onPointerDown || this.onPointerUp || this.onClick) {
if (this.renderer)
this.renderer.three.addIntersectObject(o3d);
}
bindProp(this, "position", o3d);
bindProp(this, "rotation", o3d);
bindProp(this, "scale", o3d);
bindProp(this, "userData", o3d.userData);
bindProp(this, "visible", o3d);
bindObjectProp(this, "props", o3d);
this.$emit("created", o3d);
if (this.lookAt)
o3d.lookAt((_a = this.lookAt.x) != null ? _a : 0, this.lookAt.y, this.lookAt.z);
vue.watch(() => this.lookAt, (v) => {
var _a2;
o3d.lookAt((_a2 = v.x) != null ? _a2 : 0, v.y, v.z);
}, { deep: true });
this.parent = this.getParent();
if (!this.disableAdd) {
if (this.addToParent())
this.$emit("ready", this);
else
console.error("Missing parent (Scene, Group...)");
}
},
getParent() {
let parent = this.$parent;
if (!parent) {
const instance = vue.getCurrentInstance();
if (instance && instance.parent)
parent = instance.parent.ctx;
}
while (parent) {
if (parent.add)
return parent;
parent = parent.$parent;
}
return void 0;
},
addToParent(o) {
const o3d = o || this.o3d;
if (this.parent) {
this.parent.add(o3d);
return true;
}
return false;
},
removeFromParent(o) {
const o3d = o || this.o3d;
if (this.parent) {
this.parent.remove(o3d);
return true;
}
return false;
},
add(o) {
var _a;
(_a = this.o3d) == null ? void 0 : _a.add(o);
},
remove(o) {
var _a;
(_a = this.o3d) == null ? void 0 : _a.remove(o);
}
},
render() {
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: "Object3D"
});
var Group = vue.defineComponent({
name: "Group",
extends: Object3D,
setup() {
return {
group: new three.Group()
};
},
created() {
this.initObject3D(this.group);
},
__hmrId: "Group"
});
const emptyCallBack = () => {
};
var Raycaster = vue.defineComponent({
name: "Raycaster",
props: {
onPointerEnter: { type: Function, default: emptyCallBack },
onPointerOver: { type: Function, default: emptyCallBack },
onPointerMove: { type: Function, default: emptyCallBack },
onPointerLeave: { type: Function, default: emptyCallBack },
onClick: { type: Function, default: emptyCallBack },
intersectMode: { type: String, default: "move" },
intersectRecursive: { type: Boolean, default: false }
},
setup() {
const renderer = vue.inject(RendererInjectionKey);
return { renderer };
},
mounted() {
if (!this.renderer) {
console.error("Renderer not found");
return;
}
const renderer = this.renderer;
this.renderer.onMounted(() => {
if (!renderer.camera)
return;
this.pointer = usePointer({
camera: renderer.camera,
domElement: renderer.canvas,
intersectObjects: () => renderer.scene ? renderer.scene.children : [],
intersectRecursive: this.intersectRecursive,
onIntersectEnter: this.onPointerEnter,
onIntersectOver: this.onPointerOver,
onIntersectMove: this.onPointerMove,
onIntersectLeave: this.onPointerLeave,
onIntersectClick: this.onClick
});
this.pointer.addListeners();
if (this.intersectMode === "frame") {
renderer.onBeforeRender(this.pointer.intersect);
}
});
},
unmounted() {
var _a;
if (this.pointer) {
this.pointer.removeListeners();
(_a = this.renderer) == null ? void 0 : _a.offBeforeRender(this.pointer.intersect);
}
},
render() {
return [];
},
__hmrId: "Raycaster"
});
var CubeCamera = vue.defineComponent({
extends: Object3D,
props: {
cubeRTSize: { type: Number, default: 256 },
cubeCameraNear: { type: Number, default: 0.1 },
cubeCameraFar: { type: Number, default: 2e3 },
autoUpdate: Boolean,
hideMeshes: { type: Array, default: () => [] }
},
setup(props) {
const rendererC = vue.inject(RendererInjectionKey);
if (!rendererC || !rendererC.scene) {
console.error("Missing Renderer / Scene");
return {};
}
const renderer = rendererC.renderer, scene = rendererC.scene;
const cubeRT = new three.WebGLCubeRenderTarget(props.cubeRTSize, { format: three.RGBAFormat, generateMipmaps: true, minFilter: three.LinearMipmapLinearFilter });
const cubeCamera = new three.CubeCamera(props.cubeCameraNear, props.cubeCameraFar, cubeRT);
const updateRT = () => {
props.hideMeshes.forEach((m) => {
m.visible = false;
});
cubeCamera.update(renderer, scene);
props.hideMeshes.forEach((m) => {
m.visible = true;
});
};
if (props.autoUpdate) {
rendererC.onBeforeRender(updateRT);
vue.onUnmounted(() => {
rendererC.offBeforeRender(updateRT);
});
} else {
rendererC.onMounted(updateRT);
}
return { cubeRT, cubeCamera, updateRT };
},
created() {
if (this.cubeCamera)
this.initObject3D(this.cubeCamera);
},
render() {
return [];
},
__hmrId: "CubeCamera"
});
const MeshInjectionKey = Symbol("Mesh");
const Mesh = vue.defineComponent({
name: "Mesh",
extends: Object3D,
props: {
castShadow: Boolean,
receiveShadow: Boolean
},
setup() {
return {};
},
provide() {
return {
[MeshInjectionKey]: this
};
},
mounted() {
if (!this.mesh && !this.loading)
this.initMesh();
},
methods: {
initMesh() {
const mesh = new three.Mesh(this.geometry, this.material);
bindProp(this, "castShadow", mesh);
bindProp(this, "receiveShadow", mesh);
this.mesh = mesh;
this.initObject3D(mesh);
},
createGeometry() {
},
addGeometryWatchers(props) {
Object.keys(props).forEach((prop) => {
vue.watch(() => this[prop], () => {
this.refreshGeometry();
});
});
},
setGeometry(geometry) {
this.geometry = geometry;
if (this.mesh)
this.mesh.geometry = geometry;
},
setMaterial(material) {
if (Array.isArray(material) || !this.material) {
this.material = material;
if (this.mesh)
this.mesh.material = material;
} else {
let prev = this.material;
if (Array.isArray(prev)) {
prev.push(material);
} else {
prev = [prev, material];
}
this.material = prev;
if (this.mesh)
this.mesh.material = prev;
}
},
refreshGeometry() {
const oldGeo = this.geometry;
this.createGeometry();
if (this.mesh && this.geometry)
this.mesh.geometry = this.geometry;
oldGeo == null ? void 0 : oldGeo.dispose();
}
},
unmounted() {
if (this.geometry)
this.geometry.dispose();
if (this.material) {
if (Array.isArray(this.material)) {
for (const m of this.material)
m.dispose();
} else {
this.material.dispose();
}
}
},
__hmrId: "Mesh"
});
function meshComponent(name, props, createGeometry) {
return vue.defineComponent({
name,
extends: Mesh,
props,
created() {
this.createGeometry();
this.addGeometryWatchers(props);
},
methods: {
createGeometry() {
this.geometry = createGeometry(this);
}
}
});
}
const Geometry = vue.defineComponent({
emits: ["created"],
props: {
rotateX: Number,
rotateY: Number,
rotateZ: Number,
attributes: { type: Array, default: () => [] }
},
inject: {
mesh: MeshInjectionKey
},
setup() {
return {};
},
created() {
if (!this.mesh) {
console.error("Missing parent Mesh");
return;
}
this.createGeometry();
this.rotateGeometry();
if (this.geometry)
this.mesh.setGeometry(this.geometry);
Object.keys(this.$props).forEach((prop) => {
vue.watch(() => this[prop], this.refreshGeometry);
});
},
unmounted() {
var _a;
(_a = this.geometry) == null ? void 0 : _a.dispose();
},
methods: {
createGeometry() {
const bufferAttributes = {};
const geometry = new three.BufferGeometry();
this.attributes.forEach((attribute) => {
if (attribute.name && attribute.itemSize && attribute.array) {
const bufferAttribute = bufferAttributes[attribute.name] = new three.BufferAttribute(attribute.array, attribute.itemSize, attribute.normalized);
geometry.setAttribute(attribute.name, bufferAttribute);
}
});
geometry.computeBoundingBox();
geometry.userData.component = this;
this.geometry = geometry;
this.$emit("created", geometry);
},
rotateGeometry() {
if (!this.geometry)
return;
if (this.rotateX)
this.geometry.rotateX(this.rotateX);
if (this.rotateY)
this.geometry.rotateY(this.rotateY);
if (this.rotateZ)
this.geometry.rotateZ(this.rotateZ);
},
refreshGeometry() {
const oldGeo = this.geometry;
this.createGeometry();
this.rotateGeometry();
if (this.geometry && this.mesh)
this.mesh.setGeometry(this.geometry);
oldGeo == null ? void 0 : oldGeo.dispose();
}
},
render() {
return [];
}
});
function geometryComponent(name, props, createGeometry) {
return vue.defineComponent({
name,
extends: Geometry,
props,
methods: {
createGeometry() {
this.geometry = createGeometry(this);
this.geometry.userData.component = this;
this.$emit("created", this.geometry);
}
}
});
}
const props$n = {
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 }
};
function createGeometry$h(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$n, createGeometry$h);
const props$m = {
radius: { type: Number, default: 1 },
segments: { type: Number, default: 8 },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI * 2 }
};
function createGeometry$g(comp) {
return new three.CircleGeometry(comp.radius, comp.segments, comp.thetaStart, comp.thetaLength);
}
var CircleGeometry = geometryComponent("CircleGeometry", props$m, createGeometry$g);
const props$l = {
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 }
};
function createGeometry$f(comp) {
return new three.ConeGeometry(comp.radius, comp.height, comp.radialSegments, comp.heightSegments, comp.openEnded, comp.thetaStart, comp.thetaLength);
}
var ConeGeometry = geometryComponent("ConeGeometry", props$l, createGeometry$f);
const props$k = {
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 }
};
function createGeometry$e(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$k, createGeometry$e);
const props$j = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 }
};
function createGeometry$d(comp) {
return new three.DodecahedronGeometry(comp.radius, comp.detail);
}
var DodecahedronGeometry = geometryComponent("DodecahedronGeometry", props$j, createGeometry$d);
const props$i = {
shapes: { type: [Object, Array] },
options: { type: Object }
};
function createGeometry$c(comp) {
return new three.ExtrudeGeometry(comp.shapes, comp.options);
}
var ExtrudeGeometry = geometryComponent("ExtrudeGeometry", props$i, createGeometry$c);
const props$h = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 }
};
function createGeometry$b(comp) {
return new three.IcosahedronGeometry(comp.radius, comp.detail);
}
var IcosahedronGeometry = geometryComponent("IcosahedronGeometry", props$h, createGeometry$b);
const props$g = {
points: Array,
segments: { type: Number, default: 12 },
phiStart: { type: Number, default: 0 },
phiLength: { type: Number, default: Math.PI * 2 }
};
function createGeometry$a(comp) {
return new three.LatheGeometry(comp.points, comp.segments, comp.phiStart, comp.phiLength);
}
var LatheGeometry = geometryComponent("LatheGeometry", props$g, createGeometry$a);
const props$f = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 }
};
function createGeometry$9(comp) {
return new three.OctahedronGeometry(comp.radius, comp.detail);
}
var OctahedronGeometry = geometryComponent("OctahedronGeometry", props$f, createGeometry$9);
const props$e = {
width: { type: Number, default: 1 },
height: { type: Number, default: 1 },
widthSegments: { type: Number, default: 1 },
heightSegments: { type: Number, default: 1 }
};
function createGeometry$8(comp) {
return new three.PlaneGeometry(comp.width, comp.height, comp.widthSegments, comp.heightSegments);
}
var PlaneGeometry = geometryComponent("PlaneGeometry", props$e, createGeometry$8);
const props$d = {
vertices: Array,
indices: Array,
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 }
};
function createGeometry$7(comp) {
return new three.PolyhedronGeometry(comp.vertices, comp.indices, comp.radius, comp.detail);
}
var PolyhedronGeometry = geometryComponent("PolyhedronGeometry", props$d, createGeometry$7);
const props$c = {
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 }
};
function createGeometry$6(comp) {
return new three.RingGeometry(comp.innerRadius, comp.outerRadius, comp.thetaSegments, comp.phiSegments, comp.thetaStart, comp.thetaLength);
}
var RingGeometry = geometryComponent("RingGeometry", props$c, createGeometry$6);
const props$b = {
radius: { type: Number, default: 1 },
widthSegments: { type: Number, default: 12 },
heightSegments: { type: Number, default: 12 },
phiStart: { type: Number, default: 0 },
phiLength: { type: Number, default: Math.PI * 2 },
thetaStart: { type: Number, default: 0 },
thetaLength: { type: Number, default: Math.PI }
};
function createGeometry$5(comp) {
return new three.SphereGeometry(comp.radius, comp.widthSegments, comp.heightSegments, comp.phiStart, comp.phiLength, comp.thetaStart, comp.thetaLength);
}
var SphereGeometry = geometryComponent("SphereGeometry", props$b, createGeometry$5);
const props$a = {
shapes: { type: [Object, Array] },
curveSegments: { type: Number }
};
function createGeometry$4(comp) {
return new three.ShapeGeometry(comp.shapes, comp.curveSegments);
}
var ShapeGeometry = geometryComponent("ShapeGeometry", props$a, createGeometry$4);
const props$9 = {
radius: { type: Number, default: 1 },
detail: { type: Number, default: 0 }
};
function createGeometry$3(comp) {
return new three.TetrahedronGeometry(comp.radius, comp.detail);
}
var TetrahedronGeometry = geometryComponent("TetrahedronGeometry", props$9, createGeometry$3);
const props$8 = {
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 }
};
function createGeometry$2(comp) {
return new three.TorusGeometry(comp.radius, comp.tube, comp.radialSegments, comp.tubularSegments, comp.arc);
}
var TorusGeometry = geometryComponent("TorusGeometry", props$8, createGeometry$2);
const props$7 = {
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 }
};
function createGeometry$1(comp) {
return new three.TorusKnotGeometry(comp.radius, comp.tube, comp.tubularSegments, comp.radialSegments, comp.p, comp.q);
}
var TorusKnotGeometry = geometryComponent("TorusKnotGeometry", props$7, createGeometry$1);
const props$6 = {
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 }
};
function createGeometry(comp) {
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({
extends: Geometry,
props: props$6,
methods: {
createGeometry() {
this.geometry = createGeometry(this);
},
updatePoints(points) {
updateTubeGeometryPoints(this.geometry, points);
}
}
});
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 pAttribute = tube.getAttribute("position");
const nAttribute = tube.getAttribute("normal");
const normal = new three.Vector3();
const P = new three.Vector3();
for (let i = 0; i < tubularSegments; i++) {
updateSegment(i);
}
updateSegment(tubularSegments);
tube.attributes.position.needsUpdate = true;
tube.attributes.normal.needsUpdate = true;
function updateSegment(i) {
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;
nAttribute.setXYZ(index, normal.x, normal.y, normal.z);
pAttribute.setXYZ(index, P.x + radius * normal.x, P.y + radius * normal.y, P.z + radius * normal.z);
}
}
}
var Light = vue.defineComponent({
extends: Object3D,
name: "Light",
props: {
color: { type: String, default: "#ffffff" },
intensity: { type: Number, default: 1 },
castShadow: { type: Boolean, default: false },
shadowMapSize: { type: Object, default: () => ({ x: 512, y: 512 }) },
shadowCamera: { type: Object, default: () => ({}) }
},
setup() {
return {};
},
unmounted() {
if (this.light instanceof three.SpotLight || this.light instanceof three.DirectionalLight) {
this.removeFromParent(this.light.target);
}
},
methods: {
initLight(light) {
this.light = light;
if (light.shadow) {
light.castShadow = this.castShadow;
setFromProp(light.shadow.mapSize, this.shadowMapSize);
setFromProp(light.shadow.camera, this.shadowCamera);
}
["color", "intensity", "castShadow"].forEach((p) => {
vue.watch(() => this[p], (value) => {
if (p === "color") {
light.color.set(value);
} else {
light[p] = value;
}
});
});
this.initObject3D(light);
if (light instanceof three.SpotLight || light instanceof three.DirectionalLight) {
bindProp(this, "target", light.target, "position");
this.addToParent(light.target);
}
}
},
__hmrId: "Light"
});
var AmbientLight = vue.defineComponent({
extends: Light,
created() {
this.initLight(new three.AmbientLight(this.color, this.intensity));
},
__hmrId: "AmbientLight"
});
var DirectionalLight = vue.defineComponent({
extends: Light,
props: {
target: { type: Object, default: () => ({ x: 0, y: 0, z: 0 }) }
},
created() {
this.initLight(new three.DirectionalLight(this.color, this.intensity));
},
__hmrId: "DirectionalLight"
});
var HemisphereLight = vue.defineComponent({
extends: Light,
props: {
groundColor: { type: String, default: "#444444" }
},
created() {
const light = new three.HemisphereLight(this.color, this.groundColor, this.intensity);
vue.watch(() => this.groundColor, (value) => {
light.groundColor.set(value);
});
this.initLight(light);
},
__hmrId: "HemisphereLight"
});
var PointLight = vue.defineComponent({
extends: Light,
props: {
distance: { type: Number, default: 0 },
decay: { type: Number, default: 1 }
},
created() {
this.initLight(new three.PointLight(this.color, this.intensity, this.distance, this.decay));
},
__hmrId: "PointLight"
});
var RectAreaLight = vue.defineComponent({
extends: Light,
props: {
width: { type: Number, default: 10 },
height: { type: Number, default: 10 },
helper: Boolean
},
created() {
RectAreaLightUniformsLib_js.RectAreaLightUniformsLib.init();
const light = new three.RectAreaLight(this.color, this.intensity, this.width, this.height);
const watchProps = ["width", "height"];
watchProps.forEach((p) => {
vue.watch(() => this[p], (value) => {
light[p] = value;
});
});
if (this.helper) {
const lightHelper = new RectAreaLightHelper_js.RectAreaLightHelper(light);
light.add(lightHelper);
}
this.initLight(light);
},
__hmrId: "RectAreaLight"
});
var SpotLight = vue.defineComponent({
extends: Light,
props: {
angle: { type: Number, default: Math.PI / 3 },
decay: { type: Number, default: 1 },
distance: { type: Number, default: 0 },
penumbra: { type: Number, default: 0 },
target: Object
},
created() {
const light = new three.SpotLight(this.color, this.intensity, this.distance, this.angle, this.penumbra, this.decay);
const watchProps = ["angle", "decay", "distance", "penumbra"];
watchProps.forEach((p) => {
vue.watch(() => this[p], (value) => {
light[p] = value;
});
});
this.initLight(light);
},
__hmrId: "SpotLight"
});
const MaterialInjectionKey = Symbol("Material");
const BaseMaterial = vue.defineComponent({
emits: ["created"],
props: {
color: { type: String, default: "#ffffff" },
props: { type: Object, default: () => ({}) }
},
inject: {
mesh: MeshInjectionKey
},
setup() {
return {};
},
provide() {
return {
[MaterialInjectionKey]: this
};
},
created() {
if (!this.mesh) {
console.error("Missing parent Mesh");
return;
}
if (this.createMaterial) {
const material = this.material = this.createMaterial();
vue.watch(() => this.color, (value) => {
material.color.set(value);
});
bindObjectProp(this, "props", material, false, this.setProp);
this.$emit("created", material);
this.mesh.setMaterial(material);
}
},
unmounted() {
var _a;
(_a = this.material) == null ? void 0 : _a.dispose();
},
methods: {
getMaterialParams() {
return { ...propsValues(this.$props, ["props"]), ...this.props };
},
setProp(material, key, value, needsUpdate = false) {
const dstVal = material[key];
if (dstVal instanceof three.Color)
dstVal.set(value);
else
material[key] = value;
material.needsUpdate = needsUpdate;
},
setTexture(texture, key = "map") {
this.setProp(this.material, key, texture, true);
}
},
render() {
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: "Material"
});
function materialComponent(name, props, createMaterial) {
return vue.defineComponent({
name,
extends: BaseMaterial,
props,
methods: {
createMaterial() {
return createMaterial(this.getMaterialParams());
}
}
});
}
const BasicMaterial = materialComponent("BasicMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshBasicMaterial(opts));
const LambertMaterial = materialComponent("LambertMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshLambertMaterial(opts));
const PhongMaterial = materialComponent("PhongMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshPhongMaterial(opts));
const PhysicalMaterial = materialComponent("PhysicalMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshPhysicalMaterial(opts));
const PointsMaterial = materialComponent("PointsMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.PointsMaterial(opts));
const ShadowMaterial = materialComponent("ShadowMaterial", { color: { type: String, default: "#000000" }, props: { type: Object, default: () => ({}) } }, (opts) => new three.ShadowMaterial(opts));
const StandardMaterial = materialComponent("StandardMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshStandardMaterial(opts));
const ToonMaterial = materialComponent("ToonMaterial", { props: { type: Object, default: () => ({}) } }, (opts) => new three.MeshToonMaterial(opts));
var MatcapMaterial = materialComponent(
"MatcapMaterial",
{
src: String,
name: { type: String, default: "0404E8_0404B5_0404CB_3333FC" }
},
(opts) => {
const src = opts.src ? opts.src : getMatcapUrl(opts.name);
const params = propsValues(opts, ["src", "name"]);
params.matcap = new three.TextureLoader().load(src);
return new three.MeshMatcapMaterial(params);
}
);
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);
}
`;
var ShaderMaterial = materialComponent(
"ShaderMaterial",
{
props: { type: Object, default: () => ({
uniforms: {},
vertexShader: defaultVertexShader,
fragmentShader: defaultFragmentShader
}) }
},
(opts) => new three.ShaderMaterial(propsValues(opts, ["color"]))
);
function replaceAll(string, find, replace) {
return string.split(find).join(replace);
}
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() {"));
const SubsurfaceScatteringShader = {
uniforms: three.UniformsUtils.merge([
three.ShaderLib.phong.uniforms,
{
thicknessColor: { value: new three.Color(16777215) },
thicknessDistortion: { value: 0.1 },
thicknessAmbient: { value: 0 },
thicknessAttenuation: { value: 0.1 },
thicknessPower: { value: 2 },
thicknessScale: { value: 10 }
}
]),
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(
"#include <lights_fragment_begin>",
replaceAll(
three.ShaderChunk.lights_fragment_begin,
"RE_Direct( directLight, geometry, material, reflectedLight );",
`
RE_Direct( directLight, geometry, material, reflectedLight );
#if defined( SUBSURFACE ) && defined( USE_UV )
RE_Direct_Scattering(directLight, vUv, geometry, reflectedLight);
#endif
`
)
)
};
var SubSurfaceMaterial = vue.defineComponent({
extends: BaseMaterial,
props: {
uniforms: { type: Object, default: () => ({
diffuse: "#ffffff",
thicknessColor: "#ffffff",
thicknessDistortion: 0.4,
thicknessAmbient: 0.01,
thicknessAttenuation: 0.7,
thicknessPower: 2,
thicknessScale: 4
}) }
},
methods: {
createMaterial() {
const params = SubsurfaceScatteringShader;
const uniforms = three.UniformsUtils.clone(params.uniforms);
bindObjectProp(this, "uniforms", uniforms, true, (dst, key, value) => {
const dstVal = dst[key].value;
if (dstVal instanceof three.Color)
dstVal.set(value);
else
dst[key].value = value;
});
const material = new three.ShaderMaterial({
...params,
lights: true,
...this.props,
uniforms
});
return material;
}
}
});
var Texture = vue.defineComponent({
inject: {
material: MaterialInjectionKey
},
props: {
name: { type: String, default: "map" },
uniform: String,
src: String,
onLoad: Function,
onProgress: Function,
onError: Function,
props: { type: Object, default: () => ({}) }
},
setup() {
return {};
},
created() {
this.refreshTexture();
vue.watch(() => this.src, this.refreshTexture);
},
unmounted() {
var _a, _b;
(_a = this.material) == null ? void 0 : _a.setTexture(null, this.name);
(_b = this.texture) == null ? void 0 : _b.dispose();
},
methods: {
createTexture() {
if (!this.src)
return void 0;
return new three.TextureLoader().load(this.src, this.onLoaded, this.onProgress, this.onError);
},
initTexture() {
if (!this.texture)
return;
bindObjectProp(this, "props", this.texture);
if (!this.material)
return;
this.material.setTexture(this.texture, this.name);
if (this.material.material instanceof three.ShaderMaterial && this.uniform) {
this.material.material.uniforms[this.uniform] = { value: this.texture };
}
},
refreshTexture() {
var _a;
(_a = this.texture) == null ? void 0 : _a.dispose();
this.texture = this.createTexture();
this.initTexture();
},
onLoaded(t) {
var _a;
(_a = this.onLoad) == null ? void 0 : _a.call(this, t);
}
},
render() {
return [];
}
});
var CubeTexture = vue.defineComponent({
extends: Texture,
props: {
name: { type: String, default: "envMap" },
path: { type: String, required: true },
urls: {
type: Array,
default: () => ["px.jpg", "nx.jpg", "py.jpg", "ny.jpg", "pz.jpg", "nz.jpg"]
},
props: { type: Object, default: () => ({ mapping: three.CubeReflectionMapping }) }
},
created() {
vue.watch(() => this.path, this.refreshTexture);
vue.watch(() => this.urls, this.refreshTexture);
},
methods: {
createTexture() {
return new three.CubeTextureLoader().setPath(this.path).load(this.urls, this.onLoaded, this.onProgress, this.onError);
}
}
});
var VideoTexture = vue.defineComponent({
extends: Texture,
props: {
videoId: {
type: String,
required: true
}
},
created() {
vue.watch(() => this.videoId, this.refreshTexture);
},
methods: {
createTexture() {
const video = document.getElementById(this.videoId);
return new three.VideoTexture(video);
}
}
});
var Box = meshComponent("Box", props$n, createGeometry$h);
var Circle = meshComponent("Circle", props$m, createGeometry$g);
var Cone = meshComponent("Cone", props$l, createGeometry$f);
var Cylinder = meshComponent("Cylinder", props$k, createGeometry$e);
var Dodecahedron = meshComponent("Dodecahedron", props$j, createGeometry$d);
var Icosahedron = meshComponent("Icosahedron", props$h, createGeometry$b);
var Lathe = meshComponent("Lathe", props$g, createGeometry$a);
var Octahedron = meshComponent("Octahedron", props$f, createGeometry$9);
var Plane = meshComponent("Plane", props$e, createGeometry$8);
var Polyhedron = meshComponent("Polyhedron", props$d, createGeometry$7);
var Ring = meshComponent("Ring", props$c, createGeometry$6);
var Sphere = meshComponent("Sphere", props$b, createGeometry$5);
var Tetrahedron = meshComponent("Tetrahedron", props$9, createGeometry$3);
const props$5 = {
text: { type: String, required: true, default: "Text" },
fontSrc: { type: String, required: true },
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 }
};
var Text = vue.defineComponent({
extends: Mesh,
props: props$5,
setup() {
return {};
},
created() {
if (!this.fontSrc) {
console.error('Missing required prop: "font-src"');
return;
}
const watchProps = [
"text",
"size",
"height",
"curveSegments",
"bevelEnabled",
"bevelThickness",
"bevelSize",
"bevelOffset",
"bevelSegments",
"align"
];
watchProps.forEach((p) => {
vue.watch(() => this[p], () => {
if (this.font)
this.refreshGeometry();
});
});
const loader = new FontLoader_js.FontLoader();
this.loading = true;
loader.load(this.fontSrc, (font) => {
this.loading = false;
this.font = font;
this.createGeometry();
this.initMesh();
});
},
methods: {
createGeometry() {
this.geometry = new TextGeometry_js.TextGeometry(this.text, {
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();
}
}
}
});
var Torus = meshComponent("Torus", props$8, createGeometry$2);
var TorusKnot = meshComponent("TorusKnot", props$7, createGeometry$1);
var Tube = vue.defineComponent({
extends: Mesh,
props: props$6,
created() {
this.createGeometry();
this.addGeometryWatchers(props$6);
},
methods: {
createGeometry() {
this.geometry = createGeometry(this);
},
updatePoints(points) {
updateTubeGeometryPoints(this.geometry, points);
}
},
__hmrId: "Tube"
});
var Image = vue.defineComponent({
emits: ["loaded"],
extends: Mesh,
props: {
src: { type: String, required: true },
width: Number,
height: Number,
widthSegments: { type: Number, default: 1 },
heightSegments: { type: Number, default: 1 },
keepSize: Boolean
},
setup() {
return {};
},
created() {
if (!this.renderer)
return;
this.geometry = new three.PlaneGeometry(1, 1, this.widthSegments, this.heightSegments);
this.material = new three.MeshBasicMaterial({ side: three.DoubleSide, map: this.loadTexture() });
vue.watch(() => this.src, this.refreshTexture);
["width", "height"].forEach((p) => {
vue.watch(() => this[p], this.resize);
});
this.resize();
if (this.keepSize)
this.renderer.onResize(this.resize);
},
unmounted() {
var _a;
(_a = this.renderer) == null ? void 0 : _a.offResize(this.resize);
},
methods: {
loadTexture() {
return new three.TextureLoader().load(this.src, this.onLoaded);
},
refreshTexture() {
var _a;
(_a = this.texture) == null ? void 0 : _a.dispose();
if (this.material) {
this.material.map = this.loadTexture();
this.material.needsUpdate = true;
}
},
onLoaded(texture) {
this.texture = texture;
this.resize();
this.$emit("loaded", texture);
},
resize() {
if (!this.renderer || !this.texture)
return;
const screen = this.renderer.size;
const iW = this.texture.image.width;
const iH = this.texture.image.height;
const iRatio = iW / iH;
let w = 1, h = 1;
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;
} else {
if (iRatio > 1)
w = h * iRatio;
else
h = w / iRatio;
}
if (this.mesh) {
this.mesh.scale.x = w;
this.mesh.scale.y = h;
}
}
},
__hmrId: "Image"
});
var InstancedMesh = vue.defineComponent({
extends: Mesh,
props: {
count: { type: Number, required: true }
},
methods: {
initMesh() {
if (!this.renderer)
return;
if (!this.geometry || !this.material) {
console.error("Missing geometry and/or material");
return false;
}
this.mesh = new three.InstancedMesh(this.geometry, this.material, this.count);
this.mesh.userData.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.renderer.three.addIntersectObject(this.mesh);
}
this.initObject3D(this.mesh);
}
},
__hmrId: "InstancedMesh"
});
var Sprite = vue.defineComponent({
extends: Object3D,
emits: ["loaded"],
props: {
src: { type: String, required: true }
},
setup() {
return {};
},
created() {
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.initObject3D(this.sprite);
},
unmounted() {
var _a, _b;
(_a = this.texture) == null ? void 0 : _a.dispose();
(_b = this.material) == null ? void 0 : _b.dispose();
},
methods: {
onLoaded() {
this.updateUV();
this.$emit("loaded");
},
updateUV() {
if (!this.texture || !this.sprite)
return;
const iWidth = this.texture.image.width;
const iHeight = this.texture.image.height;
const iRatio = iWidth / iHeight;
let x = 0.5, y = 0.5;
if (iRatio > 1) {
x = 0.5 * iRatio;
} else {
y = 0.5 / iRatio;
}
const positions = this.sprite.geometry.attributes.position.array;
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.sprite.geometry.attributes.position.needsUpdate = true;
}
},
__hmrId: "Sprite"
});
var Points = vue.defineComponent({
extends: Object3D,
setup() {
return {};
},
provide() {
return {
[MeshInjectionKey]: this
};
},
mounted() {
this.mesh = this.points = new three.Points(this.geometry, this.material);
this.initObject3D(this.mesh);
},
methods: {
setGeometry(geometry) {
this.geometry = geometry;
if (this.mesh)
this.mesh.geometry = geometry;
},
setMaterial(material) {
this.material = material;
if (this.mesh)
this.mesh.material = material;
}
}
});
var Model = vue.defineComponent({
extends: Object3D,
emits: ["before-load", "load", "progress", "error"],
props: {
src: { type: String, required: true }
},
data() {
return {
progress: 0
};
},
methods: {
onLoad(model) {
this.$emit("load", 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,
created() {
const loader = new GLTFLoader_js.GLTFLoader();
this.$emit("before-load", loader);
loader.load(this.src, (gltf) => {
this.onLoad(gltf);
this.initObject3D(gltf.scene);
}, this.onProgress, this.onError);
}
});
var FBX = vue.defineComponent({
extends: Model,
created() {
const loader = new FBXLoader_js.FBXLoader();
this.$emit("before-load", loader);
loader.load(this.src, (fbx) => {
this.onLoad(fbx);
this.initObject3D(fbx);
}, this.onProgress, this.onError);
}
});
const ComposerInjectionKey = Symbol("Composer");
var EffectComposer = vue.defineComponent({
setup() {
const renderer = vue.inject(RendererInjectionKey);
return { renderer };
},
provide() {
return {
[ComposerInjectionKey]: this
};
},
created() {
if (!this.renderer) {
console.error("Renderer not found");
return;
}
const renderer = this.renderer;
const composer = new EffectComposer_js.EffectComposer(this.renderer.renderer);
this.composer = composer;
this.renderer.composer = composer;
renderer.addListener("init", () => {
renderer.renderer.autoClear = false;
this.resize();
renderer.addListener("resize", this.resize);
});
},
unmounted() {
var _a;
(_a = this.renderer) == null ? void 0 : _a.removeListener("resize", this.resize);
},
methods: {
addPass(pass) {
var _a;
(_a = this.composer) == null ? void 0 : _a.addPass(pass);
},
removePass(pass) {
var _a;
(_a = this.composer) == null ? void 0 : _a.removePass(pass);
},
resize() {
if (this.composer && this.renderer) {
this.composer.setSize(this.renderer.size.width, this.renderer.size.height);
}
}
},
render() {
return this.$slots.default ? this.$slots.default() : [];
},
__hmrId: "EffectComposer"
});
var EffectPass = vue.defineComponent({
inject: {
renderer: RendererInjectionKey,
composer: ComposerInjectionKey
},
emits: ["ready"],
setup() {
return {};
},
created() {
if (!this.composer) {
console.error("Missing parent EffectComposer");
}
if (!this.renderer) {
console.error("Missing parent Renderer");
}
},
unmounted() {
var _a, _b, _c;
if (this.pass) {
(_a = this.composer) == null ? void 0 : _a.removePass(this.pass);
(_c = (_b = this.pass).dispose) == null ? void 0 : _c.call(_b);
}
},
methods: {
initEffectPass(pass) {
var _a;
this.pass = pass;
(_a = this.composer) == null ? void 0 : _a.addPass(pass);
this.$emit("ready", pass);
}
},
render() {
return [];
},
__hmrId: "EffectPass"
});
var RenderPass = vue.defineComponent({
extends: EffectPass,
created() {
if (!this.renderer)
return;
if (!this.renderer.scene) {
console.error("Missing Scene");
return;
}
if (!this.renderer.camera) {
console.error("Missing Camera");
return;
}
const pass = new RenderPass_js.RenderPass(this.renderer.scene, this.renderer.camera);
this.initEffectPass(pass);
},
__hmrId: "RenderPass"
});
const props$4 = {
focus: { type: Number, default: 1 },
aperture: { type: Number, default: 0.025 },
maxblur: { type: Number, default: 0.01 }
};
var BokehPass = vue.defineComponent({
extends: EffectPass,
props: props$4,
created() {
if (!this.renderer)
return;
if (!this.renderer.scene) {
console.error("Missing Scene");
return;
}
if (!this.renderer.camera) {
console.error("Missing Camera");
return;
}
const params = {
focus: this.focus,
aperture: this.aperture,
maxblur: this.maxblur,
width: this.renderer.size.width,
height: this.renderer.size.height
};
const pass = new BokehPass_js.BokehPass(this.renderer.scene, this.renderer.camera, params);
Object.keys(props$4).forEach((p) => {
vue.watch(() => this[p], (value) => {
pass.uniforms[p].value = value;
});
});
this.initEffectPass(pass);
},
__hmrId: "BokehPass"
});
const props$3 = {
noiseIntensity: { type: Number, default: 0.5 },
scanlinesIntensity: { type: Number, default: 0.05 },
scanlinesCount: { type: Number, default: 4096 },
grayscale: { type: Number, default: 0 }
};
var FilmPass = vue.defineComponent({
extends: EffectPass,
props: props$3,
created() {
const pass = new FilmPass_js.FilmPass(this.noiseIntensity, this.scanlinesIntensity, this.scanlinesCount, this.grayscale);
Object.keys(props$3).forEach((p) => {
vue.watch(() => this[p], (value) => {
pass.uniforms[p].value = value;
});
});
this.initEffectPass(pass);
},
__hmrId: "FilmPass"
});
var FXAAPass = vue.defineComponent({
extends: EffectPass,
created() {
var _a;
const pass = new ShaderPass_js.ShaderPass(FXAAShader_js.FXAAShader);
(_a = this.renderer) == null ? void 0 : _a.addListener("resize", this.resize);
this.initEffectPass(pass);
},
unmounted() {
var _a;
(_a = this.renderer) == null ? void 0 : _a.removeListener("resize", this.resize);
},
methods: {
resize({ size }) {
if (this.pass) {
const { resolution } = this.pass.material.uniforms;
resolution.value.x = 1 / size.width;
resolution.value.y = 1 / size.height;
}
}
},
__hmrId: "FXAAPass"
});
const props$2 = {
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 }
};
var HalftonePass = vue.defineComponent({
extends: EffectPass,
props: props$2,
created() {
if (!this.renderer)
return;
const pass = new HalftonePass_js.HalftonePass(this.renderer.size.width, this.renderer.size.height, {});
Object.keys(props$2).forEach((p) => {
pass.uniforms[p].value = this[p];
vue.watch(() => this[p], (value) => {
pass.uniforms[p].value = value;
});
});
this.initEffectPass(pass);
},
__hmrId: "HalftonePass"
});
var SMAAPass = vue.defineComponent({
extends: EffectPass,
created() {
if (!this.renderer)
return;
const pass = new SMAAPass_js.SMAAPass(this.renderer.size.width, this.renderer.size.height);
this.initEffectPass(pass);
},
__hmrId: "SMAAPass"
});
var SSAOPass = vue.defineComponent({
extends: EffectPass,
props: {
options: {
type: Object,
default: () => ({})
}
},
created() {
if (!this.renderer)
return;
if (!this.renderer.scene) {
console.error("Missing Scene");
return;
}
if (!this.renderer.camera) {
console.error("Missing Camera");
return;
}
const pass = new SSAOPass_js.SSAOPass(
this.renderer.scene,
this.renderer.camera,
this.renderer.size.width,
this.renderer.size.height
);
Object.keys(this.options).forEach((key) => {
pass[key] = this.options[key];
});
this.initEffectPass(pass);
},
__hmrId: "SSAOPass"
});
var DefaultShader = {
uniforms: {},
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);
}
`
};
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,
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;
}
`
};
const props$1 = {
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 }) }
};
var TiltShiftPass = vue.defineComponent({
extends: EffectPass,
props: props$1,
setup() {
return { uniforms1: {}, uniforms2: {} };
},
created() {
if (!this.composer)
return;
this.pass1 = new ShaderPass_js.ShaderPass(TiltShift);
this.pass2 = new ShaderPass_js.ShaderPass(TiltShift);
const uniforms1 = this.uniforms1 = this.pass1.uniforms;
const uniforms2 = this.uniforms2 = this.pass2.uniforms;
uniforms2.blurRadius = uniforms1.blurRadius;
uniforms2.gradientRadius = uniforms1.gradientRadius;
uniforms2.start = uniforms1.start;
uniforms2.end = uniforms1.end;
uniforms2.texSize = uniforms1.texSize;
bindProp(this, "blurRadius", uniforms1.blurRadius, "value");
bindProp(this, "gradientRadius", uniforms1.gradientRadius, "value");
this.updateFocusLine();
["start", "end"].forEach((p) => {
vue.watch(() => this[p], this.updateFocusLine, { deep: true });
});
this.pass1.setSize = (width, height) => {
uniforms1.texSize.value.set(width, height);
};
this.initEffectPass(this.pass1);
this.composer.addPass(this.pass2);
},
unmounted() {
if (this.composer && this.pass2)
this.composer.removePass(this.pass2);
},
methods: {
updateFocusLine() {
this.uniforms1.start.value.copy(this.start);
this.uniforms1.end.value.copy(this.end);
const dv = new three.Vector2().copy(this.end).sub(this.start).normalize();
this.uniforms1.delta.value.copy(dv);
this.uniforms2.delta.value.set(-dv.y, dv.x);
}
},
__hmrId: "TiltShiftPass"
});
const props = {
strength: { type: Number, default: 1.5 },
radius: { type: Number, default: 0 },
threshold: { type: Number, default: 0 }
};
var UnrealBloomPass = vue.defineComponent({
extends: EffectPass,
props,
created() {
if (!this.renderer)
return;
const size = new three.Vector2(this.renderer.size.width, this.renderer.size.height);
const pass = new UnrealBloomPass_js.UnrealBloomPass(size, this.strength, this.radius, this.threshold);
Object.keys(props).forEach((p) => {
vue.watch(() => this[p], (value) => {
pass.uniforms[p].value = value;
});
});
this.initEffectPass(pass);
},
__hmrId: "UnrealBloomPass"
});
var ZoomBlur = {
uniforms: {
tDiffuse: { value: null },
center: { value: new three.Vector2(0.5, 0.5) },
strength: { value: 0 }
},
vertexShader: DefaultShader.vertexShader,
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;
}
`
};
var ZoomBlurPass = vue.defineComponent({
extends: EffectPass,
props: {
center: { type: Object, default: () => ({ x: 0.5, y: 0.5 }) },
strength: { type: Number, default: 0.5 }
},
created() {
const pass = new ShaderPass_js.ShaderPass(ZoomBlur);
bindProp(this, "center", pass.uniforms.center, "value");
bindProp(this, "strength", pass.uniforms.strength, "value");
this.initEffectPass(pass);
},
__hmrId: "ZoomBlurPass"
});
var TROIS = /*#__PURE__*/Object.freeze({
__proto__: null,
Renderer: Renderer,
RendererInjectionKey: RendererInjectionKey,
OrthographicCamera: OrthographicCamera,
PerspectiveCamera: PerspectiveCamera,
Camera: PerspectiveCamera,
Group: Group,
Scene: Scene,
SceneInjectionKey: SceneInjectionKey,
Object3D: Object3D,
Raycaster: Raycaster,
CubeCamera: CubeCamera,
BufferGeometry: Geometry,
BoxGeometry: BoxGeometry,
CircleGeometry: CircleGeometry,
ConeGeometry: ConeGeometry,
CylinderGeometry: CylinderGeometry,
DodecahedronGeometry: DodecahedronGeometry,
ExtrudeGeometry: ExtrudeGeometry,
IcosahedronGeometry: IcosahedronGeometry,
LatheGeometry: LatheGeometry,
OctahedronGeometry: OctahedronGeometry,
PlaneGeometry: PlaneGeometry,
PolyhedronGeometry: PolyhedronGeometry,
RingGeometry: RingGeometry,
SphereGeometry: SphereGeometry,
ShapeGeometry: ShapeGeometry,
TetrahedronGeometry: TetrahedronGeometry,
TorusGeometry: TorusGeometry,
TorusKnotGeometry: TorusKnotGeometry,
TubeGeometry: TubeGeometry,
AmbientLight: AmbientLight,
DirectionalLight: DirectionalLight,
HemisphereLight: HemisphereLight,
PointLight: PointLight,
RectAreaLight: RectAreaLight,
SpotLight: SpotLight,
Material: BaseMaterial,
BasicMaterial: BasicMaterial,
LambertMaterial: LambertMaterial,
PhongMaterial: PhongMaterial,
PhysicalMaterial: PhysicalMaterial,
PointsMaterial: PointsMaterial,
ShadowMaterial: ShadowMaterial,
StandardMaterial: StandardMaterial,
ToonMaterial: ToonMaterial,
MaterialInjectionKey: MaterialInjectionKey,
MatcapMaterial: MatcapMaterial,
ShaderMaterial: ShaderMaterial,
SubSurfaceMaterial: SubSurfaceMaterial,
Texture: Texture,
CubeTexture: CubeTexture,
VideoTexture: VideoTexture,
Mesh: Mesh,
MeshInjectionKey: MeshInjectionKey,
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,
Points: Points,
GltfModel: GLTF,
FbxModel: FBX,
EffectComposer: EffectComposer,
ComposerInjectionKey: ComposerInjectionKey,
RenderPass: RenderPass,
EffectPass: EffectPass,
BokehPass: BokehPass,
FilmPass: FilmPass,
FXAAPass: FXAAPass,
HalftonePass: HalftonePass,
SMAAPass: SMAAPass,
SSAOPass: SSAOPass,
TiltShiftPass: TiltShiftPass,
UnrealBloomPass: UnrealBloomPass,
ZoomBlurPass: ZoomBlurPass,
applyObjectProps: applyObjectProps,
bindObjectProp: bindObjectProp,
bindObjectProps: bindObjectProps,
setFromProp: setFromProp,
bindProps: bindProps,
bindProp: bindProp,
propsValues: propsValues,
lerp: lerp,
limit: limit,
getMatcapUrl: getMatcapUrl
});
const TroisJSVuePlugin = {
install(app) {
const comps = [
"Camera",
"OrthographicCamera",
"PerspectiveCamera",
"Raycaster",
"Renderer",
"Scene",
"Group",
"CubeCamera",
"AmbientLight",
"DirectionalLight",
"HemisphereLight",
"PointLight",
"RectAreaLight",
"SpotLight",
"BasicMaterial",
"LambertMaterial",
"MatcapMaterial",
"PhongMaterial",
"PhysicalMaterial",
"PointsMaterial",
"ShaderMaterial",
"StandardMaterial",
"SubSurfaceMaterial",
"ToonMaterial",
"Texture",
"CubeTexture",
"BufferGeometry",
"Mesh",
"Box",
"BoxGeometry",
"Circle",
"CircleGeometry",
"Cone",
"ConeGeometry",
"Cylinder",
"CylinderGeometry",
"Dodecahedron",
"DodecahedronGeometry",
"Icosahedron",
"IcosahedronGeometry",
"Lathe",
"LatheGeometry",
"Octahedron",
"OctahedronGeometry",
"Plane",
"PlaneGeometry",
"Polyhedron",
"PolyhedronGeometry",
"Ring",
"RingGeometry",
"Sphere",
"SphereGeometry",
"Tetrahedron",
"TetrahedronGeometry",
"Text",
"Torus",
"TorusGeometry",
"TorusKnot",
"TorusKnotGeometry",
"Tube",
"TubeGeometry",
"Image",
"InstancedMesh",
"Points",
"Sprite",
"FbxModel",
"GltfModel",
"BokehPass",
"EffectComposer",
"FilmPass",
"FXAAPass",
"HalftonePass",
"RenderPass",
"SAOPass",
"SMAAPass",
"SSAOPass",
"TiltShiftPass",
"UnrealBloomPass",
"ZoomBlurPass"
];
comps.forEach((comp) => {
app.component(comp, TROIS[comp]);
});
}
};
function createApp(params) {
return vue.createApp(params).use(TroisJSVuePlugin);
}
function useTextures() {
const obj = {
loader: new three.TextureLoader(),
count: 0,
textures: [],
loadProgress: 0,
loadTextures,
dispose
};
return obj;
function loadTextures(images, cb) {
obj.count = images.length;
obj.textures.splice(0);
obj.loadProgress = 0;
Promise.all(images.map(loadTexture)).then(cb);
}
function loadTexture(img, index) {
return new Promise((resolve) => {
obj.loader.load(
img.src,
(texture) => {
obj.loadProgress += 1 / obj.count;
obj.textures[index] = texture;
resolve(texture);
}
);
});
}
function dispose() {
obj.textures.forEach((t) => t.dispose());
}
}
exports.AmbientLight = AmbientLight;
exports.BasicMaterial = BasicMaterial;
exports.BokehPass = BokehPass;
exports.Box = Box;
exports.BoxGeometry = BoxGeometry;
exports.BufferGeometry = Geometry;
exports.Camera = PerspectiveCamera;
exports.Circle = Circle;
exports.CircleGeometry = CircleGeometry;
exports.ComposerInjectionKey = ComposerInjectionKey;
exports.Cone = Cone;
exports.ConeGeometry = ConeGeometry;
exports.CubeCamera = CubeCamera;
exports.CubeTexture = CubeTexture;
exports.Cylinder = Cylinder;
exports.CylinderGeometry = CylinderGeometry;
exports.DirectionalLight = DirectionalLight;
exports.Dodecahedron = Dodecahedron;
exports.DodecahedronGeometry = DodecahedronGeometry;
exports.EffectComposer = EffectComposer;
exports.EffectPass = EffectPass;
exports.ExtrudeGeometry = ExtrudeGeometry;
exports.FXAAPass = FXAAPass;
exports.FbxModel = FBX;
exports.FilmPass = FilmPass;
exports.GltfModel = GLTF;
exports.Group = Group;
exports.HalftonePass = HalftonePass;
exports.HemisphereLight = HemisphereLight;
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.Material = BaseMaterial;
exports.MaterialInjectionKey = MaterialInjectionKey;
exports.Mesh = Mesh;
exports.MeshInjectionKey = MeshInjectionKey;
exports.Object3D = Object3D;
exports.Octahedron = Octahedron;
exports.OctahedronGeometry = OctahedronGeometry;
exports.OrthographicCamera = OrthographicCamera;
exports.PerspectiveCamera = PerspectiveCamera;
exports.PhongMaterial = PhongMaterial;
exports.PhysicalMaterial = PhysicalMaterial;
exports.Plane = Plane;
exports.PlaneGeometry = PlaneGeometry;
exports.PointLight = PointLight;
exports.Points = Points;
exports.PointsMaterial = PointsMaterial;
exports.Polyhedron = Polyhedron;
exports.PolyhedronGeometry = PolyhedronGeometry;
exports.Raycaster = Raycaster;
exports.RectAreaLight = RectAreaLight;
exports.RenderPass = RenderPass;
exports.Renderer = Renderer;
exports.RendererInjectionKey = RendererInjectionKey;
exports.Ring = Ring;
exports.RingGeometry = RingGeometry;
exports.SMAAPass = SMAAPass;
exports.SSAOPass = SSAOPass;
exports.Scene = Scene;
exports.SceneInjectionKey = SceneInjectionKey;
exports.ShaderMaterial = ShaderMaterial;
exports.ShadowMaterial = ShadowMaterial;
exports.ShapeGeometry = ShapeGeometry;
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.VideoTexture = VideoTexture;
exports.ZoomBlurPass = ZoomBlurPass;
exports.applyObjectProps = applyObjectProps;
exports.bindObjectProp = bindObjectProp;
exports.bindObjectProps = bindObjectProps;
exports.bindProp = bindProp;
exports.bindProps = bindProps;
exports.createApp = createApp;
exports.getMatcapUrl = getMatcapUrl;
exports.lerp = lerp;
exports.limit = limit;
exports.propsValues = propsValues;
exports.setFromProp = setFromProp;
exports.useTextures = useTextures;
//# sourceMappingURL=trois.js.map