Try dragging the title bar or resizing from the bottom-right corner.
'
}
};
class Gh {
currentLocale = "zh-CN";
messages = {
"zh-CN": Hh,
"en-US": Vh
};
listeners = [];
constructor() {
}
/**
* 获取当前语言
*/
getLocale() {
return this.currentLocale;
}
/**
* 切换语言
*/
setLocale(e) {
this.currentLocale !== e && (this.currentLocale = e, this.notifyListeners());
}
/**
* 翻译核心方法
*/
t(e) {
if (!e) return "";
const t = e.split(".");
let i = this.messages[this.currentLocale];
for (const s of t)
if (i && typeof i == "object" && s in i)
i = i[s];
else
return e;
return i;
}
/**
* 订阅变更
*/
subscribe(e) {
return this.listeners.push(e), () => {
this.listeners = this.listeners.filter((t) => t !== e);
};
}
notifyListeners() {
this.listeners.forEach((e) => e(this.currentLocale));
}
}
const dr = new Gh(), xn = (r) => dr.t(r), sl = {
name: "dark",
primary: "#0078d4",
primaryHover: "#0063b1",
// 修改:背景色统一为浅灰,不再跟随深色模式变黑
background: "#f5f5f5",
panelBackground: "rgba(30, 30, 30, 0.9)",
// 注意:如果背景是浅色,主文字颜色通常需要是深色才能看清
// 但这里的 textPrimary 主要是用于 UI 组件内部的。
// 如果 BimEngine wrapper 上的文字直接显示在 background 上,
// 我们可能需要区分 "UI文字" 和 "页面文字"。
// 目前架构中:
// theme.textPrimary 会应用到 wrapper.style.color (BimEngine.ts)
// 以及 Toolbar/Dialog 的文字颜色。
// 如果背景是浅灰,而 wrapper 文字设置为白色 (#ffffff),那就看不清了。
// 这是一个语义冲突:
// 1. Panel (Toolbar/Dialog) 是黑底,需要白字。
// 2. Background (Wrapper) 是白底,需要黑字。
// 既然您要求背景统一浅灰,那么 Wrapper 上的“直接子文本”应该是深色。
// 但 Toolbar/Dialog 仍然是深色模式(黑底),它们需要白字。
// 妥协方案:
// 保持 textPrimary 为白色(为了适配黑���的 Toolbar/Dialog)。
// 但是在 BimEngine 中,如果背景强制改为浅色,Wrapper 的默认文字颜色可能需要单独处理,
// 或者我们可以认为 "Wrapper" 主要是承载 UI 组件的,直接写在 Wrapper 上的文字(标题/描述)
// 应该有自己的样式,而不是直接继承 theme.textPrimary。
// 在之前的 BimEngine.ts 中:
// this.wrapper.style.color = theme.textPrimary;
// 如果背景变浅灰,这里 textPrimary 还是白色的话,标题就看不见了。
// 所以,深色模式下:
// 背景:浅灰
// 组件:深黑
// 组件文字:白
// 页面文字:黑 (问题点)
// 让我们先按您的要求改背景。通常这种情况下,ThemeConfig 可能需要区分
// contentText (页面内容文字) 和 uiText (组件文字)。
// 但为了不破坏现有结构,我将假定 textPrimary 主要服务于 UI 组件。
// 为了让 Wrapper 上的标题可见,我们可能需要在 BimEngine 中移除对 wrapper.style.color 的强制设置,
// 或者在 presets 里把 textPrimary 改回来?不对,改回来 Toolbar 就看不清了。
// 方案:我将仅修改 background。
// 至于 Wrapper 上的标题(BimEngine 标题),由于在最新的 BimEngine.ts 中
// ���们已经移除了 titleEl 和 descEl(在之前的重构中),
// 所以现在 Wrapper 里主要是 Toolbar 和 Dialog,它们有自己的 panelBackground。
// 只要 Toolbar/Dialog 内部正常即可。
textPrimary: "#ffffff",
textSecondary: "#cccccc",
border: "#444444",
icon: "#cccccc",
iconActive: "#ffffff",
componentBackground: "transparent",
componentHover: "#333333",
componentActive: "rgba(255, 255, 255, 0.1)"
}, Wh = {
name: "light",
primary: "#0078d4",
primaryHover: "#106ebe",
// 统一为浅灰
background: "#f5f5f5",
panelBackground: "#ffffff",
textPrimary: "#333333",
textSecondary: "#666666",
border: "#e0e0e0",
icon: "#555555",
iconActive: "#0078d4",
componentBackground: "transparent",
componentHover: "#f0f0f0",
componentActive: "#e0e0e0"
};
class jh {
currentTheme = sl;
listeners = [];
constructor() {
}
/**
* 获取当前主题配置
*/
getTheme() {
return this.currentTheme;
}
/**
* 切换预设主题
* @param themeName 'dark' | 'light'
*/
setTheme(e) {
e === "light" ? this.applyTheme(Wh) : this.applyTheme(sl);
}
/**
* 应用自定义主题配置
* @param theme 配置对象
*/
setCustomTheme(e) {
this.applyTheme(e);
}
/**
* 内部应用主题逻辑
*/
applyTheme(e) {
this.currentTheme = e, this.notifyListeners();
}
/**
* 订阅主题变更
*/
subscribe(e) {
return this.listeners.push(e), e(this.currentTheme), () => {
this.listeners = this.listeners.filter((t) => t !== e);
};
}
notifyListeners() {
this.listeners.forEach((e) => e(this.currentTheme));
}
}
const oi = new jh();
class Nc {
container;
options;
groups = [];
activeBtnIds = /* @__PURE__ */ new Set();
btnRefs = /* @__PURE__ */ new Map();
dropdownElement = null;
hoverTimeout = null;
customColors = /* @__PURE__ */ new Set();
// 记录用户自定义的颜色属性
unsubscribeLocale = null;
unsubscribeTheme = null;
DEFAULT_ICON = '';
constructor(e) {
const t = typeof e.container == "string" ? document.getElementById(e.container) : e.container;
if (!t) throw new Error("Container not found");
this.container = t, this.options = {
showLabel: !0,
visibility: {},
direction: "row",
// 默认横向
position: "static",
// 默认静态定位
align: "vertical",
// 默认图标在上
expand: "down",
// 默认向下展开
...e
}, [
"backgroundColor",
"btnBackgroundColor",
"btnHoverColor",
"btnActiveColor",
"iconColor",
"iconActiveColor",
"textColor",
"textActiveColor"
].forEach((s) => {
e[s] && this.customColors.add(s);
}), this.initContainer(), this.applyStyles();
}
initContainer() {
this.container.innerHTML = "", this.container.classList.add("bim-btn-group-root"), this.options.direction === "column" ? this.container.classList.add("dir-column") : this.container.classList.add("dir-row"), this.options.className && this.container.classList.add(this.options.className), this.updatePosition();
}
updatePosition() {
const e = this.options.position, t = this.container.style;
if (t.top = "", t.bottom = "", t.left = "", t.right = "", t.transform = "", e === "static") {
this.container.classList.add("static");
return;
}
if (this.container.classList.remove("static"), this.container.style.position = "absolute", typeof e == "object" && "x" in e)
t.left = `${e.x}px`, t.top = `${e.y}px`;
else {
const i = "20px";
switch (e) {
case "top-left":
t.top = i, t.left = i;
break;
case "top-center":
t.top = i, t.left = "50%", t.transform = "translateX(-50%)";
break;
case "top-right":
t.top = i, t.right = i;
break;
case "bottom-left":
t.bottom = i, t.left = i;
break;
case "bottom-center":
t.bottom = i, t.left = "50%", t.transform = "translateX(-50%)";
break;
case "bottom-right":
t.bottom = i, t.right = i;
break;
case "left-center":
t.left = i, t.top = "50%", t.transform = "translateY(-50%)";
break;
case "right-center":
t.right = i, t.top = "50%", t.transform = "translateY(-50%)";
break;
case "center":
t.top = "50%", t.left = "50%", t.transform = "translate(-50%, -50%)";
break;
}
}
}
/**
* 应用样式到容器
*/
applyStyles() {
const e = this.container.style;
this.options.backgroundColor && e.setProperty("--bim-btn-group-section-bg", this.options.backgroundColor), this.options.btnBackgroundColor && e.setProperty("--bim-btn-bg", this.options.btnBackgroundColor), this.options.btnHoverColor && e.setProperty("--bim-btn-hover-bg", this.options.btnHoverColor), this.options.btnActiveColor && e.setProperty("--bim-btn-active-bg", this.options.btnActiveColor), this.options.iconColor && e.setProperty("--bim-icon-color", this.options.iconColor), this.options.iconActiveColor && e.setProperty("--bim-icon-active-color", this.options.iconActiveColor), this.options.textColor && e.setProperty("--bim-btn-text-color", this.options.textColor), this.options.textActiveColor && e.setProperty("--bim-btn-text-active-color", this.options.textActiveColor);
}
/**
* 设置主题颜色
* 只会应用到没有被用户自定义的颜色属性上
*/
setTheme(e) {
const t = {
backgroundColor: e.panelBackground,
btnBackgroundColor: e.componentBackground,
btnHoverColor: e.componentHover,
btnActiveColor: e.componentActive,
iconColor: e.icon,
iconActiveColor: e.iconActive,
textColor: e.textSecondary,
textActiveColor: e.textPrimary
};
Object.entries(t).forEach(([i, s]) => {
const n = i;
this.customColors.has(n) || (this.options[n] = s);
}), this.applyStyles();
}
/**
* 直接设置颜色(强制覆盖)
* 设置的颜色会被标记为自定义,后续的 setTheme 不会覆盖它们
*/
setColors(e) {
this.options = { ...this.options, ...e }, Object.keys(e).forEach((t) => {
this.customColors.add(t);
}), this.applyStyles();
}
async init() {
this.render(), this.unsubscribeLocale = dr.subscribe(() => {
this.setLocales();
}), this.unsubscribeTheme = oi.subscribe((e) => {
this.setTheme(e);
});
}
setLocales() {
this.render();
}
addGroup(e, t) {
if (this.groups.some((s) => s.id === e)) return;
const i = { id: e, buttons: [] };
if (t) {
const s = this.groups.findIndex((n) => n.id === t);
s !== -1 ? this.groups.splice(s, 0, i) : this.groups.push(i);
} else
this.groups.push(i);
}
addButton(e) {
const { groupId: t, parentId: i } = e, s = this.groups.find((a) => a.id === t);
if (!s) return;
const n = { ...e, children: e.children || [] };
if (i) {
const a = this.findButton(s.buttons, i);
a && (a.children || (a.children = []), a.children.push(n));
} else
s.buttons.push(n);
}
findButton(e, t) {
for (const i of e) {
if (i.id === t) return i;
if (i.children) {
const s = this.findButton(i.children, t);
if (s) return s;
}
}
}
render() {
this.container.innerHTML = "", this.btnRefs.clear(), this.groups.forEach((e, t) => {
const i = this.renderGroup(e, t, this.groups.length);
this.container.appendChild(i);
});
}
renderGroup(e, t, i) {
const s = document.createElement("div");
return s.className = "bim-btn-group-section", t < i - 1 && s.classList.add("has-divider"), e.buttons.forEach((n) => {
if (this.isVisible(n.id)) {
const a = this.renderButton(n);
s.appendChild(a);
}
}), s;
}
renderButton(e) {
const t = document.createElement("div");
t.className = "opt-btn-wrapper";
const i = document.createElement("div");
i.className = "opt-btn", (e.align || this.options.align || "vertical") === "horizontal" ? i.classList.add("align-horizontal") : i.classList.add("align-vertical"), this.activeBtnIds.has(e.id) && i.classList.add("active"), e.disabled && i.classList.add("disabled"), this.options.showLabel && e.label || i.classList.add("no-label");
const a = e.iconSize || 32, o = e.minWidth || 50;
i.style.minWidth = `${o}px`;
const l = document.createElement("div");
l.className = "opt-btn-icon", l.style.width = `${a}px`, l.style.height = `${a}px`, l.innerHTML = this.getIcon(e.icon), i.appendChild(l);
const c = document.createElement("div");
if (c.className = "opt-btn-text-wrapper", this.options.showLabel && e.label) {
const h = document.createElement("span");
h.className = "opt-btn-label", h.textContent = xn(e.label), c.appendChild(h);
}
if (e.children && e.children.length > 0) {
const h = document.createElement("span");
h.className = "opt-btn-arrow", h.textContent = "▼", c.appendChild(h);
}
return c.hasChildNodes() && i.appendChild(c), i.addEventListener("click", () => this.handleClick(e)), i.addEventListener("mouseenter", () => this.handleMouseEnter(e, i)), i.addEventListener("mouseleave", () => this.handleMouseLeave()), this.btnRefs.set(e.id, i), t.appendChild(i), t;
}
handleClick(e) {
e.disabled || (!e.children || e.children.length === 0) && (e.keepActive && (this.activeBtnIds.has(e.id) ? this.activeBtnIds.delete(e.id) : this.activeBtnIds.add(e.id), this.updateButtonState(e.id)), this.closeDropdown(), e.onClick && e.onClick(e));
}
handleMouseEnter(e, t) {
this.hoverTimeout && clearTimeout(this.hoverTimeout), e.children && e.children.length > 0 ? this.showDropdown(e, t) : this.closeDropdown();
}
handleMouseLeave() {
this.hoverTimeout = window.setTimeout(() => this.closeDropdown(), 200);
}
showDropdown(e, t) {
if (this.closeDropdown(), !e.children) return;
const i = document.createElement("div");
i.className = "opt-btn-dropdown", this.options.backgroundColor && i.style.setProperty("--bim-toolbar-bg", this.options.backgroundColor);
const s = t.getBoundingClientRect(), n = this.options.expand || "down";
this.options.direction === "row" ? i.style.flexDirection = "column" : i.style.flexDirection = "row", document.body.appendChild(i), e.children.forEach((o) => {
if (this.isVisible(o.id)) {
const l = this.renderDropdownItem(o);
i.appendChild(l);
}
});
const a = i.getBoundingClientRect();
n === "up" ? (i.style.bottom = window.innerHeight - s.top + 8 + "px", i.style.left = s.left + (s.width - a.width) / 2 + "px") : n === "down" ? (i.style.top = s.bottom + 8 + "px", i.style.left = s.left + (s.width - a.width) / 2 + "px") : n === "right" ? (i.style.top = s.top + (s.height - a.height) / 2 + "px", i.style.left = s.right + 8 + "px") : n === "left" && (i.style.top = s.top + (s.height - a.height) / 2 + "px", i.style.right = window.innerWidth - s.left + 8 + "px"), i.addEventListener("mouseenter", () => {
this.hoverTimeout && clearTimeout(this.hoverTimeout);
}), i.addEventListener("mouseleave", () => this.handleMouseLeave()), this.dropdownElement = i;
}
renderDropdownItem(e) {
const t = document.createElement("div");
t.className = "opt-btn-dropdown-item", (e.align || "horizontal") === "horizontal" ? t.classList.add("align-horizontal") : t.classList.add("align-vertical");
const s = e.iconSize || 32, n = e.minWidth;
n && (t.style.minWidth = `${n}px`);
const a = document.createElement("div");
if (a.className = "opt-btn-icon", a.style.width = `${s}px`, a.style.height = `${s}px`, a.innerHTML = this.getIcon(e.icon), t.appendChild(a), this.options.showLabel && e.label) {
const o = document.createElement("span");
o.className = "opt-btn-dropdown-label", o.textContent = xn(e.label), t.appendChild(o);
}
return t.addEventListener("click", (o) => {
o.stopPropagation(), this.handleClick(e);
}), t;
}
closeDropdown() {
this.dropdownElement && (this.dropdownElement.remove(), this.dropdownElement = null), this.btnRefs.forEach((e) => {
const t = e.querySelector(".opt-btn-arrow");
t && t.classList.remove("rotated");
});
}
updateButtonState(e) {
const t = this.btnRefs.get(e);
t && (this.activeBtnIds.has(e) ? t.classList.add("active") : t.classList.remove("active"));
}
getIcon(e) {
return e || this.DEFAULT_ICON;
}
updateButtonVisibility(e, t) {
this.options.visibility || (this.options.visibility = {}), this.options.visibility[e] = t, this.render();
}
setShowLabel(e) {
this.options.showLabel = e, this.updateLabelsVisibility();
}
updateLabelsVisibility() {
this.btnRefs.forEach((e, t) => {
const i = this.findButtonById(t);
if (!i) return;
this.options.showLabel && i.label ? e.classList.remove("no-label") : e.classList.add("no-label");
});
}
findButtonById(e) {
for (const t of this.groups) {
const i = this.findButton(t.buttons, e);
if (i) return i;
}
}
setBackgroundColor(e) {
this.setColors({ backgroundColor: e });
}
isVisible(e) {
return this.options.visibility?.[e] !== !1;
}
destroy() {
this.unsubscribeLocale && (this.unsubscribeLocale(), this.unsubscribeLocale = null), this.unsubscribeTheme && (this.unsubscribeTheme(), this.unsubscribeTheme = null), this.closeDropdown(), this.container.innerHTML = "", this.btnRefs.clear();
}
}
class Xh extends Nc {
/**
* 重写初始化,加载默认按钮
*/
async init() {
await super.init();
const { homeButton: e } = await import("./index-CAPOUzfO.mjs"), { locationButton: t } = await import("./index-Cadgm6mg.mjs"), { walkMenuButton: i } = await import("./index-BzDQeHxh.mjs"), { walkPersonButton: s } = await import("./index-CIgUZcJM.mjs"), { walkBirdButton: n } = await import("./index-psziCat8.mjs"), { settingButton: a } = await import("./index-DSz8VpYf.mjs"), { infoButton: o } = await import("./index-C4v-Lg_Y.mjs");
this.addGroup("group-1"), this.addButton(e), this.addButton(i), this.addButton(s), this.addButton(n), this.addButton(t), this.addGroup("group-2"), this.addButton(a), this.addButton(o), this.render();
}
}
class qh {
toolbar = null;
toolbarContainer = null;
container;
constructor(e) {
this.container = e, this.init();
}
init() {
this.toolbarContainer = document.createElement("div"), this.toolbarContainer.id = "opt-btn-groups", this.toolbarContainer.className = "bim-engine-opt-btn-container is-bottom-toolbar", this.container.appendChild(this.toolbarContainer), this.toolbar = new Xh({
container: this.toolbarContainer,
showLabel: !0,
direction: "row",
position: "bottom-center",
// 底部居中
align: "vertical",
// 图标在上
expand: "up"
// 向上展开
}), this.toolbar.init();
}
updateTheme(e) {
this.toolbar?.setTheme(e);
}
refresh() {
this.toolbar?.render();
}
destroy() {
this.toolbar?.destroy(), this.toolbar = null;
}
// --- 转发 API ---
addGroup(e, t) {
this.toolbar?.addGroup(e, t), this.toolbar?.render();
}
addButton(e) {
this.toolbar?.addButton(e), this.toolbar?.render();
}
setButtonVisibility(e, t) {
this.toolbar?.updateButtonVisibility(e, t);
}
setShowLabel(e) {
this.toolbar?.setShowLabel(e);
}
setVisible(e) {
this.toolbarContainer && (this.toolbarContainer.style.visibility = e ? "visible" : "hidden");
}
setBackgroundColor(e) {
this.toolbar?.setBackgroundColor(e);
}
setColors(e) {
this.toolbar?.setColors(e);
}
}
class Yh {
activeGroups = [];
container;
constructor(e) {
this.container = e;
}
/**
* 创建一个新的按钮组
*/
create(e) {
const t = document.createElement("div");
this.container.appendChild(t);
const i = new Nc({
container: t,
...e
});
return i.init(), this.activeGroups.push(i), i;
}
updateTheme(e) {
this.activeGroups.forEach((t) => t.setTheme(e));
}
refresh() {
this.activeGroups.forEach((e) => e.render());
}
destroy() {
this.activeGroups.forEach((e) => e.destroy()), this.activeGroups = [];
}
}
class Oc {
element;
options;
container;
header;
contentArea;
_isDestroyed = !1;
_isInitialized = !1;
unsubscribeTheme = null;
unsubscribeLocale = null;
// 性能优化:用于存储 requestAnimationFrame 的 ID
rafId = null;
/**
* 构造函数
* @param options 弹窗配置选项
*/
constructor(e) {
this.options = {
title: "Dialog",
width: 300,
height: "auto",
position: "center",
draggable: !0,
resizable: !1,
minWidth: 200,
minHeight: 100,
...e
}, this.container = e.container, this.element = this.createDom(), this.header = this.element.querySelector(".bim-dialog-header"), this.contentArea = this.element.querySelector(".bim-dialog-content"), this.init();
}
/**
* 设置主题
* @param theme 全局主题配置
*/
setTheme(e) {
const t = this.element.style;
this.options.backgroundColor || t.setProperty("--bim-dialog-bg", e.panelBackground), this.options.headerBackgroundColor || t.setProperty("--bim-dialog-header-bg", e.componentHover), this.options.titleColor || t.setProperty("--bim-dialog-title-color", e.textPrimary), this.options.textColor || t.setProperty("--bim-dialog-text-color", e.textPrimary), this.options.borderColor || t.setProperty("--bim-dialog-border-color", e.border);
}
/**
* 初始化组件功能 (接口实现)
*/
init() {
this._isInitialized || (this.container.appendChild(this.element), this.initPosition(), this.options.draggable && this.initDrag(), this.options.resizable && this.initResize(), this._isInitialized = !0, this.options.onOpen && this.options.onOpen(), this.unsubscribeTheme = oi.subscribe((e) => {
this.setTheme(e);
}), this.unsubscribeLocale = dr.subscribe(() => {
this.setLocales();
}));
}
setLocales() {
if (this.options.title) {
const e = this.header.querySelector(".bim-dialog-title");
e && (e.textContent = xn(this.options.title));
}
}
/**
* 创建弹窗的 DOM 结构
*/
createDom() {
const e = document.createElement("div");
e.className = "bim-dialog", this.options.id && (e.id = this.options.id);
const t = e.style;
this.options.backgroundColor && t.setProperty("--bim-dialog-bg", this.options.backgroundColor), this.options.headerBackgroundColor && t.setProperty("--bim-dialog-header-bg", this.options.headerBackgroundColor), this.options.titleColor && t.setProperty("--bim-dialog-title-color", this.options.titleColor), this.options.textColor && t.setProperty("--bim-dialog-text-color", this.options.textColor), this.options.borderColor && t.setProperty("--bim-dialog-border-color", this.options.borderColor), this.setSize(e, this.options.width, this.options.height);
const i = document.createElement("div");
i.className = "bim-dialog-header", this.options.draggable && i.classList.add("draggable");
const s = document.createElement("span");
s.className = "bim-dialog-title", s.textContent = this.options.title ? xn(this.options.title) : "";
const n = document.createElement("span");
n.className = "bim-dialog-close", n.innerHTML = "×", n.onclick = () => {
this.close();
}, i.appendChild(s), i.appendChild(n);
const a = document.createElement("div");
if (a.className = "bim-dialog-content", typeof this.options.content == "string" ? a.innerHTML = this.options.content : this.options.content instanceof HTMLElement && a.appendChild(this.options.content), e.appendChild(i), e.appendChild(a), this.options.resizable) {
const c = document.createElement("div");
c.className = "bim-dialog-resize-handle", e.appendChild(c);
}
const o = (c) => {
c.stopPropagation();
};
return [
"click",
"dblclick",
"contextmenu",
"wheel",
"mousedown",
"mouseup",
"mousemove",
"touchstart",
"touchend",
"touchmove",
"pointerdown",
"pointerup",
"pointermove",
"pointerenter",
"pointerleave",
"pointerover",
"pointerout"
].forEach((c) => {
e.addEventListener(c, o, { passive: !1 });
}), e;
}
/**
* 设置元素尺寸
*/
setSize(e, t, i) {
t !== void 0 && (e.style.width = typeof t == "number" ? `${t}px` : t), i !== void 0 && (e.style.height = typeof i == "number" ? `${i}px` : i);
}
/**
* 初始化弹窗位置
*/
initPosition() {
const e = this.options.position, t = this.element.getBoundingClientRect();
let i = 0, s = 0;
const n = this.container.clientWidth, a = this.container.clientHeight, o = t.width, l = t.height;
if (typeof e == "object" && "x" in e)
i = e.x, s = e.y;
else
switch (e) {
case "center":
i = (n - o) / 2, s = (a - l) / 2;
break;
case "top-left":
i = 0, s = 0;
break;
case "top-center":
i = (n - o) / 2, s = 0;
break;
case "top-right":
i = n - o, s = 0;
break;
case "left-center":
i = 0, s = (a - l) / 2;
break;
case "right-center":
i = n - o, s = (a - l) / 2;
break;
case "bottom-left":
i = 0, s = a - l;
break;
case "bottom-center":
i = (n - o) / 2, s = a - l;
break;
case "bottom-right":
i = n - o, s = a - l;
break;
default:
i = (n - o) / 2, s = (a - l) / 2;
}
i = Math.max(0, Math.min(i, n - o)), s = Math.max(0, Math.min(s, a - l)), this.element.style.left = `${i}px`, this.element.style.top = `${s}px`;
}
/**
* 初始化拖拽功能 (性能优化 + 解决粘手)
*/
initDrag() {
let e = 0, t = 0, i = 0, s = 0, n = 0, a = 0, o = 0, l = 0;
const c = (d) => {
d.preventDefault(), d.stopPropagation(), e = d.clientX, t = d.clientY, i = this.element.offsetLeft, s = this.element.offsetTop, n = this.container.clientWidth, a = this.container.clientHeight, o = this.element.offsetWidth, l = this.element.offsetHeight, document.addEventListener("mousemove", h, { capture: !0 }), document.addEventListener("mouseup", u, { capture: !0 });
}, h = (d) => {
d.preventDefault(), d.stopPropagation(), !this.rafId && (this.rafId = requestAnimationFrame(() => {
const f = d.clientX - e, g = d.clientY - t;
let v = i + f, m = s + g;
const p = n - o, y = a - l;
v = Math.max(0, Math.min(v, p)), m = Math.max(0, Math.min(m, y)), this.element.style.left = `${v}px`, this.element.style.top = `${m}px`, this.rafId = null;
}));
}, u = () => {
this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), document.removeEventListener("mousemove", h, { capture: !0 }), document.removeEventListener("mouseup", u, { capture: !0 });
};
this.header.addEventListener("mousedown", c);
}
/**
* 初始化缩放功能 (性能优化 + 解决粘手)
*/
initResize() {
const e = this.element.querySelector(".bim-dialog-resize-handle");
if (!e) return;
let t = 0, i = 0, s = 0, n = 0;
const a = (c) => {
c.preventDefault(), c.stopPropagation(), t = c.clientX, i = c.clientY, s = this.element.offsetWidth, n = this.element.offsetHeight, document.addEventListener("mousemove", o, { capture: !0 }), document.addEventListener("mouseup", l, { capture: !0 });
}, o = (c) => {
c.preventDefault(), c.stopPropagation(), !this.rafId && (this.rafId = requestAnimationFrame(() => {
const h = c.clientX - t, u = c.clientY - i, d = Math.max(this.options.minWidth || 100, s + h), f = Math.max(this.options.minHeight || 50, n + u);
this.element.style.width = `${d}px`, this.element.style.height = `${f}px`, this.rafId = null;
}));
}, l = () => {
this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), document.removeEventListener("mousemove", o, { capture: !0 }), document.removeEventListener("mouseup", l, { capture: !0 });
};
e.addEventListener("mousedown", a);
}
/**
* 动态设置内容
* @param content 内容元素或 HTML 字符串
*/
setContent(e) {
this.contentArea.innerHTML = "", typeof e == "string" ? this.contentArea.innerHTML = e : this.contentArea.appendChild(e);
}
/**
* 关闭弹窗并销毁
*/
close() {
this._isDestroyed || (this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.unsubscribeTheme && (this.unsubscribeTheme(), this.unsubscribeTheme = null), this.unsubscribeLocale && (this.unsubscribeLocale(), this.unsubscribeLocale = null), this.element.remove(), this._isDestroyed = !0, this.options.onClose && this.options.onClose());
}
/**
* 销毁组件 (接口实现)
*/
destroy() {
this.close();
}
}
class Kh extends Oc {
/**
* 构造函数
* @param container 父容器
*/
constructor(e) {
const t = document.createElement("div");
t.className = "bim-info-dialog-content";
const i = document.createElement("h3");
i.textContent = "Model Information";
const s = document.createElement("ul");
s.innerHTML = `
Name: Sample Project
Version: 1.0.0
Date: ${(/* @__PURE__ */ new Date()).toLocaleDateString()}
Status:Active
`;
const n = document.createElement("button");
n.textContent = "Update Status", n.style.marginTop = "10px", n.onclick = () => {
alert("Status updated!");
}, t.appendChild(i), t.appendChild(s), t.appendChild(n), super({
container: e,
title: "dialog.testTitle",
content: t,
width: 320,
height: "auto",
position: "center",
resizable: !0,
draggable: !0,
// 可以在这里添加特定的 onClose 逻辑
onClose: () => {
console.log("Info dialog closed");
},
onOpen: () => {
console.log("Info dialog opened");
}
});
}
// 不需要再手动实现 setTheme, destroy, close, init
// 它们都已从 BimDialog 继承
}
class Zh {
/** 弹窗挂载的父容器 */
container;
/** 活跃的弹窗实例列表 */
activeDialogs = [];
/**
* 构造函数
* @param container 弹窗挂载的目标容器
*/
constructor(e) {
this.container = e;
}
/**
* 创建一个通用弹窗
* @param options 弹窗配置选项(不需要传 container,自动使用管理器绑定的容器)
* @returns BimDialog 实例
*/
create(e) {
const t = new Oc({
container: this.container,
...e,
onClose: () => {
this.activeDialogs = this.activeDialogs.filter((i) => i !== t), e.onClose && e.onClose();
}
});
return t.setTheme(oi.getTheme()), this.activeDialogs.push(t), t;
}
/**
* 显示二次封装的模型信息弹窗
* 演示如何调用特定的业务弹窗组件
*/
showInfoDialog() {
new Kh(this.container);
}
/**
* 响应全局主题变更
* @param theme 全局主题配置
*/
updateTheme(e) {
this.activeDialogs.forEach((t) => {
t.setTheme && t.setTheme(e);
});
}
}
const Or = { ROTATE: 0, DOLLY: 1, PAN: 2 }, Ur = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }, Jh = 0, nl = 1, $h = 2, Bc = 1, Fc = 2, Bi = 3, Ti = 0, Ft = 1, Vt = 2, vt = 0, Br = 1, yn = 2, al = 3, ol = 4, zc = 5, li = 100, Qh = 101, eu = 102, tu = 103, iu = 104, ms = 200, ru = 201, su = 202, nu = 203, Ta = 204, Ea = 205, wa = 206, au = 207, Ca = 208, ou = 209, lu = 210, cu = 211, hu = 212, uu = 213, du = 214, Ra = 0, Aa = 1, Pa = 2, Vr = 3, Da = 4, La = 5, Ia = 6, Ua = 7, To = 0, pu = 1, fu = 2, $i = 0, kc = 1, Hc = 2, Vc = 3, Eo = 4, Gc = 5, Wc = 6, jc = 7, ll = "attached", mu = "detached", Xc = 300, Gr = 301, Wr = 302, Mn = 303, Na = 304, Pn = 306, Ei = 1e3, Jt = 1001, Sn = 1002, Dt = 1003, qc = 1004, gs = 1005, xt = 1006, pn = 1007, Si = 1008, fi = 1009, Yc = 1010, Kc = 1011, Ss = 1012, wo = 1013, pr = 1014, Gt = 1015, ft = 1016, Co = 1017, Ro = 1018, jr = 1020, Zc = 35902, Jc = 35899, $c = 1021, Qc = 1022, qt = 1023, bs = 1026, Xr = 1027, Ao = 1028, Po = 1029, Do = 1030, Lo = 1031, Io = 1033, fn = 33776, mn = 33777, gn = 33778, vn = 33779, Oa = 35840, Ba = 35841, Fa = 35842, za = 35843, ka = 36196, Ha = 37492, Va = 37496, Ga = 37808, Wa = 37809, ja = 37810, Xa = 37811, qa = 37812, Ya = 37813, Ka = 37814, Za = 37815, Ja = 37816, $a = 37817, Qa = 37818, eo = 37819, to = 37820, io = 37821, ro = 36492, so = 36494, no = 36495, ao = 36283, oo = 36284, lo = 36285, co = 36286, Ts = 2300, Es = 2301, On = 2302, cl = 2400, hl = 2401, ul = 2402, gu = 2500, vu = 0, eh = 1, ho = 2, _u = 3200, th = 3201, Dn = 0, xu = 1, Ki = "", wt = "srgb", Ut = "srgb-linear", bn = "linear", et = "srgb", _r = 7680, Bn = 34055, Fn = 34056, yu = 517, uo = 519, Mu = 512, Su = 513, bu = 514, ih = 515, Tu = 516, Eu = 517, wu = 518, Cu = 519, po = 35044, dl = "300 es", bi = 2e3, Tn = 2001;
function rh(r) {
for (let e = r.length - 1; e >= 0; --e)
if (r[e] >= 65535) return !0;
return !1;
}
function ws(r) {
return document.createElementNS("http://www.w3.org/1999/xhtml", r);
}
function Ru() {
const r = ws("canvas");
return r.style.display = "block", r;
}
const pl = {};
function En(...r) {
const e = "THREE." + r.shift();
console.log(e, ...r);
}
function Se(...r) {
const e = "THREE." + r.shift();
console.warn(e, ...r);
}
function He(...r) {
const e = "THREE." + r.shift();
console.error(e, ...r);
}
function Cs(...r) {
const e = r.join(" ");
e in pl || (pl[e] = !0, Se(...r));
}
function Au(r, e, t) {
return new Promise(function(i, s) {
function n() {
switch (r.clientWaitSync(e, r.SYNC_FLUSH_COMMANDS_BIT, 0)) {
case r.WAIT_FAILED:
s();
break;
case r.TIMEOUT_EXPIRED:
setTimeout(n, t);
break;
default:
i();
}
}
setTimeout(n, t);
});
}
class gr {
/**
* Adds the given event listener to the given event type.
*
* @param {string} type - The type of event to listen to.
* @param {Function} listener - The function that gets called when the event is fired.
*/
addEventListener(e, t) {
this._listeners === void 0 && (this._listeners = {});
const i = this._listeners;
i[e] === void 0 && (i[e] = []), i[e].indexOf(t) === -1 && i[e].push(t);
}
/**
* Returns `true` if the given event listener has been added to the given event type.
*
* @param {string} type - The type of event.
* @param {Function} listener - The listener to check.
* @return {boolean} Whether the given event listener has been added to the given event type.
*/
hasEventListener(e, t) {
const i = this._listeners;
return i === void 0 ? !1 : i[e] !== void 0 && i[e].indexOf(t) !== -1;
}
/**
* Removes the given event listener from the given event type.
*
* @param {string} type - The type of event.
* @param {Function} listener - The listener to remove.
*/
removeEventListener(e, t) {
const i = this._listeners;
if (i === void 0) return;
const s = i[e];
if (s !== void 0) {
const n = s.indexOf(t);
n !== -1 && s.splice(n, 1);
}
}
/**
* Dispatches an event object.
*
* @param {Object} event - The event that gets fired.
*/
dispatchEvent(e) {
const t = this._listeners;
if (t === void 0) return;
const i = t[e.type];
if (i !== void 0) {
e.target = this;
const s = i.slice(0);
for (let n = 0, a = s.length; n < a; n++)
s[n].call(this, e);
e.target = null;
}
}
}
const Lt = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"];
let fl = 1234567;
const xs = Math.PI / 180, qr = 180 / Math.PI;
function di() {
const r = Math.random() * 4294967295 | 0, e = Math.random() * 4294967295 | 0, t = Math.random() * 4294967295 | 0, i = Math.random() * 4294967295 | 0;
return (Lt[r & 255] + Lt[r >> 8 & 255] + Lt[r >> 16 & 255] + Lt[r >> 24 & 255] + "-" + Lt[e & 255] + Lt[e >> 8 & 255] + "-" + Lt[e >> 16 & 15 | 64] + Lt[e >> 24 & 255] + "-" + Lt[t & 63 | 128] + Lt[t >> 8 & 255] + "-" + Lt[t >> 16 & 255] + Lt[t >> 24 & 255] + Lt[i & 255] + Lt[i >> 8 & 255] + Lt[i >> 16 & 255] + Lt[i >> 24 & 255]).toLowerCase();
}
function ze(r, e, t) {
return Math.max(e, Math.min(t, r));
}
function Uo(r, e) {
return (r % e + e) % e;
}
function Pu(r, e, t, i, s) {
return i + (r - e) * (s - i) / (t - e);
}
function Du(r, e, t) {
return r !== e ? (t - r) / (e - r) : 0;
}
function ys(r, e, t) {
return (1 - t) * r + t * e;
}
function Lu(r, e, t, i) {
return ys(r, e, 1 - Math.exp(-t * i));
}
function Iu(r, e = 1) {
return e - Math.abs(Uo(r, e * 2) - e);
}
function Uu(r, e, t) {
return r <= e ? 0 : r >= t ? 1 : (r = (r - e) / (t - e), r * r * (3 - 2 * r));
}
function Nu(r, e, t) {
return r <= e ? 0 : r >= t ? 1 : (r = (r - e) / (t - e), r * r * r * (r * (r * 6 - 15) + 10));
}
function Ou(r, e) {
return r + Math.floor(Math.random() * (e - r + 1));
}
function Bu(r, e) {
return r + Math.random() * (e - r);
}
function Fu(r) {
return r * (0.5 - Math.random());
}
function zu(r) {
r !== void 0 && (fl = r);
let e = fl += 1831565813;
return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296;
}
function ku(r) {
return r * xs;
}
function Hu(r) {
return r * qr;
}
function Vu(r) {
return (r & r - 1) === 0 && r !== 0;
}
function Gu(r) {
return Math.pow(2, Math.ceil(Math.log(r) / Math.LN2));
}
function Wu(r) {
return Math.pow(2, Math.floor(Math.log(r) / Math.LN2));
}
function ju(r, e, t, i, s) {
const n = Math.cos, a = Math.sin, o = n(t / 2), l = a(t / 2), c = n((e + i) / 2), h = a((e + i) / 2), u = n((e - i) / 2), d = a((e - i) / 2), f = n((i - e) / 2), g = a((i - e) / 2);
switch (s) {
case "XYX":
r.set(o * h, l * u, l * d, o * c);
break;
case "YZY":
r.set(l * d, o * h, l * u, o * c);
break;
case "ZXZ":
r.set(l * u, l * d, o * h, o * c);
break;
case "XZX":
r.set(o * h, l * g, l * f, o * c);
break;
case "YXY":
r.set(l * f, o * h, l * g, o * c);
break;
case "ZYZ":
r.set(l * g, l * f, o * h, o * c);
break;
default:
Se("MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: " + s);
}
}
function ci(r, e) {
switch (e.constructor) {
case Float32Array:
return r;
case Uint32Array:
return r / 4294967295;
case Uint16Array:
return r / 65535;
case Uint8Array:
return r / 255;
case Int32Array:
return Math.max(r / 2147483647, -1);
case Int16Array:
return Math.max(r / 32767, -1);
case Int8Array:
return Math.max(r / 127, -1);
default:
throw new Error("Invalid component type.");
}
}
function tt(r, e) {
switch (e.constructor) {
case Float32Array:
return r;
case Uint32Array:
return Math.round(r * 4294967295);
case Uint16Array:
return Math.round(r * 65535);
case Uint8Array:
return Math.round(r * 255);
case Int32Array:
return Math.round(r * 2147483647);
case Int16Array:
return Math.round(r * 32767);
case Int8Array:
return Math.round(r * 127);
default:
throw new Error("Invalid component type.");
}
}
const No = {
DEG2RAD: xs,
RAD2DEG: qr,
/**
* Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
* (universally unique identifier).
*
* @static
* @method
* @return {string} The UUID.
*/
generateUUID: di,
/**
* Clamps the given value between min and max.
*
* @static
* @method
* @param {number} value - The value to clamp.
* @param {number} min - The min value.
* @param {number} max - The max value.
* @return {number} The clamped value.
*/
clamp: ze,
/**
* Computes the Euclidean modulo of the given parameters that
* is `( ( n % m ) + m ) % m`.
*
* @static
* @method
* @param {number} n - The first parameter.
* @param {number} m - The second parameter.
* @return {number} The Euclidean modulo.
*/
euclideanModulo: Uo,
/**
* Performs a linear mapping from range `` to range ``
* for the given value.
*
* @static
* @method
* @param {number} x - The value to be mapped.
* @param {number} a1 - Minimum value for range A.
* @param {number} a2 - Maximum value for range A.
* @param {number} b1 - Minimum value for range B.
* @param {number} b2 - Maximum value for range B.
* @return {number} The mapped value.
*/
mapLinear: Pu,
/**
* Returns the percentage in the closed interval `[0, 1]` of the given value
* between the start and end point.
*
* @static
* @method
* @param {number} x - The start point
* @param {number} y - The end point.
* @param {number} value - A value between start and end.
* @return {number} The interpolation factor.
*/
inverseLerp: Du,
/**
* Returns a value linearly interpolated from two known points based on the given interval -
* `t = 0` will return `x` and `t = 1` will return `y`.
*
* @static
* @method
* @param {number} x - The start point
* @param {number} y - The end point.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {number} The interpolated value.
*/
lerp: ys,
/**
* Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta
* time to maintain frame rate independent movement. For details, see
* [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/).
*
* @static
* @method
* @param {number} x - The current point.
* @param {number} y - The target point.
* @param {number} lambda - A higher lambda value will make the movement more sudden,
* and a lower value will make the movement more gradual.
* @param {number} dt - Delta time in seconds.
* @return {number} The interpolated value.
*/
damp: Lu,
/**
* Returns a value that alternates between `0` and the given `length` parameter.
*
* @static
* @method
* @param {number} x - The value to pingpong.
* @param {number} [length=1] - The positive value the function will pingpong to.
* @return {number} The alternated value.
*/
pingpong: Iu,
/**
* Returns a value in the range `[0,1]` that represents the percentage that `x` has
* moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
* the `min` and `max`.
*
* See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details.
*
* @static
* @method
* @param {number} x - The value to evaluate based on its position between min and max.
* @param {number} min - The min value. Any x value below min will be `0`.
* @param {number} max - The max value. Any x value above max will be `1`.
* @return {number} The alternated value.
*/
smoothstep: Uu,
/**
* A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
* that has zero 1st and 2nd order derivatives at x=0 and x=1.
*
* @static
* @method
* @param {number} x - The value to evaluate based on its position between min and max.
* @param {number} min - The min value. Any x value below min will be `0`.
* @param {number} max - The max value. Any x value above max will be `1`.
* @return {number} The alternated value.
*/
smootherstep: Nu,
/**
* Returns a random integer from `` interval.
*
* @static
* @method
* @param {number} low - The lower value boundary.
* @param {number} high - The upper value boundary
* @return {number} A random integer.
*/
randInt: Ou,
/**
* Returns a random float from `` interval.
*
* @static
* @method
* @param {number} low - The lower value boundary.
* @param {number} high - The upper value boundary
* @return {number} A random float.
*/
randFloat: Bu,
/**
* Returns a random integer from `<-range/2, range/2>` interval.
*
* @static
* @method
* @param {number} range - Defines the value range.
* @return {number} A random float.
*/
randFloatSpread: Fu,
/**
* Returns a deterministic pseudo-random float in the interval `[0, 1]`.
*
* @static
* @method
* @param {number} [s] - The integer seed.
* @return {number} A random float.
*/
seededRandom: zu,
/**
* Converts degrees to radians.
*
* @static
* @method
* @param {number} degrees - A value in degrees.
* @return {number} The converted value in radians.
*/
degToRad: ku,
/**
* Converts radians to degrees.
*
* @static
* @method
* @param {number} radians - A value in radians.
* @return {number} The converted value in degrees.
*/
radToDeg: Hu,
/**
* Returns `true` if the given number is a power of two.
*
* @static
* @method
* @param {number} value - The value to check.
* @return {boolean} Whether the given number is a power of two or not.
*/
isPowerOfTwo: Vu,
/**
* Returns the smallest power of two that is greater than or equal to the given number.
*
* @static
* @method
* @param {number} value - The value to find a POT for.
* @return {number} The smallest power of two that is greater than or equal to the given number.
*/
ceilPowerOfTwo: Gu,
/**
* Returns the largest power of two that is less than or equal to the given number.
*
* @static
* @method
* @param {number} value - The value to find a POT for.
* @return {number} The largest power of two that is less than or equal to the given number.
*/
floorPowerOfTwo: Wu,
/**
* Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles)
* defined by the given angles and order.
*
* Rotations are applied to the axes in the order specified by order:
* rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
*
* @static
* @method
* @param {Quaternion} q - The quaternion to set.
* @param {number} a - The rotation applied to the first axis, in radians.
* @param {number} b - The rotation applied to the second axis, in radians.
* @param {number} c - The rotation applied to the third axis, in radians.
* @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
*/
setQuaternionFromProperEuler: ju,
/**
* Normalizes the given value according to the given typed array.
*
* @static
* @method
* @param {number} value - The float value in the range `[0,1]` to normalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The normalize value.
*/
normalize: tt,
/**
* Denormalizes the given value according to the given typed array.
*
* @static
* @method
* @param {number} value - The value to denormalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The denormalize (float) value in the range `[0,1]`.
*/
denormalize: ci
};
class oe {
/**
* Constructs a new 2D vector.
*
* @param {number} [x=0] - The x value of this vector.
* @param {number} [y=0] - The y value of this vector.
*/
constructor(e = 0, t = 0) {
oe.prototype.isVector2 = !0, this.x = e, this.y = t;
}
/**
* Alias for {@link Vector2#x}.
*
* @type {number}
*/
get width() {
return this.x;
}
set width(e) {
this.x = e;
}
/**
* Alias for {@link Vector2#y}.
*
* @type {number}
*/
get height() {
return this.y;
}
set height(e) {
this.y = e;
}
/**
* Sets the vector components.
*
* @param {number} x - The value of the x component.
* @param {number} y - The value of the y component.
* @return {Vector2} A reference to this vector.
*/
set(e, t) {
return this.x = e, this.y = t, this;
}
/**
* Sets the vector components to the same value.
*
* @param {number} scalar - The value to set for all vector components.
* @return {Vector2} A reference to this vector.
*/
setScalar(e) {
return this.x = e, this.y = e, this;
}
/**
* Sets the vector's x component to the given value
*
* @param {number} x - The value to set.
* @return {Vector2} A reference to this vector.
*/
setX(e) {
return this.x = e, this;
}
/**
* Sets the vector's y component to the given value
*
* @param {number} y - The value to set.
* @return {Vector2} A reference to this vector.
*/
setY(e) {
return this.y = e, this;
}
/**
* Allows to set a vector component with an index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y.
* @param {number} value - The value to set.
* @return {Vector2} A reference to this vector.
*/
setComponent(e, t) {
switch (e) {
case 0:
this.x = t;
break;
case 1:
this.y = t;
break;
default:
throw new Error("index is out of range: " + e);
}
return this;
}
/**
* Returns the value of the vector component which matches the given index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y.
* @return {number} A vector component value.
*/
getComponent(e) {
switch (e) {
case 0:
return this.x;
case 1:
return this.y;
default:
throw new Error("index is out of range: " + e);
}
}
/**
* Returns a new vector with copied values from this instance.
*
* @return {Vector2} A clone of this instance.
*/
clone() {
return new this.constructor(this.x, this.y);
}
/**
* Copies the values of the given vector to this instance.
*
* @param {Vector2} v - The vector to copy.
* @return {Vector2} A reference to this vector.
*/
copy(e) {
return this.x = e.x, this.y = e.y, this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector2} v - The vector to add.
* @return {Vector2} A reference to this vector.
*/
add(e) {
return this.x += e.x, this.y += e.y, this;
}
/**
* Adds the given scalar value to all components of this instance.
*
* @param {number} s - The scalar to add.
* @return {Vector2} A reference to this vector.
*/
addScalar(e) {
return this.x += e, this.y += e, this;
}
/**
* Adds the given vectors and stores the result in this instance.
*
* @param {Vector2} a - The first vector.
* @param {Vector2} b - The second vector.
* @return {Vector2} A reference to this vector.
*/
addVectors(e, t) {
return this.x = e.x + t.x, this.y = e.y + t.y, this;
}
/**
* Adds the given vector scaled by the given factor to this instance.
*
* @param {Vector2} v - The vector.
* @param {number} s - The factor that scales `v`.
* @return {Vector2} A reference to this vector.
*/
addScaledVector(e, t) {
return this.x += e.x * t, this.y += e.y * t, this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector2} v - The vector to subtract.
* @return {Vector2} A reference to this vector.
*/
sub(e) {
return this.x -= e.x, this.y -= e.y, this;
}
/**
* Subtracts the given scalar value from all components of this instance.
*
* @param {number} s - The scalar to subtract.
* @return {Vector2} A reference to this vector.
*/
subScalar(e) {
return this.x -= e, this.y -= e, this;
}
/**
* Subtracts the given vectors and stores the result in this instance.
*
* @param {Vector2} a - The first vector.
* @param {Vector2} b - The second vector.
* @return {Vector2} A reference to this vector.
*/
subVectors(e, t) {
return this.x = e.x - t.x, this.y = e.y - t.y, this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector2} v - The vector to multiply.
* @return {Vector2} A reference to this vector.
*/
multiply(e) {
return this.x *= e.x, this.y *= e.y, this;
}
/**
* Multiplies the given scalar value with all components of this instance.
*
* @param {number} scalar - The scalar to multiply.
* @return {Vector2} A reference to this vector.
*/
multiplyScalar(e) {
return this.x *= e, this.y *= e, this;
}
/**
* Divides this instance by the given vector.
*
* @param {Vector2} v - The vector to divide.
* @return {Vector2} A reference to this vector.
*/
divide(e) {
return this.x /= e.x, this.y /= e.y, this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector2} A reference to this vector.
*/
divideScalar(e) {
return this.multiplyScalar(1 / e);
}
/**
* Multiplies this vector (with an implicit 1 as the 3rd component) by
* the given 3x3 matrix.
*
* @param {Matrix3} m - The matrix to apply.
* @return {Vector2} A reference to this vector.
*/
applyMatrix3(e) {
const t = this.x, i = this.y, s = e.elements;
return this.x = s[0] * t + s[3] * i + s[6], this.y = s[1] * t + s[4] * i + s[7], this;
}
/**
* If this vector's x or y value is greater than the given vector's x or y
* value, replace that value with the corresponding min value.
*
* @param {Vector2} v - The vector.
* @return {Vector2} A reference to this vector.
*/
min(e) {
return this.x = Math.min(this.x, e.x), this.y = Math.min(this.y, e.y), this;
}
/**
* If this vector's x or y value is less than the given vector's x or y
* value, replace that value with the corresponding max value.
*
* @param {Vector2} v - The vector.
* @return {Vector2} A reference to this vector.
*/
max(e) {
return this.x = Math.max(this.x, e.x), this.y = Math.max(this.y, e.y), this;
}
/**
* If this vector's x or y value is greater than the max vector's x or y
* value, it is replaced by the corresponding value.
* If this vector's x or y value is less than the min vector's x or y value,
* it is replaced by the corresponding value.
*
* @param {Vector2} min - The minimum x and y values.
* @param {Vector2} max - The maximum x and y values in the desired range.
* @return {Vector2} A reference to this vector.
*/
clamp(e, t) {
return this.x = ze(this.x, e.x, t.x), this.y = ze(this.y, e.y, t.y), this;
}
/**
* If this vector's x or y values are greater than the max value, they are
* replaced by the max value.
* If this vector's x or y values are less than the min value, they are
* replaced by the min value.
*
* @param {number} minVal - The minimum value the components will be clamped to.
* @param {number} maxVal - The maximum value the components will be clamped to.
* @return {Vector2} A reference to this vector.
*/
clampScalar(e, t) {
return this.x = ze(this.x, e, t), this.y = ze(this.y, e, t), this;
}
/**
* If this vector's length is greater than the max value, it is replaced by
* the max value.
* If this vector's length is less than the min value, it is replaced by the
* min value.
*
* @param {number} min - The minimum value the vector length will be clamped to.
* @param {number} max - The maximum value the vector length will be clamped to.
* @return {Vector2} A reference to this vector.
*/
clampLength(e, t) {
const i = this.length();
return this.divideScalar(i || 1).multiplyScalar(ze(i, e, t));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/
floor() {
return this.x = Math.floor(this.x), this.y = Math.floor(this.y), this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/
ceil() {
return this.x = Math.ceil(this.x), this.y = Math.ceil(this.y), this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector2} A reference to this vector.
*/
round() {
return this.x = Math.round(this.x), this.y = Math.round(this.y), this;
}
/**
* The components of this vector are rounded towards zero (up if negative,
* down if positive) to an integer value.
*
* @return {Vector2} A reference to this vector.
*/
roundToZero() {
return this.x = Math.trunc(this.x), this.y = Math.trunc(this.y), this;
}
/**
* Inverts this vector - i.e. sets x = -x and y = -y.
*
* @return {Vector2} A reference to this vector.
*/
negate() {
return this.x = -this.x, this.y = -this.y, this;
}
/**
* Calculates the dot product of the given vector with this instance.
*
* @param {Vector2} v - The vector to compute the dot product with.
* @return {number} The result of the dot product.
*/
dot(e) {
return this.x * e.x + this.y * e.y;
}
/**
* Calculates the cross product of the given vector with this instance.
*
* @param {Vector2} v - The vector to compute the cross product with.
* @return {number} The result of the cross product.
*/
cross(e) {
return this.x * e.y - this.y * e.x;
}
/**
* Computes the square of the Euclidean length (straight-line length) from
* (0, 0) to (x, y). If you are comparing the lengths of vectors, you should
* compare the length squared instead as it is slightly more efficient to calculate.
*
* @return {number} The square length of this vector.
*/
lengthSq() {
return this.x * this.x + this.y * this.y;
}
/**
* Computes the Euclidean length (straight-line length) from (0, 0) to (x, y).
*
* @return {number} The length of this vector.
*/
length() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
/**
* Computes the Manhattan length of this vector.
*
* @return {number} The length of this vector.
*/
manhattanLength() {
return Math.abs(this.x) + Math.abs(this.y);
}
/**
* Converts this vector to a unit vector - that is, sets it equal to a vector
* with the same direction as this one, but with a vector length of `1`.
*
* @return {Vector2} A reference to this vector.
*/
normalize() {
return this.divideScalar(this.length() || 1);
}
/**
* Computes the angle in radians of this vector with respect to the positive x-axis.
*
* @return {number} The angle in radians.
*/
angle() {
return Math.atan2(-this.y, -this.x) + Math.PI;
}
/**
* Returns the angle between the given vector and this instance in radians.
*
* @param {Vector2} v - The vector to compute the angle with.
* @return {number} The angle in radians.
*/
angleTo(e) {
const t = Math.sqrt(this.lengthSq() * e.lengthSq());
if (t === 0) return Math.PI / 2;
const i = this.dot(e) / t;
return Math.acos(ze(i, -1, 1));
}
/**
* Computes the distance from the given vector to this instance.
*
* @param {Vector2} v - The vector to compute the distance to.
* @return {number} The distance.
*/
distanceTo(e) {
return Math.sqrt(this.distanceToSquared(e));
}
/**
* Computes the squared distance from the given vector to this instance.
* If you are just comparing the distance with another distance, you should compare
* the distance squared instead as it is slightly more efficient to calculate.
*
* @param {Vector2} v - The vector to compute the squared distance to.
* @return {number} The squared distance.
*/
distanceToSquared(e) {
const t = this.x - e.x, i = this.y - e.y;
return t * t + i * i;
}
/**
* Computes the Manhattan distance from the given vector to this instance.
*
* @param {Vector2} v - The vector to compute the Manhattan distance to.
* @return {number} The Manhattan distance.
*/
manhattanDistanceTo(e) {
return Math.abs(this.x - e.x) + Math.abs(this.y - e.y);
}
/**
* Sets this vector to a vector with the same direction as this one, but
* with the specified length.
*
* @param {number} length - The new length of this vector.
* @return {Vector2} A reference to this vector.
*/
setLength(e) {
return this.normalize().multiplyScalar(e);
}
/**
* Linearly interpolates between the given vector and this instance, where
* alpha is the percent distance along the line - alpha = 0 will be this
* vector, and alpha = 1 will be the given one.
*
* @param {Vector2} v - The vector to interpolate towards.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector2} A reference to this vector.
*/
lerp(e, t) {
return this.x += (e.x - this.x) * t, this.y += (e.y - this.y) * t, this;
}
/**
* Linearly interpolates between the given vectors, where alpha is the percent
* distance along the line - alpha = 0 will be first vector, and alpha = 1 will
* be the second one. The result is stored in this instance.
*
* @param {Vector2} v1 - The first vector.
* @param {Vector2} v2 - The second vector.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector2} A reference to this vector.
*/
lerpVectors(e, t, i) {
return this.x = e.x + (t.x - e.x) * i, this.y = e.y + (t.y - e.y) * i, this;
}
/**
* Returns `true` if this vector is equal with the given one.
*
* @param {Vector2} v - The vector to test for equality.
* @return {boolean} Whether this vector is equal with the given one.
*/
equals(e) {
return e.x === this.x && e.y === this.y;
}
/**
* Sets this vector's x value to be `array[ offset ]` and y
* value to be `array[ offset + 1 ]`.
*
* @param {Array} array - An array holding the vector component values.
* @param {number} [offset=0] - The offset into the array.
* @return {Vector2} A reference to this vector.
*/
fromArray(e, t = 0) {
return this.x = e[t], this.y = e[t + 1], this;
}
/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The vector components.
*/
toArray(e = [], t = 0) {
return e[t] = this.x, e[t + 1] = this.y, e;
}
/**
* Sets the components of this vector from the given buffer attribute.
*
* @param {BufferAttribute} attribute - The buffer attribute holding vector data.
* @param {number} index - The index into the attribute.
* @return {Vector2} A reference to this vector.
*/
fromBufferAttribute(e, t) {
return this.x = e.getX(t), this.y = e.getY(t), this;
}
/**
* Rotates this vector around the given center by the given angle.
*
* @param {Vector2} center - The point around which to rotate.
* @param {number} angle - The angle to rotate, in radians.
* @return {Vector2} A reference to this vector.
*/
rotateAround(e, t) {
const i = Math.cos(t), s = Math.sin(t), n = this.x - e.x, a = this.y - e.y;
return this.x = n * i - a * s + e.x, this.y = n * s + a * i + e.y, this;
}
/**
* Sets each component of this vector to a pseudo-random value between `0` and
* `1`, excluding `1`.
*
* @return {Vector2} A reference to this vector.
*/
random() {
return this.x = Math.random(), this.y = Math.random(), this;
}
*[Symbol.iterator]() {
yield this.x, yield this.y;
}
}
class mi {
/**
* Constructs a new quaternion.
*
* @param {number} [x=0] - The x value of this quaternion.
* @param {number} [y=0] - The y value of this quaternion.
* @param {number} [z=0] - The z value of this quaternion.
* @param {number} [w=1] - The w value of this quaternion.
*/
constructor(e = 0, t = 0, i = 0, s = 1) {
this.isQuaternion = !0, this._x = e, this._y = t, this._z = i, this._w = s;
}
/**
* Interpolates between two quaternions via SLERP. This implementation assumes the
* quaternion data are managed in flat arrays.
*
* @param {Array} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @param {number} t - The interpolation factor in the range `[0,1]`.
* @see {@link Quaternion#slerp}
*/
static slerpFlat(e, t, i, s, n, a, o) {
let l = i[s + 0], c = i[s + 1], h = i[s + 2], u = i[s + 3], d = n[a + 0], f = n[a + 1], g = n[a + 2], v = n[a + 3];
if (o <= 0) {
e[t + 0] = l, e[t + 1] = c, e[t + 2] = h, e[t + 3] = u;
return;
}
if (o >= 1) {
e[t + 0] = d, e[t + 1] = f, e[t + 2] = g, e[t + 3] = v;
return;
}
if (u !== v || l !== d || c !== f || h !== g) {
let m = l * d + c * f + h * g + u * v;
m < 0 && (d = -d, f = -f, g = -g, v = -v, m = -m);
let p = 1 - o;
if (m < 0.9995) {
const y = Math.acos(m), _ = Math.sin(y);
p = Math.sin(p * y) / _, o = Math.sin(o * y) / _, l = l * p + d * o, c = c * p + f * o, h = h * p + g * o, u = u * p + v * o;
} else {
l = l * p + d * o, c = c * p + f * o, h = h * p + g * o, u = u * p + v * o;
const y = 1 / Math.sqrt(l * l + c * c + h * h + u * u);
l *= y, c *= y, h *= y, u *= y;
}
}
e[t] = l, e[t + 1] = c, e[t + 2] = h, e[t + 3] = u;
}
/**
* Multiplies two quaternions. This implementation assumes the quaternion data are managed
* in flat arrays.
*
* @param {Array} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @return {Array} The destination array.
* @see {@link Quaternion#multiplyQuaternions}.
*/
static multiplyQuaternionsFlat(e, t, i, s, n, a) {
const o = i[s], l = i[s + 1], c = i[s + 2], h = i[s + 3], u = n[a], d = n[a + 1], f = n[a + 2], g = n[a + 3];
return e[t] = o * g + h * u + l * f - c * d, e[t + 1] = l * g + h * d + c * u - o * f, e[t + 2] = c * g + h * f + o * d - l * u, e[t + 3] = h * g - o * u - l * d - c * f, e;
}
/**
* The x value of this quaternion.
*
* @type {number}
* @default 0
*/
get x() {
return this._x;
}
set x(e) {
this._x = e, this._onChangeCallback();
}
/**
* The y value of this quaternion.
*
* @type {number}
* @default 0
*/
get y() {
return this._y;
}
set y(e) {
this._y = e, this._onChangeCallback();
}
/**
* The z value of this quaternion.
*
* @type {number}
* @default 0
*/
get z() {
return this._z;
}
set z(e) {
this._z = e, this._onChangeCallback();
}
/**
* The w value of this quaternion.
*
* @type {number}
* @default 1
*/
get w() {
return this._w;
}
set w(e) {
this._w = e, this._onChangeCallback();
}
/**
* Sets the quaternion components.
*
* @param {number} x - The x value of this quaternion.
* @param {number} y - The y value of this quaternion.
* @param {number} z - The z value of this quaternion.
* @param {number} w - The w value of this quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
set(e, t, i, s) {
return this._x = e, this._y = t, this._z = i, this._w = s, this._onChangeCallback(), this;
}
/**
* Returns a new quaternion with copied values from this instance.
*
* @return {Quaternion} A clone of this instance.
*/
clone() {
return new this.constructor(this._x, this._y, this._z, this._w);
}
/**
* Copies the values of the given quaternion to this instance.
*
* @param {Quaternion} quaternion - The quaternion to copy.
* @return {Quaternion} A reference to this quaternion.
*/
copy(e) {
return this._x = e.x, this._y = e.y, this._z = e.z, this._w = e.w, this._onChangeCallback(), this;
}
/**
* Sets this quaternion from the rotation specified by the given
* Euler angles.
*
* @param {Euler} euler - The Euler angles.
* @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
* @return {Quaternion} A reference to this quaternion.
*/
setFromEuler(e, t = !0) {
const i = e._x, s = e._y, n = e._z, a = e._order, o = Math.cos, l = Math.sin, c = o(i / 2), h = o(s / 2), u = o(n / 2), d = l(i / 2), f = l(s / 2), g = l(n / 2);
switch (a) {
case "XYZ":
this._x = d * h * u + c * f * g, this._y = c * f * u - d * h * g, this._z = c * h * g + d * f * u, this._w = c * h * u - d * f * g;
break;
case "YXZ":
this._x = d * h * u + c * f * g, this._y = c * f * u - d * h * g, this._z = c * h * g - d * f * u, this._w = c * h * u + d * f * g;
break;
case "ZXY":
this._x = d * h * u - c * f * g, this._y = c * f * u + d * h * g, this._z = c * h * g + d * f * u, this._w = c * h * u - d * f * g;
break;
case "ZYX":
this._x = d * h * u - c * f * g, this._y = c * f * u + d * h * g, this._z = c * h * g - d * f * u, this._w = c * h * u + d * f * g;
break;
case "YZX":
this._x = d * h * u + c * f * g, this._y = c * f * u + d * h * g, this._z = c * h * g - d * f * u, this._w = c * h * u - d * f * g;
break;
case "XZY":
this._x = d * h * u - c * f * g, this._y = c * f * u - d * h * g, this._z = c * h * g + d * f * u, this._w = c * h * u + d * f * g;
break;
default:
Se("Quaternion: .setFromEuler() encountered an unknown order: " + a);
}
return t === !0 && this._onChangeCallback(), this;
}
/**
* Sets this quaternion from the given axis and angle.
*
* @param {Vector3} axis - The normalized axis.
* @param {number} angle - The angle in radians.
* @return {Quaternion} A reference to this quaternion.
*/
setFromAxisAngle(e, t) {
const i = t / 2, s = Math.sin(i);
return this._x = e.x * s, this._y = e.y * s, this._z = e.z * s, this._w = Math.cos(i), this._onChangeCallback(), this;
}
/**
* Sets this quaternion from the given rotation matrix.
*
* @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
* @return {Quaternion} A reference to this quaternion.
*/
setFromRotationMatrix(e) {
const t = e.elements, i = t[0], s = t[4], n = t[8], a = t[1], o = t[5], l = t[9], c = t[2], h = t[6], u = t[10], d = i + o + u;
if (d > 0) {
const f = 0.5 / Math.sqrt(d + 1);
this._w = 0.25 / f, this._x = (h - l) * f, this._y = (n - c) * f, this._z = (a - s) * f;
} else if (i > o && i > u) {
const f = 2 * Math.sqrt(1 + i - o - u);
this._w = (h - l) / f, this._x = 0.25 * f, this._y = (s + a) / f, this._z = (n + c) / f;
} else if (o > u) {
const f = 2 * Math.sqrt(1 + o - i - u);
this._w = (n - c) / f, this._x = (s + a) / f, this._y = 0.25 * f, this._z = (l + h) / f;
} else {
const f = 2 * Math.sqrt(1 + u - i - o);
this._w = (a - s) / f, this._x = (n + c) / f, this._y = (l + h) / f, this._z = 0.25 * f;
}
return this._onChangeCallback(), this;
}
/**
* Sets this quaternion to the rotation required to rotate the direction vector
* `vFrom` to the direction vector `vTo`.
*
* @param {Vector3} vFrom - The first (normalized) direction vector.
* @param {Vector3} vTo - The second (normalized) direction vector.
* @return {Quaternion} A reference to this quaternion.
*/
setFromUnitVectors(e, t) {
let i = e.dot(t) + 1;
return i < 1e-8 ? (i = 0, Math.abs(e.x) > Math.abs(e.z) ? (this._x = -e.y, this._y = e.x, this._z = 0, this._w = i) : (this._x = 0, this._y = -e.z, this._z = e.y, this._w = i)) : (this._x = e.y * t.z - e.z * t.y, this._y = e.z * t.x - e.x * t.z, this._z = e.x * t.y - e.y * t.x, this._w = i), this.normalize();
}
/**
* Returns the angle between this quaternion and the given one in radians.
*
* @param {Quaternion} q - The quaternion to compute the angle with.
* @return {number} The angle in radians.
*/
angleTo(e) {
return 2 * Math.acos(Math.abs(ze(this.dot(e), -1, 1)));
}
/**
* Rotates this quaternion by a given angular step to the given quaternion.
* The method ensures that the final quaternion will not overshoot `q`.
*
* @param {Quaternion} q - The target quaternion.
* @param {number} step - The angular step in radians.
* @return {Quaternion} A reference to this quaternion.
*/
rotateTowards(e, t) {
const i = this.angleTo(e);
if (i === 0) return this;
const s = Math.min(1, t / i);
return this.slerp(e, s), this;
}
/**
* Sets this quaternion to the identity quaternion; that is, to the
* quaternion that represents "no rotation".
*
* @return {Quaternion} A reference to this quaternion.
*/
identity() {
return this.set(0, 0, 0, 1);
}
/**
* Inverts this quaternion via {@link Quaternion#conjugate}. The
* quaternion is assumed to have unit length.
*
* @return {Quaternion} A reference to this quaternion.
*/
invert() {
return this.conjugate();
}
/**
* Returns the rotational conjugate of this quaternion. The conjugate of a
* quaternion represents the same rotation in the opposite direction about
* the rotational axis.
*
* @return {Quaternion} A reference to this quaternion.
*/
conjugate() {
return this._x *= -1, this._y *= -1, this._z *= -1, this._onChangeCallback(), this;
}
/**
* Calculates the dot product of this quaternion and the given one.
*
* @param {Quaternion} v - The quaternion to compute the dot product with.
* @return {number} The result of the dot product.
*/
dot(e) {
return this._x * e._x + this._y * e._y + this._z * e._z + this._w * e._w;
}
/**
* Computes the squared Euclidean length (straight-line length) of this quaternion,
* considered as a 4 dimensional vector. This can be useful if you are comparing the
* lengths of two quaternions, as this is a slightly more efficient calculation than
* {@link Quaternion#length}.
*
* @return {number} The squared Euclidean length.
*/
lengthSq() {
return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
}
/**
* Computes the Euclidean length (straight-line length) of this quaternion,
* considered as a 4 dimensional vector.
*
* @return {number} The Euclidean length.
*/
length() {
return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
}
/**
* Normalizes this quaternion - that is, calculated the quaternion that performs
* the same rotation as this one, but has a length equal to `1`.
*
* @return {Quaternion} A reference to this quaternion.
*/
normalize() {
let e = this.length();
return e === 0 ? (this._x = 0, this._y = 0, this._z = 0, this._w = 1) : (e = 1 / e, this._x = this._x * e, this._y = this._y * e, this._z = this._z * e, this._w = this._w * e), this._onChangeCallback(), this;
}
/**
* Multiplies this quaternion by the given one.
*
* @param {Quaternion} q - The quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
multiply(e) {
return this.multiplyQuaternions(this, e);
}
/**
* Pre-multiplies this quaternion by the given one.
*
* @param {Quaternion} q - The quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
premultiply(e) {
return this.multiplyQuaternions(e, this);
}
/**
* Multiplies the given quaternions and stores the result in this instance.
*
* @param {Quaternion} a - The first quaternion.
* @param {Quaternion} b - The second quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
multiplyQuaternions(e, t) {
const i = e._x, s = e._y, n = e._z, a = e._w, o = t._x, l = t._y, c = t._z, h = t._w;
return this._x = i * h + a * o + s * c - n * l, this._y = s * h + a * l + n * o - i * c, this._z = n * h + a * c + i * l - s * o, this._w = a * h - i * o - s * l - n * c, this._onChangeCallback(), this;
}
/**
* Performs a spherical linear interpolation between quaternions.
*
* @param {Quaternion} qb - The target quaternion.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {Quaternion} A reference to this quaternion.
*/
slerp(e, t) {
if (t <= 0) return this;
if (t >= 1) return this.copy(e);
let i = e._x, s = e._y, n = e._z, a = e._w, o = this.dot(e);
o < 0 && (i = -i, s = -s, n = -n, a = -a, o = -o);
let l = 1 - t;
if (o < 0.9995) {
const c = Math.acos(o), h = Math.sin(c);
l = Math.sin(l * c) / h, t = Math.sin(t * c) / h, this._x = this._x * l + i * t, this._y = this._y * l + s * t, this._z = this._z * l + n * t, this._w = this._w * l + a * t, this._onChangeCallback();
} else
this._x = this._x * l + i * t, this._y = this._y * l + s * t, this._z = this._z * l + n * t, this._w = this._w * l + a * t, this.normalize();
return this;
}
/**
* Performs a spherical linear interpolation between the given quaternions
* and stores the result in this quaternion.
*
* @param {Quaternion} qa - The source quaternion.
* @param {Quaternion} qb - The target quaternion.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {Quaternion} A reference to this quaternion.
*/
slerpQuaternions(e, t, i) {
return this.copy(e).slerp(t, i);
}
/**
* Sets this quaternion to a uniformly random, normalized quaternion.
*
* @return {Quaternion} A reference to this quaternion.
*/
random() {
const e = 2 * Math.PI * Math.random(), t = 2 * Math.PI * Math.random(), i = Math.random(), s = Math.sqrt(1 - i), n = Math.sqrt(i);
return this.set(
s * Math.sin(e),
s * Math.cos(e),
n * Math.sin(t),
n * Math.cos(t)
);
}
/**
* Returns `true` if this quaternion is equal with the given one.
*
* @param {Quaternion} quaternion - The quaternion to test for equality.
* @return {boolean} Whether this quaternion is equal with the given one.
*/
equals(e) {
return e._x === this._x && e._y === this._y && e._z === this._z && e._w === this._w;
}
/**
* Sets this quaternion's components from the given array.
*
* @param {Array} array - An array holding the quaternion component values.
* @param {number} [offset=0] - The offset into the array.
* @return {Quaternion} A reference to this quaternion.
*/
fromArray(e, t = 0) {
return this._x = e[t], this._y = e[t + 1], this._z = e[t + 2], this._w = e[t + 3], this._onChangeCallback(), this;
}
/**
* Writes the components of this quaternion to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the quaternion components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The quaternion components.
*/
toArray(e = [], t = 0) {
return e[t] = this._x, e[t + 1] = this._y, e[t + 2] = this._z, e[t + 3] = this._w, e;
}
/**
* Sets the components of this quaternion from the given buffer attribute.
*
* @param {BufferAttribute} attribute - The buffer attribute holding quaternion data.
* @param {number} index - The index into the attribute.
* @return {Quaternion} A reference to this quaternion.
*/
fromBufferAttribute(e, t) {
return this._x = e.getX(t), this._y = e.getY(t), this._z = e.getZ(t), this._w = e.getW(t), this._onChangeCallback(), this;
}
/**
* This methods defines the serialization result of this class. Returns the
* numerical elements of this quaternion in an array of format `[x, y, z, w]`.
*
* @return {Array} The serialized quaternion.
*/
toJSON() {
return this.toArray();
}
_onChange(e) {
return this._onChangeCallback = e, this;
}
_onChangeCallback() {
}
*[Symbol.iterator]() {
yield this._x, yield this._y, yield this._z, yield this._w;
}
}
class w {
/**
* Constructs a new 3D vector.
*
* @param {number} [x=0] - The x value of this vector.
* @param {number} [y=0] - The y value of this vector.
* @param {number} [z=0] - The z value of this vector.
*/
constructor(e = 0, t = 0, i = 0) {
w.prototype.isVector3 = !0, this.x = e, this.y = t, this.z = i;
}
/**
* Sets the vector components.
*
* @param {number} x - The value of the x component.
* @param {number} y - The value of the y component.
* @param {number} z - The value of the z component.
* @return {Vector3} A reference to this vector.
*/
set(e, t, i) {
return i === void 0 && (i = this.z), this.x = e, this.y = t, this.z = i, this;
}
/**
* Sets the vector components to the same value.
*
* @param {number} scalar - The value to set for all vector components.
* @return {Vector3} A reference to this vector.
*/
setScalar(e) {
return this.x = e, this.y = e, this.z = e, this;
}
/**
* Sets the vector's x component to the given value
*
* @param {number} x - The value to set.
* @return {Vector3} A reference to this vector.
*/
setX(e) {
return this.x = e, this;
}
/**
* Sets the vector's y component to the given value
*
* @param {number} y - The value to set.
* @return {Vector3} A reference to this vector.
*/
setY(e) {
return this.y = e, this;
}
/**
* Sets the vector's z component to the given value
*
* @param {number} z - The value to set.
* @return {Vector3} A reference to this vector.
*/
setZ(e) {
return this.z = e, this;
}
/**
* Allows to set a vector component with an index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
* @param {number} value - The value to set.
* @return {Vector3} A reference to this vector.
*/
setComponent(e, t) {
switch (e) {
case 0:
this.x = t;
break;
case 1:
this.y = t;
break;
case 2:
this.z = t;
break;
default:
throw new Error("index is out of range: " + e);
}
return this;
}
/**
* Returns the value of the vector component which matches the given index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
* @return {number} A vector component value.
*/
getComponent(e) {
switch (e) {
case 0:
return this.x;
case 1:
return this.y;
case 2:
return this.z;
default:
throw new Error("index is out of range: " + e);
}
}
/**
* Returns a new vector with copied values from this instance.
*
* @return {Vector3} A clone of this instance.
*/
clone() {
return new this.constructor(this.x, this.y, this.z);
}
/**
* Copies the values of the given vector to this instance.
*
* @param {Vector3} v - The vector to copy.
* @return {Vector3} A reference to this vector.
*/
copy(e) {
return this.x = e.x, this.y = e.y, this.z = e.z, this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector3} v - The vector to add.
* @return {Vector3} A reference to this vector.
*/
add(e) {
return this.x += e.x, this.y += e.y, this.z += e.z, this;
}
/**
* Adds the given scalar value to all components of this instance.
*
* @param {number} s - The scalar to add.
* @return {Vector3} A reference to this vector.
*/
addScalar(e) {
return this.x += e, this.y += e, this.z += e, this;
}
/**
* Adds the given vectors and stores the result in this instance.
*
* @param {Vector3} a - The first vector.
* @param {Vector3} b - The second vector.
* @return {Vector3} A reference to this vector.
*/
addVectors(e, t) {
return this.x = e.x + t.x, this.y = e.y + t.y, this.z = e.z + t.z, this;
}
/**
* Adds the given vector scaled by the given factor to this instance.
*
* @param {Vector3|Vector4} v - The vector.
* @param {number} s - The factor that scales `v`.
* @return {Vector3} A reference to this vector.
*/
addScaledVector(e, t) {
return this.x += e.x * t, this.y += e.y * t, this.z += e.z * t, this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector3} v - The vector to subtract.
* @return {Vector3} A reference to this vector.
*/
sub(e) {
return this.x -= e.x, this.y -= e.y, this.z -= e.z, this;
}
/**
* Subtracts the given scalar value from all components of this instance.
*
* @param {number} s - The scalar to subtract.
* @return {Vector3} A reference to this vector.
*/
subScalar(e) {
return this.x -= e, this.y -= e, this.z -= e, this;
}
/**
* Subtracts the given vectors and stores the result in this instance.
*
* @param {Vector3} a - The first vector.
* @param {Vector3} b - The second vector.
* @return {Vector3} A reference to this vector.
*/
subVectors(e, t) {
return this.x = e.x - t.x, this.y = e.y - t.y, this.z = e.z - t.z, this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector3} v - The vector to multiply.
* @return {Vector3} A reference to this vector.
*/
multiply(e) {
return this.x *= e.x, this.y *= e.y, this.z *= e.z, this;
}
/**
* Multiplies the given scalar value with all components of this instance.
*
* @param {number} scalar - The scalar to multiply.
* @return {Vector3} A reference to this vector.
*/
multiplyScalar(e) {
return this.x *= e, this.y *= e, this.z *= e, this;
}
/**
* Multiplies the given vectors and stores the result in this instance.
*
* @param {Vector3} a - The first vector.
* @param {Vector3} b - The second vector.
* @return {Vector3} A reference to this vector.
*/
multiplyVectors(e, t) {
return this.x = e.x * t.x, this.y = e.y * t.y, this.z = e.z * t.z, this;
}
/**
* Applies the given Euler rotation to this vector.
*
* @param {Euler} euler - The Euler angles.
* @return {Vector3} A reference to this vector.
*/
applyEuler(e) {
return this.applyQuaternion(ml.setFromEuler(e));
}
/**
* Applies a rotation specified by an axis and an angle to this vector.
*
* @param {Vector3} axis - A normalized vector representing the rotation axis.
* @param {number} angle - The angle in radians.
* @return {Vector3} A reference to this vector.
*/
applyAxisAngle(e, t) {
return this.applyQuaternion(ml.setFromAxisAngle(e, t));
}
/**
* Multiplies this vector with the given 3x3 matrix.
*
* @param {Matrix3} m - The 3x3 matrix.
* @return {Vector3} A reference to this vector.
*/
applyMatrix3(e) {
const t = this.x, i = this.y, s = this.z, n = e.elements;
return this.x = n[0] * t + n[3] * i + n[6] * s, this.y = n[1] * t + n[4] * i + n[7] * s, this.z = n[2] * t + n[5] * i + n[8] * s, this;
}
/**
* Multiplies this vector by the given normal matrix and normalizes
* the result.
*
* @param {Matrix3} m - The normal matrix.
* @return {Vector3} A reference to this vector.
*/
applyNormalMatrix(e) {
return this.applyMatrix3(e).normalize();
}
/**
* Multiplies this vector (with an implicit 1 in the 4th dimension) by m, and
* divides by perspective.
*
* @param {Matrix4} m - The matrix to apply.
* @return {Vector3} A reference to this vector.
*/
applyMatrix4(e) {
const t = this.x, i = this.y, s = this.z, n = e.elements, a = 1 / (n[3] * t + n[7] * i + n[11] * s + n[15]);
return this.x = (n[0] * t + n[4] * i + n[8] * s + n[12]) * a, this.y = (n[1] * t + n[5] * i + n[9] * s + n[13]) * a, this.z = (n[2] * t + n[6] * i + n[10] * s + n[14]) * a, this;
}
/**
* Applies the given Quaternion to this vector.
*
* @param {Quaternion} q - The Quaternion.
* @return {Vector3} A reference to this vector.
*/
applyQuaternion(e) {
const t = this.x, i = this.y, s = this.z, n = e.x, a = e.y, o = e.z, l = e.w, c = 2 * (a * s - o * i), h = 2 * (o * t - n * s), u = 2 * (n * i - a * t);
return this.x = t + l * c + a * u - o * h, this.y = i + l * h + o * c - n * u, this.z = s + l * u + n * h - a * c, this;
}
/**
* Projects this vector from world space into the camera's normalized
* device coordinate (NDC) space.
*
* @param {Camera} camera - The camera.
* @return {Vector3} A reference to this vector.
*/
project(e) {
return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix);
}
/**
* Unprojects this vector from the camera's normalized device coordinate (NDC)
* space into world space.
*
* @param {Camera} camera - The camera.
* @return {Vector3} A reference to this vector.
*/
unproject(e) {
return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld);
}
/**
* Transforms the direction of this vector by a matrix (the upper left 3 x 3
* subset of the given 4x4 matrix and then normalizes the result.
*
* @param {Matrix4} m - The matrix.
* @return {Vector3} A reference to this vector.
*/
transformDirection(e) {
const t = this.x, i = this.y, s = this.z, n = e.elements;
return this.x = n[0] * t + n[4] * i + n[8] * s, this.y = n[1] * t + n[5] * i + n[9] * s, this.z = n[2] * t + n[6] * i + n[10] * s, this.normalize();
}
/**
* Divides this instance by the given vector.
*
* @param {Vector3} v - The vector to divide.
* @return {Vector3} A reference to this vector.
*/
divide(e) {
return this.x /= e.x, this.y /= e.y, this.z /= e.z, this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector3} A reference to this vector.
*/
divideScalar(e) {
return this.multiplyScalar(1 / e);
}
/**
* If this vector's x, y or z value is greater than the given vector's x, y or z
* value, replace that value with the corresponding min value.
*
* @param {Vector3} v - The vector.
* @return {Vector3} A reference to this vector.
*/
min(e) {
return this.x = Math.min(this.x, e.x), this.y = Math.min(this.y, e.y), this.z = Math.min(this.z, e.z), this;
}
/**
* If this vector's x, y or z value is less than the given vector's x, y or z
* value, replace that value with the corresponding max value.
*
* @param {Vector3} v - The vector.
* @return {Vector3} A reference to this vector.
*/
max(e) {
return this.x = Math.max(this.x, e.x), this.y = Math.max(this.y, e.y), this.z = Math.max(this.z, e.z), this;
}
/**
* If this vector's x, y or z value is greater than the max vector's x, y or z
* value, it is replaced by the corresponding value.
* If this vector's x, y or z value is less than the min vector's x, y or z value,
* it is replaced by the corresponding value.
*
* @param {Vector3} min - The minimum x, y and z values.
* @param {Vector3} max - The maximum x, y and z values in the desired range.
* @return {Vector3} A reference to this vector.
*/
clamp(e, t) {
return this.x = ze(this.x, e.x, t.x), this.y = ze(this.y, e.y, t.y), this.z = ze(this.z, e.z, t.z), this;
}
/**
* If this vector's x, y or z values are greater than the max value, they are
* replaced by the max value.
* If this vector's x, y or z values are less than the min value, they are
* replaced by the min value.
*
* @param {number} minVal - The minimum value the components will be clamped to.
* @param {number} maxVal - The maximum value the components will be clamped to.
* @return {Vector3} A reference to this vector.
*/
clampScalar(e, t) {
return this.x = ze(this.x, e, t), this.y = ze(this.y, e, t), this.z = ze(this.z, e, t), this;
}
/**
* If this vector's length is greater than the max value, it is replaced by
* the max value.
* If this vector's length is less than the min value, it is replaced by the
* min value.
*
* @param {number} min - The minimum value the vector length will be clamped to.
* @param {number} max - The maximum value the vector length will be clamped to.
* @return {Vector3} A reference to this vector.
*/
clampLength(e, t) {
const i = this.length();
return this.divideScalar(i || 1).multiplyScalar(ze(i, e, t));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector3} A reference to this vector.
*/
floor() {
return this.x = Math.floor(this.x), this.y = Math.floor(this.y), this.z = Math.floor(this.z), this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector3} A reference to this vector.
*/
ceil() {
return this.x = Math.ceil(this.x), this.y = Math.ceil(this.y), this.z = Math.ceil(this.z), this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector3} A reference to this vector.
*/
round() {
return this.x = Math.round(this.x), this.y = Math.round(this.y), this.z = Math.round(this.z), this;
}
/**
* The components of this vector are rounded towards zero (up if negative,
* down if positive) to an integer value.
*
* @return {Vector3} A reference to this vector.
*/
roundToZero() {
return this.x = Math.trunc(this.x), this.y = Math.trunc(this.y), this.z = Math.trunc(this.z), this;
}
/**
* Inverts this vector - i.e. sets x = -x, y = -y and z = -z.
*
* @return {Vector3} A reference to this vector.
*/
negate() {
return this.x = -this.x, this.y = -this.y, this.z = -this.z, this;
}
/**
* Calculates the dot product of the given vector with this instance.
*
* @param {Vector3} v - The vector to compute the dot product with.
* @return {number} The result of the dot product.
*/
dot(e) {
return this.x * e.x + this.y * e.y + this.z * e.z;
}
// TODO lengthSquared?
/**
* Computes the square of the Euclidean length (straight-line length) from
* (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should
* compare the length squared instead as it is slightly more efficient to calculate.
*
* @return {number} The square length of this vector.
*/
lengthSq() {
return this.x * this.x + this.y * this.y + this.z * this.z;
}
/**
* Computes the Euclidean length (straight-line length) from (0, 0, 0) to (x, y, z).
*
* @return {number} The length of this vector.
*/
length() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
/**
* Computes the Manhattan length of this vector.
*
* @return {number} The length of this vector.
*/
manhattanLength() {
return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
}
/**
* Converts this vector to a unit vector - that is, sets it equal to a vector
* with the same direction as this one, but with a vector length of `1`.
*
* @return {Vector3} A reference to this vector.
*/
normalize() {
return this.divideScalar(this.length() || 1);
}
/**
* Sets this vector to a vector with the same direction as this one, but
* with the specified length.
*
* @param {number} length - The new length of this vector.
* @return {Vector3} A reference to this vector.
*/
setLength(e) {
return this.normalize().multiplyScalar(e);
}
/**
* Linearly interpolates between the given vector and this instance, where
* alpha is the percent distance along the line - alpha = 0 will be this
* vector, and alpha = 1 will be the given one.
*
* @param {Vector3} v - The vector to interpolate towards.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector3} A reference to this vector.
*/
lerp(e, t) {
return this.x += (e.x - this.x) * t, this.y += (e.y - this.y) * t, this.z += (e.z - this.z) * t, this;
}
/**
* Linearly interpolates between the given vectors, where alpha is the percent
* distance along the line - alpha = 0 will be first vector, and alpha = 1 will
* be the second one. The result is stored in this instance.
*
* @param {Vector3} v1 - The first vector.
* @param {Vector3} v2 - The second vector.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector3} A reference to this vector.
*/
lerpVectors(e, t, i) {
return this.x = e.x + (t.x - e.x) * i, this.y = e.y + (t.y - e.y) * i, this.z = e.z + (t.z - e.z) * i, this;
}
/**
* Calculates the cross product of the given vector with this instance.
*
* @param {Vector3} v - The vector to compute the cross product with.
* @return {Vector3} The result of the cross product.
*/
cross(e) {
return this.crossVectors(this, e);
}
/**
* Calculates the cross product of the given vectors and stores the result
* in this instance.
*
* @param {Vector3} a - The first vector.
* @param {Vector3} b - The second vector.
* @return {Vector3} A reference to this vector.
*/
crossVectors(e, t) {
const i = e.x, s = e.y, n = e.z, a = t.x, o = t.y, l = t.z;
return this.x = s * l - n * o, this.y = n * a - i * l, this.z = i * o - s * a, this;
}
/**
* Projects this vector onto the given one.
*
* @param {Vector3} v - The vector to project to.
* @return {Vector3} A reference to this vector.
*/
projectOnVector(e) {
const t = e.lengthSq();
if (t === 0) return this.set(0, 0, 0);
const i = e.dot(this) / t;
return this.copy(e).multiplyScalar(i);
}
/**
* Projects this vector onto a plane by subtracting this
* vector projected onto the plane's normal from this vector.
*
* @param {Vector3} planeNormal - The plane normal.
* @return {Vector3} A reference to this vector.
*/
projectOnPlane(e) {
return zn.copy(this).projectOnVector(e), this.sub(zn);
}
/**
* Reflects this vector off a plane orthogonal to the given normal vector.
*
* @param {Vector3} normal - The (normalized) normal vector.
* @return {Vector3} A reference to this vector.
*/
reflect(e) {
return this.sub(zn.copy(e).multiplyScalar(2 * this.dot(e)));
}
/**
* Returns the angle between the given vector and this instance in radians.
*
* @param {Vector3} v - The vector to compute the angle with.
* @return {number} The angle in radians.
*/
angleTo(e) {
const t = Math.sqrt(this.lengthSq() * e.lengthSq());
if (t === 0) return Math.PI / 2;
const i = this.dot(e) / t;
return Math.acos(ze(i, -1, 1));
}
/**
* Computes the distance from the given vector to this instance.
*
* @param {Vector3} v - The vector to compute the distance to.
* @return {number} The distance.
*/
distanceTo(e) {
return Math.sqrt(this.distanceToSquared(e));
}
/**
* Computes the squared distance from the given vector to this instance.
* If you are just comparing the distance with another distance, you should compare
* the distance squared instead as it is slightly more efficient to calculate.
*
* @param {Vector3} v - The vector to compute the squared distance to.
* @return {number} The squared distance.
*/
distanceToSquared(e) {
const t = this.x - e.x, i = this.y - e.y, s = this.z - e.z;
return t * t + i * i + s * s;
}
/**
* Computes the Manhattan distance from the given vector to this instance.
*
* @param {Vector3} v - The vector to compute the Manhattan distance to.
* @return {number} The Manhattan distance.
*/
manhattanDistanceTo(e) {
return Math.abs(this.x - e.x) + Math.abs(this.y - e.y) + Math.abs(this.z - e.z);
}
/**
* Sets the vector components from the given spherical coordinates.
*
* @param {Spherical} s - The spherical coordinates.
* @return {Vector3} A reference to this vector.
*/
setFromSpherical(e) {
return this.setFromSphericalCoords(e.radius, e.phi, e.theta);
}
/**
* Sets the vector components from the given spherical coordinates.
*
* @param {number} radius - The radius.
* @param {number} phi - The phi angle in radians.
* @param {number} theta - The theta angle in radians.
* @return {Vector3} A reference to this vector.
*/
setFromSphericalCoords(e, t, i) {
const s = Math.sin(t) * e;
return this.x = s * Math.sin(i), this.y = Math.cos(t) * e, this.z = s * Math.cos(i), this;
}
/**
* Sets the vector components from the given cylindrical coordinates.
*
* @param {Cylindrical} c - The cylindrical coordinates.
* @return {Vector3} A reference to this vector.
*/
setFromCylindrical(e) {
return this.setFromCylindricalCoords(e.radius, e.theta, e.y);
}
/**
* Sets the vector components from the given cylindrical coordinates.
*
* @param {number} radius - The radius.
* @param {number} theta - The theta angle in radians.
* @param {number} y - The y value.
* @return {Vector3} A reference to this vector.
*/
setFromCylindricalCoords(e, t, i) {
return this.x = e * Math.sin(t), this.y = i, this.z = e * Math.cos(t), this;
}
/**
* Sets the vector components to the position elements of the
* given transformation matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Vector3} A reference to this vector.
*/
setFromMatrixPosition(e) {
const t = e.elements;
return this.x = t[12], this.y = t[13], this.z = t[14], this;
}
/**
* Sets the vector components to the scale elements of the
* given transformation matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Vector3} A reference to this vector.
*/
setFromMatrixScale(e) {
const t = this.setFromMatrixColumn(e, 0).length(), i = this.setFromMatrixColumn(e, 1).length(), s = this.setFromMatrixColumn(e, 2).length();
return this.x = t, this.y = i, this.z = s, this;
}
/**
* Sets the vector components from the specified matrix column.
*
* @param {Matrix4} m - The 4x4 matrix.
* @param {number} index - The column index.
* @return {Vector3} A reference to this vector.
*/
setFromMatrixColumn(e, t) {
return this.fromArray(e.elements, t * 4);
}
/**
* Sets the vector components from the specified matrix column.
*
* @param {Matrix3} m - The 3x3 matrix.
* @param {number} index - The column index.
* @return {Vector3} A reference to this vector.
*/
setFromMatrix3Column(e, t) {
return this.fromArray(e.elements, t * 3);
}
/**
* Sets the vector components from the given Euler angles.
*
* @param {Euler} e - The Euler angles to set.
* @return {Vector3} A reference to this vector.
*/
setFromEuler(e) {
return this.x = e._x, this.y = e._y, this.z = e._z, this;
}
/**
* Sets the vector components from the RGB components of the
* given color.
*
* @param {Color} c - The color to set.
* @return {Vector3} A reference to this vector.
*/
setFromColor(e) {
return this.x = e.r, this.y = e.g, this.z = e.b, this;
}
/**
* Returns `true` if this vector is equal with the given one.
*
* @param {Vector3} v - The vector to test for equality.
* @return {boolean} Whether this vector is equal with the given one.
*/
equals(e) {
return e.x === this.x && e.y === this.y && e.z === this.z;
}
/**
* Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`
* and z value to be `array[ offset + 2 ]`.
*
* @param {Array} array - An array holding the vector component values.
* @param {number} [offset=0] - The offset into the array.
* @return {Vector3} A reference to this vector.
*/
fromArray(e, t = 0) {
return this.x = e[t], this.y = e[t + 1], this.z = e[t + 2], this;
}
/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The vector components.
*/
toArray(e = [], t = 0) {
return e[t] = this.x, e[t + 1] = this.y, e[t + 2] = this.z, e;
}
/**
* Sets the components of this vector from the given buffer attribute.
*
* @param {BufferAttribute} attribute - The buffer attribute holding vector data.
* @param {number} index - The index into the attribute.
* @return {Vector3} A reference to this vector.
*/
fromBufferAttribute(e, t) {
return this.x = e.getX(t), this.y = e.getY(t), this.z = e.getZ(t), this;
}
/**
* Sets each component of this vector to a pseudo-random value between `0` and
* `1`, excluding `1`.
*
* @return {Vector3} A reference to this vector.
*/
random() {
return this.x = Math.random(), this.y = Math.random(), this.z = Math.random(), this;
}
/**
* Sets this vector to a uniformly random point on a unit sphere.
*
* @return {Vector3} A reference to this vector.
*/
randomDirection() {
const e = Math.random() * Math.PI * 2, t = Math.random() * 2 - 1, i = Math.sqrt(1 - t * t);
return this.x = i * Math.cos(e), this.y = t, this.z = i * Math.sin(e), this;
}
*[Symbol.iterator]() {
yield this.x, yield this.y, yield this.z;
}
}
const zn = /* @__PURE__ */ new w(), ml = /* @__PURE__ */ new mi();
class Be {
/**
* Constructs a new 3x3 matrix. The arguments are supposed to be
* in row-major order. If no arguments are provided, the constructor
* initializes the matrix as an identity matrix.
*
* @param {number} [n11] - 1-1 matrix element.
* @param {number} [n12] - 1-2 matrix element.
* @param {number} [n13] - 1-3 matrix element.
* @param {number} [n21] - 2-1 matrix element.
* @param {number} [n22] - 2-2 matrix element.
* @param {number} [n23] - 2-3 matrix element.
* @param {number} [n31] - 3-1 matrix element.
* @param {number} [n32] - 3-2 matrix element.
* @param {number} [n33] - 3-3 matrix element.
*/
constructor(e, t, i, s, n, a, o, l, c) {
Be.prototype.isMatrix3 = !0, this.elements = [
1,
0,
0,
0,
1,
0,
0,
0,
1
], e !== void 0 && this.set(e, t, i, s, n, a, o, l, c);
}
/**
* Sets the elements of the matrix.The arguments are supposed to be
* in row-major order.
*
* @param {number} [n11] - 1-1 matrix element.
* @param {number} [n12] - 1-2 matrix element.
* @param {number} [n13] - 1-3 matrix element.
* @param {number} [n21] - 2-1 matrix element.
* @param {number} [n22] - 2-2 matrix element.
* @param {number} [n23] - 2-3 matrix element.
* @param {number} [n31] - 3-1 matrix element.
* @param {number} [n32] - 3-2 matrix element.
* @param {number} [n33] - 3-3 matrix element.
* @return {Matrix3} A reference to this matrix.
*/
set(e, t, i, s, n, a, o, l, c) {
const h = this.elements;
return h[0] = e, h[1] = s, h[2] = o, h[3] = t, h[4] = n, h[5] = l, h[6] = i, h[7] = a, h[8] = c, this;
}
/**
* Sets this matrix to the 3x3 identity matrix.
*
* @return {Matrix3} A reference to this matrix.
*/
identity() {
return this.set(
1,
0,
0,
0,
1,
0,
0,
0,
1
), this;
}
/**
* Copies the values of the given matrix to this instance.
*
* @param {Matrix3} m - The matrix to copy.
* @return {Matrix3} A reference to this matrix.
*/
copy(e) {
const t = this.elements, i = e.elements;
return t[0] = i[0], t[1] = i[1], t[2] = i[2], t[3] = i[3], t[4] = i[4], t[5] = i[5], t[6] = i[6], t[7] = i[7], t[8] = i[8], this;
}
/**
* Extracts the basis of this matrix into the three axis vectors provided.
*
* @param {Vector3} xAxis - The basis's x axis.
* @param {Vector3} yAxis - The basis's y axis.
* @param {Vector3} zAxis - The basis's z axis.
* @return {Matrix3} A reference to this matrix.
*/
extractBasis(e, t, i) {
return e.setFromMatrix3Column(this, 0), t.setFromMatrix3Column(this, 1), i.setFromMatrix3Column(this, 2), this;
}
/**
* Set this matrix to the upper 3x3 matrix of the given 4x4 matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Matrix3} A reference to this matrix.
*/
setFromMatrix4(e) {
const t = e.elements;
return this.set(
t[0],
t[4],
t[8],
t[1],
t[5],
t[9],
t[2],
t[6],
t[10]
), this;
}
/**
* Post-multiplies this matrix by the given 3x3 matrix.
*
* @param {Matrix3} m - The matrix to multiply with.
* @return {Matrix3} A reference to this matrix.
*/
multiply(e) {
return this.multiplyMatrices(this, e);
}
/**
* Pre-multiplies this matrix by the given 3x3 matrix.
*
* @param {Matrix3} m - The matrix to multiply with.
* @return {Matrix3} A reference to this matrix.
*/
premultiply(e) {
return this.multiplyMatrices(e, this);
}
/**
* Multiples the given 3x3 matrices and stores the result
* in this matrix.
*
* @param {Matrix3} a - The first matrix.
* @param {Matrix3} b - The second matrix.
* @return {Matrix3} A reference to this matrix.
*/
multiplyMatrices(e, t) {
const i = e.elements, s = t.elements, n = this.elements, a = i[0], o = i[3], l = i[6], c = i[1], h = i[4], u = i[7], d = i[2], f = i[5], g = i[8], v = s[0], m = s[3], p = s[6], y = s[1], _ = s[4], E = s[7], A = s[2], T = s[5], R = s[8];
return n[0] = a * v + o * y + l * A, n[3] = a * m + o * _ + l * T, n[6] = a * p + o * E + l * R, n[1] = c * v + h * y + u * A, n[4] = c * m + h * _ + u * T, n[7] = c * p + h * E + u * R, n[2] = d * v + f * y + g * A, n[5] = d * m + f * _ + g * T, n[8] = d * p + f * E + g * R, this;
}
/**
* Multiplies every component of the matrix by the given scalar.
*
* @param {number} s - The scalar.
* @return {Matrix3} A reference to this matrix.
*/
multiplyScalar(e) {
const t = this.elements;
return t[0] *= e, t[3] *= e, t[6] *= e, t[1] *= e, t[4] *= e, t[7] *= e, t[2] *= e, t[5] *= e, t[8] *= e, this;
}
/**
* Computes and returns the determinant of this matrix.
*
* @return {number} The determinant.
*/
determinant() {
const e = this.elements, t = e[0], i = e[1], s = e[2], n = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8];
return t * a * h - t * o * c - i * n * h + i * o * l + s * n * c - s * a * l;
}
/**
* Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
* You can not invert with a determinant of zero. If you attempt this, the method produces
* a zero matrix instead.
*
* @return {Matrix3} A reference to this matrix.
*/
invert() {
const e = this.elements, t = e[0], i = e[1], s = e[2], n = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8], u = h * a - o * c, d = o * l - h * n, f = c * n - a * l, g = t * u + i * d + s * f;
if (g === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
const v = 1 / g;
return e[0] = u * v, e[1] = (s * c - h * i) * v, e[2] = (o * i - s * a) * v, e[3] = d * v, e[4] = (h * t - s * l) * v, e[5] = (s * n - o * t) * v, e[6] = f * v, e[7] = (i * l - c * t) * v, e[8] = (a * t - i * n) * v, this;
}
/**
* Transposes this matrix in place.
*
* @return {Matrix3} A reference to this matrix.
*/
transpose() {
let e;
const t = this.elements;
return e = t[1], t[1] = t[3], t[3] = e, e = t[2], t[2] = t[6], t[6] = e, e = t[5], t[5] = t[7], t[7] = e, this;
}
/**
* Computes the normal matrix which is the inverse transpose of the upper
* left 3x3 portion of the given 4x4 matrix.
*
* @param {Matrix4} matrix4 - The 4x4 matrix.
* @return {Matrix3} A reference to this matrix.
*/
getNormalMatrix(e) {
return this.setFromMatrix4(e).invert().transpose();
}
/**
* Transposes this matrix into the supplied array, and returns itself unchanged.
*
* @param {Array} r - An array to store the transposed matrix elements.
* @return {Matrix3} A reference to this matrix.
*/
transposeIntoArray(e) {
const t = this.elements;
return e[0] = t[0], e[1] = t[3], e[2] = t[6], e[3] = t[1], e[4] = t[4], e[5] = t[7], e[6] = t[2], e[7] = t[5], e[8] = t[8], this;
}
/**
* Sets the UV transform matrix from offset, repeat, rotation, and center.
*
* @param {number} tx - Offset x.
* @param {number} ty - Offset y.
* @param {number} sx - Repeat x.
* @param {number} sy - Repeat y.
* @param {number} rotation - Rotation, in radians. Positive values rotate counterclockwise.
* @param {number} cx - Center x of rotation.
* @param {number} cy - Center y of rotation
* @return {Matrix3} A reference to this matrix.
*/
setUvTransform(e, t, i, s, n, a, o) {
const l = Math.cos(n), c = Math.sin(n);
return this.set(
i * l,
i * c,
-i * (l * a + c * o) + a + e,
-s * c,
s * l,
-s * (-c * a + l * o) + o + t,
0,
0,
1
), this;
}
/**
* Scales this matrix with the given scalar values.
*
* @param {number} sx - The amount to scale in the X axis.
* @param {number} sy - The amount to scale in the Y axis.
* @return {Matrix3} A reference to this matrix.
*/
scale(e, t) {
return this.premultiply(kn.makeScale(e, t)), this;
}
/**
* Rotates this matrix by the given angle.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix3} A reference to this matrix.
*/
rotate(e) {
return this.premultiply(kn.makeRotation(-e)), this;
}
/**
* Translates this matrix by the given scalar values.
*
* @param {number} tx - The amount to translate in the X axis.
* @param {number} ty - The amount to translate in the Y axis.
* @return {Matrix3} A reference to this matrix.
*/
translate(e, t) {
return this.premultiply(kn.makeTranslation(e, t)), this;
}
// for 2D Transforms
/**
* Sets this matrix as a 2D translation transform.
*
* @param {number|Vector2} x - The amount to translate in the X axis or alternatively a translation vector.
* @param {number} y - The amount to translate in the Y axis.
* @return {Matrix3} A reference to this matrix.
*/
makeTranslation(e, t) {
return e.isVector2 ? this.set(
1,
0,
e.x,
0,
1,
e.y,
0,
0,
1
) : this.set(
1,
0,
e,
0,
1,
t,
0,
0,
1
), this;
}
/**
* Sets this matrix as a 2D rotational transformation.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix3} A reference to this matrix.
*/
makeRotation(e) {
const t = Math.cos(e), i = Math.sin(e);
return this.set(
t,
-i,
0,
i,
t,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a 2D scale transform.
*
* @param {number} x - The amount to scale in the X axis.
* @param {number} y - The amount to scale in the Y axis.
* @return {Matrix3} A reference to this matrix.
*/
makeScale(e, t) {
return this.set(
e,
0,
0,
0,
t,
0,
0,
0,
1
), this;
}
/**
* Returns `true` if this matrix is equal with the given one.
*
* @param {Matrix3} matrix - The matrix to test for equality.
* @return {boolean} Whether this matrix is equal with the given one.
*/
equals(e) {
const t = this.elements, i = e.elements;
for (let s = 0; s < 9; s++)
if (t[s] !== i[s]) return !1;
return !0;
}
/**
* Sets the elements of the matrix from the given array.
*
* @param {Array} array - The matrix elements in column-major order.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Matrix3} A reference to this matrix.
*/
fromArray(e, t = 0) {
for (let i = 0; i < 9; i++)
this.elements[i] = e[i + t];
return this;
}
/**
* Writes the elements of this matrix to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the matrix elements in column-major order.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The matrix elements in column-major order.
*/
toArray(e = [], t = 0) {
const i = this.elements;
return e[t] = i[0], e[t + 1] = i[1], e[t + 2] = i[2], e[t + 3] = i[3], e[t + 4] = i[4], e[t + 5] = i[5], e[t + 6] = i[6], e[t + 7] = i[7], e[t + 8] = i[8], e;
}
/**
* Returns a matrix with copied values from this instance.
*
* @return {Matrix3} A clone of this instance.
*/
clone() {
return new this.constructor().fromArray(this.elements);
}
}
const kn = /* @__PURE__ */ new Be(), gl = /* @__PURE__ */ new Be().set(
0.4123908,
0.3575843,
0.1804808,
0.212639,
0.7151687,
0.0721923,
0.0193308,
0.1191948,
0.9505322
), vl = /* @__PURE__ */ new Be().set(
3.2409699,
-1.5373832,
-0.4986108,
-0.9692436,
1.8759675,
0.0415551,
0.0556301,
-0.203977,
1.0569715
);
function Xu() {
const r = {
enabled: !0,
workingColorSpace: Ut,
/**
* Implementations of supported color spaces.
*
* Required:
* - primaries: chromaticity coordinates [ rx ry gx gy bx by ]
* - whitePoint: reference white [ x y ]
* - transfer: transfer function (pre-defined)
* - toXYZ: Matrix3 RGB to XYZ transform
* - fromXYZ: Matrix3 XYZ to RGB transform
* - luminanceCoefficients: RGB luminance coefficients
*
* Optional:
* - outputColorSpaceConfig: { drawingBufferColorSpace: ColorSpace, toneMappingMode: 'extended' | 'standard' }
* - workingColorSpaceConfig: { unpackColorSpace: ColorSpace }
*
* Reference:
* - https://www.russellcottrell.com/photo/matrixCalculator.htm
*/
spaces: {},
convert: function(s, n, a) {
return this.enabled === !1 || n === a || !n || !a || (this.spaces[n].transfer === et && (s.r = Hi(s.r), s.g = Hi(s.g), s.b = Hi(s.b)), this.spaces[n].primaries !== this.spaces[a].primaries && (s.applyMatrix3(this.spaces[n].toXYZ), s.applyMatrix3(this.spaces[a].fromXYZ)), this.spaces[a].transfer === et && (s.r = Fr(s.r), s.g = Fr(s.g), s.b = Fr(s.b))), s;
},
workingToColorSpace: function(s, n) {
return this.convert(s, this.workingColorSpace, n);
},
colorSpaceToWorking: function(s, n) {
return this.convert(s, n, this.workingColorSpace);
},
getPrimaries: function(s) {
return this.spaces[s].primaries;
},
getTransfer: function(s) {
return s === Ki ? bn : this.spaces[s].transfer;
},
getToneMappingMode: function(s) {
return this.spaces[s].outputColorSpaceConfig.toneMappingMode || "standard";
},
getLuminanceCoefficients: function(s, n = this.workingColorSpace) {
return s.fromArray(this.spaces[n].luminanceCoefficients);
},
define: function(s) {
Object.assign(this.spaces, s);
},
// Internal APIs
_getMatrix: function(s, n, a) {
return s.copy(this.spaces[n].toXYZ).multiply(this.spaces[a].fromXYZ);
},
_getDrawingBufferColorSpace: function(s) {
return this.spaces[s].outputColorSpaceConfig.drawingBufferColorSpace;
},
_getUnpackColorSpace: function(s = this.workingColorSpace) {
return this.spaces[s].workingColorSpaceConfig.unpackColorSpace;
},
// Deprecated
fromWorkingColorSpace: function(s, n) {
return Cs("ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace()."), r.workingToColorSpace(s, n);
},
toWorkingColorSpace: function(s, n) {
return Cs("ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking()."), r.colorSpaceToWorking(s, n);
}
}, e = [0.64, 0.33, 0.3, 0.6, 0.15, 0.06], t = [0.2126, 0.7152, 0.0722], i = [0.3127, 0.329];
return r.define({
[Ut]: {
primaries: e,
whitePoint: i,
transfer: bn,
toXYZ: gl,
fromXYZ: vl,
luminanceCoefficients: t,
workingColorSpaceConfig: { unpackColorSpace: wt },
outputColorSpaceConfig: { drawingBufferColorSpace: wt }
},
[wt]: {
primaries: e,
whitePoint: i,
transfer: et,
toXYZ: gl,
fromXYZ: vl,
luminanceCoefficients: t,
outputColorSpaceConfig: { drawingBufferColorSpace: wt }
}
}), r;
}
const Xe = /* @__PURE__ */ Xu();
function Hi(r) {
return r < 0.04045 ? r * 0.0773993808 : Math.pow(r * 0.9478672986 + 0.0521327014, 2.4);
}
function Fr(r) {
return r < 31308e-7 ? r * 12.92 : 1.055 * Math.pow(r, 0.41666) - 0.055;
}
let xr;
class qu {
/**
* Returns a data URI containing a representation of the given image.
*
* @param {(HTMLImageElement|HTMLCanvasElement)} image - The image object.
* @param {string} [type='image/png'] - Indicates the image format.
* @return {string} The data URI.
*/
static getDataURL(e, t = "image/png") {
if (/^data:/i.test(e.src) || typeof HTMLCanvasElement > "u")
return e.src;
let i;
if (e instanceof HTMLCanvasElement)
i = e;
else {
xr === void 0 && (xr = ws("canvas")), xr.width = e.width, xr.height = e.height;
const s = xr.getContext("2d");
e instanceof ImageData ? s.putImageData(e, 0, 0) : s.drawImage(e, 0, 0, e.width, e.height), i = xr;
}
return i.toDataURL(t);
}
/**
* Converts the given sRGB image data to linear color space.
*
* @param {(HTMLImageElement|HTMLCanvasElement|ImageBitmap|Object)} image - The image object.
* @return {HTMLCanvasElement|Object} The converted image.
*/
static sRGBToLinear(e) {
if (typeof HTMLImageElement < "u" && e instanceof HTMLImageElement || typeof HTMLCanvasElement < "u" && e instanceof HTMLCanvasElement || typeof ImageBitmap < "u" && e instanceof ImageBitmap) {
const t = ws("canvas");
t.width = e.width, t.height = e.height;
const i = t.getContext("2d");
i.drawImage(e, 0, 0, e.width, e.height);
const s = i.getImageData(0, 0, e.width, e.height), n = s.data;
for (let a = 0; a < n.length; a++)
n[a] = Hi(n[a] / 255) * 255;
return i.putImageData(s, 0, 0), t;
} else if (e.data) {
const t = e.data.slice(0);
for (let i = 0; i < t.length; i++)
t instanceof Uint8Array || t instanceof Uint8ClampedArray ? t[i] = Math.floor(Hi(t[i] / 255) * 255) : t[i] = Hi(t[i]);
return {
data: t,
width: e.width,
height: e.height
};
} else
return Se("ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied."), e;
}
}
let Yu = 0;
class Oo {
/**
* Constructs a new video texture.
*
* @param {any} [data=null] - The data definition of a texture.
*/
constructor(e = null) {
this.isSource = !0, Object.defineProperty(this, "id", { value: Yu++ }), this.uuid = di(), this.data = e, this.dataReady = !0, this.version = 0;
}
/**
* Returns the dimensions of the source into the given target vector.
*
* @param {(Vector2|Vector3)} target - The target object the result is written into.
* @return {(Vector2|Vector3)} The dimensions of the source.
*/
getSize(e) {
const t = this.data;
return typeof HTMLVideoElement < "u" && t instanceof HTMLVideoElement ? e.set(t.videoWidth, t.videoHeight, 0) : t instanceof VideoFrame ? e.set(t.displayHeight, t.displayWidth, 0) : t !== null ? e.set(t.width, t.height, t.depth || 0) : e.set(0, 0, 0), e;
}
/**
* When the property is set to `true`, the engine allocates the memory
* for the texture (if necessary) and triggers the actual texture upload
* to the GPU next time the source is used.
*
* @type {boolean}
* @default false
* @param {boolean} value
*/
set needsUpdate(e) {
e === !0 && this.version++;
}
/**
* Serializes the source into JSON.
*
* @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
* @return {Object} A JSON object representing the serialized source.
* @see {@link ObjectLoader#parse}
*/
toJSON(e) {
const t = e === void 0 || typeof e == "string";
if (!t && e.images[this.uuid] !== void 0)
return e.images[this.uuid];
const i = {
uuid: this.uuid,
url: ""
}, s = this.data;
if (s !== null) {
let n;
if (Array.isArray(s)) {
n = [];
for (let a = 0, o = s.length; a < o; a++)
s[a].isDataTexture ? n.push(Hn(s[a].image)) : n.push(Hn(s[a]));
} else
n = Hn(s);
i.url = n;
}
return t || (e.images[this.uuid] = i), i;
}
}
function Hn(r) {
return typeof HTMLImageElement < "u" && r instanceof HTMLImageElement || typeof HTMLCanvasElement < "u" && r instanceof HTMLCanvasElement || typeof ImageBitmap < "u" && r instanceof ImageBitmap ? qu.getDataURL(r) : r.data ? {
data: Array.from(r.data),
width: r.width,
height: r.height,
type: r.data.constructor.name
} : (Se("Texture: Unable to serialize Texture."), {});
}
let Ku = 0;
const Vn = /* @__PURE__ */ new w();
class Ct extends gr {
/**
* Constructs a new texture.
*
* @param {?Object} [image=Texture.DEFAULT_IMAGE] - The image holding the texture data.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {string} [colorSpace=NoColorSpace] - The color space.
*/
constructor(e = Ct.DEFAULT_IMAGE, t = Ct.DEFAULT_MAPPING, i = Jt, s = Jt, n = xt, a = Si, o = qt, l = fi, c = Ct.DEFAULT_ANISOTROPY, h = Ki) {
super(), this.isTexture = !0, Object.defineProperty(this, "id", { value: Ku++ }), this.uuid = di(), this.name = "", this.source = new Oo(e), this.mipmaps = [], this.mapping = t, this.channel = 0, this.wrapS = i, this.wrapT = s, this.magFilter = n, this.minFilter = a, this.anisotropy = c, this.format = o, this.internalFormat = null, this.type = l, this.offset = new oe(0, 0), this.repeat = new oe(1, 1), this.center = new oe(0, 0), this.rotation = 0, this.matrixAutoUpdate = !0, this.matrix = new Be(), this.generateMipmaps = !0, this.premultiplyAlpha = !1, this.flipY = !0, this.unpackAlignment = 4, this.colorSpace = h, this.userData = {}, this.updateRanges = [], this.version = 0, this.onUpdate = null, this.renderTarget = null, this.isRenderTargetTexture = !1, this.isArrayTexture = !!(e && e.depth && e.depth > 1), this.pmremVersion = 0;
}
/**
* The width of the texture in pixels.
*/
get width() {
return this.source.getSize(Vn).x;
}
/**
* The height of the texture in pixels.
*/
get height() {
return this.source.getSize(Vn).y;
}
/**
* The depth of the texture in pixels.
*/
get depth() {
return this.source.getSize(Vn).z;
}
/**
* The image object holding the texture data.
*
* @type {?Object}
*/
get image() {
return this.source.data;
}
set image(e = null) {
this.source.data = e;
}
/**
* Updates the texture transformation matrix from the from the properties {@link Texture#offset},
* {@link Texture#repeat}, {@link Texture#rotation}, and {@link Texture#center}.
*/
updateMatrix() {
this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y);
}
/**
* Adds a range of data in the data texture to be updated on the GPU.
*
* @param {number} start - Position at which to start update.
* @param {number} count - The number of components to update.
*/
addUpdateRange(e, t) {
this.updateRanges.push({ start: e, count: t });
}
/**
* Clears the update ranges.
*/
clearUpdateRanges() {
this.updateRanges.length = 0;
}
/**
* Returns a new texture with copied values from this instance.
*
* @return {Texture} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Copies the values of the given texture to this instance.
*
* @param {Texture} source - The texture to copy.
* @return {Texture} A reference to this instance.
*/
copy(e) {
return this.name = e.name, this.source = e.source, this.mipmaps = e.mipmaps.slice(0), this.mapping = e.mapping, this.channel = e.channel, this.wrapS = e.wrapS, this.wrapT = e.wrapT, this.magFilter = e.magFilter, this.minFilter = e.minFilter, this.anisotropy = e.anisotropy, this.format = e.format, this.internalFormat = e.internalFormat, this.type = e.type, this.offset.copy(e.offset), this.repeat.copy(e.repeat), this.center.copy(e.center), this.rotation = e.rotation, this.matrixAutoUpdate = e.matrixAutoUpdate, this.matrix.copy(e.matrix), this.generateMipmaps = e.generateMipmaps, this.premultiplyAlpha = e.premultiplyAlpha, this.flipY = e.flipY, this.unpackAlignment = e.unpackAlignment, this.colorSpace = e.colorSpace, this.renderTarget = e.renderTarget, this.isRenderTargetTexture = e.isRenderTargetTexture, this.isArrayTexture = e.isArrayTexture, this.userData = JSON.parse(JSON.stringify(e.userData)), this.needsUpdate = !0, this;
}
/**
* Sets this texture's properties based on `values`.
* @param {Object} values - A container with texture parameters.
*/
setValues(e) {
for (const t in e) {
const i = e[t];
if (i === void 0) {
Se(`Texture.setValues(): parameter '${t}' has value of undefined.`);
continue;
}
const s = this[t];
if (s === void 0) {
Se(`Texture.setValues(): property '${t}' does not exist.`);
continue;
}
s && i && s.isVector2 && i.isVector2 || s && i && s.isVector3 && i.isVector3 || s && i && s.isMatrix3 && i.isMatrix3 ? s.copy(i) : this[t] = i;
}
}
/**
* Serializes the texture into JSON.
*
* @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
* @return {Object} A JSON object representing the serialized texture.
* @see {@link ObjectLoader#parse}
*/
toJSON(e) {
const t = e === void 0 || typeof e == "string";
if (!t && e.textures[this.uuid] !== void 0)
return e.textures[this.uuid];
const i = {
metadata: {
version: 4.7,
type: "Texture",
generator: "Texture.toJSON"
},
uuid: this.uuid,
name: this.name,
image: this.source.toJSON(e).uuid,
mapping: this.mapping,
channel: this.channel,
repeat: [this.repeat.x, this.repeat.y],
offset: [this.offset.x, this.offset.y],
center: [this.center.x, this.center.y],
rotation: this.rotation,
wrap: [this.wrapS, this.wrapT],
format: this.format,
internalFormat: this.internalFormat,
type: this.type,
colorSpace: this.colorSpace,
minFilter: this.minFilter,
magFilter: this.magFilter,
anisotropy: this.anisotropy,
flipY: this.flipY,
generateMipmaps: this.generateMipmaps,
premultiplyAlpha: this.premultiplyAlpha,
unpackAlignment: this.unpackAlignment
};
return Object.keys(this.userData).length > 0 && (i.userData = this.userData), t || (e.textures[this.uuid] = i), i;
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*
* @fires Texture#dispose
*/
dispose() {
this.dispatchEvent({ type: "dispose" });
}
/**
* Transforms the given uv vector with the textures uv transformation matrix.
*
* @param {Vector2} uv - The uv vector.
* @return {Vector2} The transformed uv vector.
*/
transformUv(e) {
if (this.mapping !== Xc) return e;
if (e.applyMatrix3(this.matrix), e.x < 0 || e.x > 1)
switch (this.wrapS) {
case Ei:
e.x = e.x - Math.floor(e.x);
break;
case Jt:
e.x = e.x < 0 ? 0 : 1;
break;
case Sn:
Math.abs(Math.floor(e.x) % 2) === 1 ? e.x = Math.ceil(e.x) - e.x : e.x = e.x - Math.floor(e.x);
break;
}
if (e.y < 0 || e.y > 1)
switch (this.wrapT) {
case Ei:
e.y = e.y - Math.floor(e.y);
break;
case Jt:
e.y = e.y < 0 ? 0 : 1;
break;
case Sn:
Math.abs(Math.floor(e.y) % 2) === 1 ? e.y = Math.ceil(e.y) - e.y : e.y = e.y - Math.floor(e.y);
break;
}
return this.flipY && (e.y = 1 - e.y), e;
}
/**
* Setting this property to `true` indicates the engine the texture
* must be updated in the next render. This triggers a texture upload
* to the GPU and ensures correct texture parameter configuration.
*
* @type {boolean}
* @default false
* @param {boolean} value
*/
set needsUpdate(e) {
e === !0 && (this.version++, this.source.needsUpdate = !0);
}
/**
* Setting this property to `true` indicates the engine the PMREM
* must be regenerated.
*
* @type {boolean}
* @default false
* @param {boolean} value
*/
set needsPMREMUpdate(e) {
e === !0 && this.pmremVersion++;
}
}
Ct.DEFAULT_IMAGE = null;
Ct.DEFAULT_MAPPING = Xc;
Ct.DEFAULT_ANISOTROPY = 1;
class Je {
/**
* Constructs a new 4D vector.
*
* @param {number} [x=0] - The x value of this vector.
* @param {number} [y=0] - The y value of this vector.
* @param {number} [z=0] - The z value of this vector.
* @param {number} [w=1] - The w value of this vector.
*/
constructor(e = 0, t = 0, i = 0, s = 1) {
Je.prototype.isVector4 = !0, this.x = e, this.y = t, this.z = i, this.w = s;
}
/**
* Alias for {@link Vector4#z}.
*
* @type {number}
*/
get width() {
return this.z;
}
set width(e) {
this.z = e;
}
/**
* Alias for {@link Vector4#w}.
*
* @type {number}
*/
get height() {
return this.w;
}
set height(e) {
this.w = e;
}
/**
* Sets the vector components.
*
* @param {number} x - The value of the x component.
* @param {number} y - The value of the y component.
* @param {number} z - The value of the z component.
* @param {number} w - The value of the w component.
* @return {Vector4} A reference to this vector.
*/
set(e, t, i, s) {
return this.x = e, this.y = t, this.z = i, this.w = s, this;
}
/**
* Sets the vector components to the same value.
*
* @param {number} scalar - The value to set for all vector components.
* @return {Vector4} A reference to this vector.
*/
setScalar(e) {
return this.x = e, this.y = e, this.z = e, this.w = e, this;
}
/**
* Sets the vector's x component to the given value
*
* @param {number} x - The value to set.
* @return {Vector4} A reference to this vector.
*/
setX(e) {
return this.x = e, this;
}
/**
* Sets the vector's y component to the given value
*
* @param {number} y - The value to set.
* @return {Vector4} A reference to this vector.
*/
setY(e) {
return this.y = e, this;
}
/**
* Sets the vector's z component to the given value
*
* @param {number} z - The value to set.
* @return {Vector4} A reference to this vector.
*/
setZ(e) {
return this.z = e, this;
}
/**
* Sets the vector's w component to the given value
*
* @param {number} w - The value to set.
* @return {Vector4} A reference to this vector.
*/
setW(e) {
return this.w = e, this;
}
/**
* Allows to set a vector component with an index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y,
* `2` equals to z, `3` equals to w.
* @param {number} value - The value to set.
* @return {Vector4} A reference to this vector.
*/
setComponent(e, t) {
switch (e) {
case 0:
this.x = t;
break;
case 1:
this.y = t;
break;
case 2:
this.z = t;
break;
case 3:
this.w = t;
break;
default:
throw new Error("index is out of range: " + e);
}
return this;
}
/**
* Returns the value of the vector component which matches the given index.
*
* @param {number} index - The component index. `0` equals to x, `1` equals to y,
* `2` equals to z, `3` equals to w.
* @return {number} A vector component value.
*/
getComponent(e) {
switch (e) {
case 0:
return this.x;
case 1:
return this.y;
case 2:
return this.z;
case 3:
return this.w;
default:
throw new Error("index is out of range: " + e);
}
}
/**
* Returns a new vector with copied values from this instance.
*
* @return {Vector4} A clone of this instance.
*/
clone() {
return new this.constructor(this.x, this.y, this.z, this.w);
}
/**
* Copies the values of the given vector to this instance.
*
* @param {Vector3|Vector4} v - The vector to copy.
* @return {Vector4} A reference to this vector.
*/
copy(e) {
return this.x = e.x, this.y = e.y, this.z = e.z, this.w = e.w !== void 0 ? e.w : 1, this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector4} v - The vector to add.
* @return {Vector4} A reference to this vector.
*/
add(e) {
return this.x += e.x, this.y += e.y, this.z += e.z, this.w += e.w, this;
}
/**
* Adds the given scalar value to all components of this instance.
*
* @param {number} s - The scalar to add.
* @return {Vector4} A reference to this vector.
*/
addScalar(e) {
return this.x += e, this.y += e, this.z += e, this.w += e, this;
}
/**
* Adds the given vectors and stores the result in this instance.
*
* @param {Vector4} a - The first vector.
* @param {Vector4} b - The second vector.
* @return {Vector4} A reference to this vector.
*/
addVectors(e, t) {
return this.x = e.x + t.x, this.y = e.y + t.y, this.z = e.z + t.z, this.w = e.w + t.w, this;
}
/**
* Adds the given vector scaled by the given factor to this instance.
*
* @param {Vector4} v - The vector.
* @param {number} s - The factor that scales `v`.
* @return {Vector4} A reference to this vector.
*/
addScaledVector(e, t) {
return this.x += e.x * t, this.y += e.y * t, this.z += e.z * t, this.w += e.w * t, this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector4} v - The vector to subtract.
* @return {Vector4} A reference to this vector.
*/
sub(e) {
return this.x -= e.x, this.y -= e.y, this.z -= e.z, this.w -= e.w, this;
}
/**
* Subtracts the given scalar value from all components of this instance.
*
* @param {number} s - The scalar to subtract.
* @return {Vector4} A reference to this vector.
*/
subScalar(e) {
return this.x -= e, this.y -= e, this.z -= e, this.w -= e, this;
}
/**
* Subtracts the given vectors and stores the result in this instance.
*
* @param {Vector4} a - The first vector.
* @param {Vector4} b - The second vector.
* @return {Vector4} A reference to this vector.
*/
subVectors(e, t) {
return this.x = e.x - t.x, this.y = e.y - t.y, this.z = e.z - t.z, this.w = e.w - t.w, this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector4} v - The vector to multiply.
* @return {Vector4} A reference to this vector.
*/
multiply(e) {
return this.x *= e.x, this.y *= e.y, this.z *= e.z, this.w *= e.w, this;
}
/**
* Multiplies the given scalar value with all components of this instance.
*
* @param {number} scalar - The scalar to multiply.
* @return {Vector4} A reference to this vector.
*/
multiplyScalar(e) {
return this.x *= e, this.y *= e, this.z *= e, this.w *= e, this;
}
/**
* Multiplies this vector with the given 4x4 matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Vector4} A reference to this vector.
*/
applyMatrix4(e) {
const t = this.x, i = this.y, s = this.z, n = this.w, a = e.elements;
return this.x = a[0] * t + a[4] * i + a[8] * s + a[12] * n, this.y = a[1] * t + a[5] * i + a[9] * s + a[13] * n, this.z = a[2] * t + a[6] * i + a[10] * s + a[14] * n, this.w = a[3] * t + a[7] * i + a[11] * s + a[15] * n, this;
}
/**
* Divides this instance by the given vector.
*
* @param {Vector4} v - The vector to divide.
* @return {Vector4} A reference to this vector.
*/
divide(e) {
return this.x /= e.x, this.y /= e.y, this.z /= e.z, this.w /= e.w, this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector4} A reference to this vector.
*/
divideScalar(e) {
return this.multiplyScalar(1 / e);
}
/**
* Sets the x, y and z components of this
* vector to the quaternion's axis and w to the angle.
*
* @param {Quaternion} q - The Quaternion to set.
* @return {Vector4} A reference to this vector.
*/
setAxisAngleFromQuaternion(e) {
this.w = 2 * Math.acos(e.w);
const t = Math.sqrt(1 - e.w * e.w);
return t < 1e-4 ? (this.x = 1, this.y = 0, this.z = 0) : (this.x = e.x / t, this.y = e.y / t, this.z = e.z / t), this;
}
/**
* Sets the x, y and z components of this
* vector to the axis of rotation and w to the angle.
*
* @param {Matrix4} m - A 4x4 matrix of which the upper left 3x3 matrix is a pure rotation matrix.
* @return {Vector4} A reference to this vector.
*/
setAxisAngleFromRotationMatrix(e) {
let t, i, s, n;
const a = e.elements, o = a[0], l = a[4], c = a[8], h = a[1], u = a[5], d = a[9], f = a[2], g = a[6], v = a[10];
if (Math.abs(l - h) < 0.01 && Math.abs(c - f) < 0.01 && Math.abs(d - g) < 0.01) {
if (Math.abs(l + h) < 0.1 && Math.abs(c + f) < 0.1 && Math.abs(d + g) < 0.1 && Math.abs(o + u + v - 3) < 0.1)
return this.set(1, 0, 0, 0), this;
t = Math.PI;
const p = (o + 1) / 2, y = (u + 1) / 2, _ = (v + 1) / 2, E = (l + h) / 4, A = (c + f) / 4, T = (d + g) / 4;
return p > y && p > _ ? p < 0.01 ? (i = 0, s = 0.707106781, n = 0.707106781) : (i = Math.sqrt(p), s = E / i, n = A / i) : y > _ ? y < 0.01 ? (i = 0.707106781, s = 0, n = 0.707106781) : (s = Math.sqrt(y), i = E / s, n = T / s) : _ < 0.01 ? (i = 0.707106781, s = 0.707106781, n = 0) : (n = Math.sqrt(_), i = A / n, s = T / n), this.set(i, s, n, t), this;
}
let m = Math.sqrt((g - d) * (g - d) + (c - f) * (c - f) + (h - l) * (h - l));
return Math.abs(m) < 1e-3 && (m = 1), this.x = (g - d) / m, this.y = (c - f) / m, this.z = (h - l) / m, this.w = Math.acos((o + u + v - 1) / 2), this;
}
/**
* Sets the vector components to the position elements of the
* given transformation matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Vector4} A reference to this vector.
*/
setFromMatrixPosition(e) {
const t = e.elements;
return this.x = t[12], this.y = t[13], this.z = t[14], this.w = t[15], this;
}
/**
* If this vector's x, y, z or w value is greater than the given vector's x, y, z or w
* value, replace that value with the corresponding min value.
*
* @param {Vector4} v - The vector.
* @return {Vector4} A reference to this vector.
*/
min(e) {
return this.x = Math.min(this.x, e.x), this.y = Math.min(this.y, e.y), this.z = Math.min(this.z, e.z), this.w = Math.min(this.w, e.w), this;
}
/**
* If this vector's x, y, z or w value is less than the given vector's x, y, z or w
* value, replace that value with the corresponding max value.
*
* @param {Vector4} v - The vector.
* @return {Vector4} A reference to this vector.
*/
max(e) {
return this.x = Math.max(this.x, e.x), this.y = Math.max(this.y, e.y), this.z = Math.max(this.z, e.z), this.w = Math.max(this.w, e.w), this;
}
/**
* If this vector's x, y, z or w value is greater than the max vector's x, y, z or w
* value, it is replaced by the corresponding value.
* If this vector's x, y, z or w value is less than the min vector's x, y, z or w value,
* it is replaced by the corresponding value.
*
* @param {Vector4} min - The minimum x, y and z values.
* @param {Vector4} max - The maximum x, y and z values in the desired range.
* @return {Vector4} A reference to this vector.
*/
clamp(e, t) {
return this.x = ze(this.x, e.x, t.x), this.y = ze(this.y, e.y, t.y), this.z = ze(this.z, e.z, t.z), this.w = ze(this.w, e.w, t.w), this;
}
/**
* If this vector's x, y, z or w values are greater than the max value, they are
* replaced by the max value.
* If this vector's x, y, z or w values are less than the min value, they are
* replaced by the min value.
*
* @param {number} minVal - The minimum value the components will be clamped to.
* @param {number} maxVal - The maximum value the components will be clamped to.
* @return {Vector4} A reference to this vector.
*/
clampScalar(e, t) {
return this.x = ze(this.x, e, t), this.y = ze(this.y, e, t), this.z = ze(this.z, e, t), this.w = ze(this.w, e, t), this;
}
/**
* If this vector's length is greater than the max value, it is replaced by
* the max value.
* If this vector's length is less than the min value, it is replaced by the
* min value.
*
* @param {number} min - The minimum value the vector length will be clamped to.
* @param {number} max - The maximum value the vector length will be clamped to.
* @return {Vector4} A reference to this vector.
*/
clampLength(e, t) {
const i = this.length();
return this.divideScalar(i || 1).multiplyScalar(ze(i, e, t));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector4} A reference to this vector.
*/
floor() {
return this.x = Math.floor(this.x), this.y = Math.floor(this.y), this.z = Math.floor(this.z), this.w = Math.floor(this.w), this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector4} A reference to this vector.
*/
ceil() {
return this.x = Math.ceil(this.x), this.y = Math.ceil(this.y), this.z = Math.ceil(this.z), this.w = Math.ceil(this.w), this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector4} A reference to this vector.
*/
round() {
return this.x = Math.round(this.x), this.y = Math.round(this.y), this.z = Math.round(this.z), this.w = Math.round(this.w), this;
}
/**
* The components of this vector are rounded towards zero (up if negative,
* down if positive) to an integer value.
*
* @return {Vector4} A reference to this vector.
*/
roundToZero() {
return this.x = Math.trunc(this.x), this.y = Math.trunc(this.y), this.z = Math.trunc(this.z), this.w = Math.trunc(this.w), this;
}
/**
* Inverts this vector - i.e. sets x = -x, y = -y, z = -z, w = -w.
*
* @return {Vector4} A reference to this vector.
*/
negate() {
return this.x = -this.x, this.y = -this.y, this.z = -this.z, this.w = -this.w, this;
}
/**
* Calculates the dot product of the given vector with this instance.
*
* @param {Vector4} v - The vector to compute the dot product with.
* @return {number} The result of the dot product.
*/
dot(e) {
return this.x * e.x + this.y * e.y + this.z * e.z + this.w * e.w;
}
/**
* Computes the square of the Euclidean length (straight-line length) from
* (0, 0, 0, 0) to (x, y, z, w). If you are comparing the lengths of vectors, you should
* compare the length squared instead as it is slightly more efficient to calculate.
*
* @return {number} The square length of this vector.
*/
lengthSq() {
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
}
/**
* Computes the Euclidean length (straight-line length) from (0, 0, 0, 0) to (x, y, z, w).
*
* @return {number} The length of this vector.
*/
length() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
}
/**
* Computes the Manhattan length of this vector.
*
* @return {number} The length of this vector.
*/
manhattanLength() {
return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w);
}
/**
* Converts this vector to a unit vector - that is, sets it equal to a vector
* with the same direction as this one, but with a vector length of `1`.
*
* @return {Vector4} A reference to this vector.
*/
normalize() {
return this.divideScalar(this.length() || 1);
}
/**
* Sets this vector to a vector with the same direction as this one, but
* with the specified length.
*
* @param {number} length - The new length of this vector.
* @return {Vector4} A reference to this vector.
*/
setLength(e) {
return this.normalize().multiplyScalar(e);
}
/**
* Linearly interpolates between the given vector and this instance, where
* alpha is the percent distance along the line - alpha = 0 will be this
* vector, and alpha = 1 will be the given one.
*
* @param {Vector4} v - The vector to interpolate towards.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector4} A reference to this vector.
*/
lerp(e, t) {
return this.x += (e.x - this.x) * t, this.y += (e.y - this.y) * t, this.z += (e.z - this.z) * t, this.w += (e.w - this.w) * t, this;
}
/**
* Linearly interpolates between the given vectors, where alpha is the percent
* distance along the line - alpha = 0 will be first vector, and alpha = 1 will
* be the second one. The result is stored in this instance.
*
* @param {Vector4} v1 - The first vector.
* @param {Vector4} v2 - The second vector.
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
* @return {Vector4} A reference to this vector.
*/
lerpVectors(e, t, i) {
return this.x = e.x + (t.x - e.x) * i, this.y = e.y + (t.y - e.y) * i, this.z = e.z + (t.z - e.z) * i, this.w = e.w + (t.w - e.w) * i, this;
}
/**
* Returns `true` if this vector is equal with the given one.
*
* @param {Vector4} v - The vector to test for equality.
* @return {boolean} Whether this vector is equal with the given one.
*/
equals(e) {
return e.x === this.x && e.y === this.y && e.z === this.z && e.w === this.w;
}
/**
* Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`,
* z value to be `array[ offset + 2 ]`, w value to be `array[ offset + 3 ]`.
*
* @param {Array} array - An array holding the vector component values.
* @param {number} [offset=0] - The offset into the array.
* @return {Vector4} A reference to this vector.
*/
fromArray(e, t = 0) {
return this.x = e[t], this.y = e[t + 1], this.z = e[t + 2], this.w = e[t + 3], this;
}
/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The vector components.
*/
toArray(e = [], t = 0) {
return e[t] = this.x, e[t + 1] = this.y, e[t + 2] = this.z, e[t + 3] = this.w, e;
}
/**
* Sets the components of this vector from the given buffer attribute.
*
* @param {BufferAttribute} attribute - The buffer attribute holding vector data.
* @param {number} index - The index into the attribute.
* @return {Vector4} A reference to this vector.
*/
fromBufferAttribute(e, t) {
return this.x = e.getX(t), this.y = e.getY(t), this.z = e.getZ(t), this.w = e.getW(t), this;
}
/**
* Sets each component of this vector to a pseudo-random value between `0` and
* `1`, excluding `1`.
*
* @return {Vector4} A reference to this vector.
*/
random() {
return this.x = Math.random(), this.y = Math.random(), this.z = Math.random(), this.w = Math.random(), this;
}
*[Symbol.iterator]() {
yield this.x, yield this.y, yield this.z, yield this.w;
}
}
class Zu extends gr {
/**
* Render target options.
*
* @typedef {Object} RenderTarget~Options
* @property {boolean} [generateMipmaps=false] - Whether to generate mipmaps or not.
* @property {number} [magFilter=LinearFilter] - The mag filter.
* @property {number} [minFilter=LinearFilter] - The min filter.
* @property {number} [format=RGBAFormat] - The texture format.
* @property {number} [type=UnsignedByteType] - The texture type.
* @property {?string} [internalFormat=null] - The texture's internal format.
* @property {number} [wrapS=ClampToEdgeWrapping] - The texture's uv wrapping mode.
* @property {number} [wrapT=ClampToEdgeWrapping] - The texture's uv wrapping mode.
* @property {number} [anisotropy=1] - The texture's anisotropy value.
* @property {string} [colorSpace=NoColorSpace] - The texture's color space.
* @property {boolean} [depthBuffer=true] - Whether to allocate a depth buffer or not.
* @property {boolean} [stencilBuffer=false] - Whether to allocate a stencil buffer or not.
* @property {boolean} [resolveDepthBuffer=true] - Whether to resolve the depth buffer or not.
* @property {boolean} [resolveStencilBuffer=true] - Whether to resolve the stencil buffer or not.
* @property {?Texture} [depthTexture=null] - Reference to a depth texture.
* @property {number} [samples=0] - The MSAA samples count.
* @property {number} [count=1] - Defines the number of color attachments . Must be at least `1`.
* @property {number} [depth=1] - The texture depth.
* @property {boolean} [multiview=false] - Whether this target is used for multiview rendering.
*/
/**
* Constructs a new render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor(e = 1, t = 1, i = {}) {
super(), i = Object.assign({
generateMipmaps: !1,
internalFormat: null,
minFilter: xt,
depthBuffer: !0,
stencilBuffer: !1,
resolveDepthBuffer: !0,
resolveStencilBuffer: !0,
depthTexture: null,
samples: 0,
count: 1,
depth: 1,
multiview: !1
}, i), this.isRenderTarget = !0, this.width = e, this.height = t, this.depth = i.depth, this.scissor = new Je(0, 0, e, t), this.scissorTest = !1, this.viewport = new Je(0, 0, e, t);
const s = { width: e, height: t, depth: i.depth }, n = new Ct(s);
this.textures = [];
const a = i.count;
for (let o = 0; o < a; o++)
this.textures[o] = n.clone(), this.textures[o].isRenderTargetTexture = !0, this.textures[o].renderTarget = this;
this._setTextureOptions(i), this.depthBuffer = i.depthBuffer, this.stencilBuffer = i.stencilBuffer, this.resolveDepthBuffer = i.resolveDepthBuffer, this.resolveStencilBuffer = i.resolveStencilBuffer, this._depthTexture = null, this.depthTexture = i.depthTexture, this.samples = i.samples, this.multiview = i.multiview;
}
_setTextureOptions(e = {}) {
const t = {
minFilter: xt,
generateMipmaps: !1,
flipY: !1,
internalFormat: null
};
e.mapping !== void 0 && (t.mapping = e.mapping), e.wrapS !== void 0 && (t.wrapS = e.wrapS), e.wrapT !== void 0 && (t.wrapT = e.wrapT), e.wrapR !== void 0 && (t.wrapR = e.wrapR), e.magFilter !== void 0 && (t.magFilter = e.magFilter), e.minFilter !== void 0 && (t.minFilter = e.minFilter), e.format !== void 0 && (t.format = e.format), e.type !== void 0 && (t.type = e.type), e.anisotropy !== void 0 && (t.anisotropy = e.anisotropy), e.colorSpace !== void 0 && (t.colorSpace = e.colorSpace), e.flipY !== void 0 && (t.flipY = e.flipY), e.generateMipmaps !== void 0 && (t.generateMipmaps = e.generateMipmaps), e.internalFormat !== void 0 && (t.internalFormat = e.internalFormat);
for (let i = 0; i < this.textures.length; i++)
this.textures[i].setValues(t);
}
/**
* The texture representing the default color attachment.
*
* @type {Texture}
*/
get texture() {
return this.textures[0];
}
set texture(e) {
this.textures[0] = e;
}
set depthTexture(e) {
this._depthTexture !== null && (this._depthTexture.renderTarget = null), e !== null && (e.renderTarget = this), this._depthTexture = e;
}
/**
* Instead of saving the depth in a renderbuffer, a texture
* can be used instead which is useful for further processing
* e.g. in context of post-processing.
*
* @type {?DepthTexture}
* @default null
*/
get depthTexture() {
return this._depthTexture;
}
/**
* Sets the size of this render target.
*
* @param {number} width - The width.
* @param {number} height - The height.
* @param {number} [depth=1] - The depth.
*/
setSize(e, t, i = 1) {
if (this.width !== e || this.height !== t || this.depth !== i) {
this.width = e, this.height = t, this.depth = i;
for (let s = 0, n = this.textures.length; s < n; s++)
this.textures[s].image.width = e, this.textures[s].image.height = t, this.textures[s].image.depth = i, this.textures[s].isData3DTexture !== !0 && (this.textures[s].isArrayTexture = this.textures[s].image.depth > 1);
this.dispose();
}
this.viewport.set(0, 0, e, t), this.scissor.set(0, 0, e, t);
}
/**
* Returns a new render target with copied values from this instance.
*
* @return {RenderTarget} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Copies the settings of the given render target. This is a structural copy so
* no resources are shared between render targets after the copy. That includes
* all MRT textures and the depth texture.
*
* @param {RenderTarget} source - The render target to copy.
* @return {RenderTarget} A reference to this instance.
*/
copy(e) {
this.width = e.width, this.height = e.height, this.depth = e.depth, this.scissor.copy(e.scissor), this.scissorTest = e.scissorTest, this.viewport.copy(e.viewport), this.textures.length = 0;
for (let t = 0, i = e.textures.length; t < i; t++) {
this.textures[t] = e.textures[t].clone(), this.textures[t].isRenderTargetTexture = !0, this.textures[t].renderTarget = this;
const s = Object.assign({}, e.textures[t].image);
this.textures[t].source = new Oo(s);
}
return this.depthBuffer = e.depthBuffer, this.stencilBuffer = e.stencilBuffer, this.resolveDepthBuffer = e.resolveDepthBuffer, this.resolveStencilBuffer = e.resolveStencilBuffer, e.depthTexture !== null && (this.depthTexture = e.depthTexture.clone()), this.samples = e.samples, this;
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*
* @fires RenderTarget#dispose
*/
dispose() {
this.dispatchEvent({ type: "dispose" });
}
}
class _t extends Zu {
/**
* Constructs a new 3D render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor(e = 1, t = 1, i = {}) {
super(e, t, i), this.isWebGLRenderTarget = !0;
}
}
class sh extends Ct {
/**
* Constructs a new data array texture.
*
* @param {?TypedArray} [data=null] - The buffer data.
* @param {number} [width=1] - The width of the texture.
* @param {number} [height=1] - The height of the texture.
* @param {number} [depth=1] - The depth of the texture.
*/
constructor(e = null, t = 1, i = 1, s = 1) {
super(null), this.isDataArrayTexture = !0, this.image = { data: e, width: t, height: i, depth: s }, this.magFilter = Dt, this.minFilter = Dt, this.wrapR = Jt, this.generateMipmaps = !1, this.flipY = !1, this.unpackAlignment = 1, this.layerUpdates = /* @__PURE__ */ new Set();
}
/**
* Describes that a specific layer of the texture needs to be updated.
* Normally when {@link Texture#needsUpdate} is set to `true`, the
* entire data texture array is sent to the GPU. Marking specific
* layers will only transmit subsets of all mipmaps associated with a
* specific depth in the array which is often much more performant.
*
* @param {number} layerIndex - The layer index that should be updated.
*/
addLayerUpdate(e) {
this.layerUpdates.add(e);
}
/**
* Resets the layer updates registry.
*/
clearLayerUpdates() {
this.layerUpdates.clear();
}
}
class Ju extends Ct {
/**
* Constructs a new data array texture.
*
* @param {?TypedArray} [data=null] - The buffer data.
* @param {number} [width=1] - The width of the texture.
* @param {number} [height=1] - The height of the texture.
* @param {number} [depth=1] - The depth of the texture.
*/
constructor(e = null, t = 1, i = 1, s = 1) {
super(null), this.isData3DTexture = !0, this.image = { data: e, width: t, height: i, depth: s }, this.magFilter = Dt, this.minFilter = Dt, this.wrapR = Jt, this.generateMipmaps = !1, this.flipY = !1, this.unpackAlignment = 1;
}
}
class Rt {
/**
* Constructs a new bounding box.
*
* @param {Vector3} [min=(Infinity,Infinity,Infinity)] - A vector representing the lower boundary of the box.
* @param {Vector3} [max=(-Infinity,-Infinity,-Infinity)] - A vector representing the upper boundary of the box.
*/
constructor(e = new w(1 / 0, 1 / 0, 1 / 0), t = new w(-1 / 0, -1 / 0, -1 / 0)) {
this.isBox3 = !0, this.min = e, this.max = t;
}
/**
* Sets the lower and upper boundaries of this box.
* Please note that this method only copies the values from the given objects.
*
* @param {Vector3} min - The lower boundary of the box.
* @param {Vector3} max - The upper boundary of the box.
* @return {Box3} A reference to this bounding box.
*/
set(e, t) {
return this.min.copy(e), this.max.copy(t), this;
}
/**
* Sets the upper and lower bounds of this box so it encloses the position data
* in the given array.
*
* @param {Array} array - An array holding 3D position data.
* @return {Box3} A reference to this bounding box.
*/
setFromArray(e) {
this.makeEmpty();
for (let t = 0, i = e.length; t < i; t += 3)
this.expandByPoint(ri.fromArray(e, t));
return this;
}
/**
* Sets the upper and lower bounds of this box so it encloses the position data
* in the given buffer attribute.
*
* @param {BufferAttribute} attribute - A buffer attribute holding 3D position data.
* @return {Box3} A reference to this bounding box.
*/
setFromBufferAttribute(e) {
this.makeEmpty();
for (let t = 0, i = e.count; t < i; t++)
this.expandByPoint(ri.fromBufferAttribute(e, t));
return this;
}
/**
* Sets the upper and lower bounds of this box so it encloses the position data
* in the given array.
*
* @param {Array} points - An array holding 3D position data as instances of {@link Vector3}.
* @return {Box3} A reference to this bounding box.
*/
setFromPoints(e) {
this.makeEmpty();
for (let t = 0, i = e.length; t < i; t++)
this.expandByPoint(e[t]);
return this;
}
/**
* Centers this box on the given center vector and sets this box's width, height and
* depth to the given size values.
*
* @param {Vector3} center - The center of the box.
* @param {Vector3} size - The x, y and z dimensions of the box.
* @return {Box3} A reference to this bounding box.
*/
setFromCenterAndSize(e, t) {
const i = ri.copy(t).multiplyScalar(0.5);
return this.min.copy(e).sub(i), this.max.copy(e).add(i), this;
}
/**
* Computes the world-axis-aligned bounding box for the given 3D object
* (including its children), accounting for the object's, and children's,
* world transforms. The function may result in a larger box than strictly necessary.
*
* @param {Object3D} object - The 3D object to compute the bounding box for.
* @param {boolean} [precise=false] - If set to `true`, the method computes the smallest
* world-axis-aligned bounding box at the expense of more computation.
* @return {Box3} A reference to this bounding box.
*/
setFromObject(e, t = !1) {
return this.makeEmpty(), this.expandByObject(e, t);
}
/**
* Returns a new box with copied values from this instance.
*
* @return {Box3} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Copies the values of the given box to this instance.
*
* @param {Box3} box - The box to copy.
* @return {Box3} A reference to this bounding box.
*/
copy(e) {
return this.min.copy(e.min), this.max.copy(e.max), this;
}
/**
* Makes this box empty which means in encloses a zero space in 3D.
*
* @return {Box3} A reference to this bounding box.
*/
makeEmpty() {
return this.min.x = this.min.y = this.min.z = 1 / 0, this.max.x = this.max.y = this.max.z = -1 / 0, this;
}
/**
* Returns true if this box includes zero points within its bounds.
* Note that a box with equal lower and upper bounds still includes one
* point, the one both bounds share.
*
* @return {boolean} Whether this box is empty or not.
*/
isEmpty() {
return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z;
}
/**
* Returns the center point of this box.
*
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The center point.
*/
getCenter(e) {
return this.isEmpty() ? e.set(0, 0, 0) : e.addVectors(this.min, this.max).multiplyScalar(0.5);
}
/**
* Returns the dimensions of this box.
*
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The size.
*/
getSize(e) {
return this.isEmpty() ? e.set(0, 0, 0) : e.subVectors(this.max, this.min);
}
/**
* Expands the boundaries of this box to include the given point.
*
* @param {Vector3} point - The point that should be included by the bounding box.
* @return {Box3} A reference to this bounding box.
*/
expandByPoint(e) {
return this.min.min(e), this.max.max(e), this;
}
/**
* Expands this box equilaterally by the given vector. The width of this
* box will be expanded by the x component of the vector in both
* directions. The height of this box will be expanded by the y component of
* the vector in both directions. The depth of this box will be
* expanded by the z component of the vector in both directions.
*
* @param {Vector3} vector - The vector that should expand the bounding box.
* @return {Box3} A reference to this bounding box.
*/
expandByVector(e) {
return this.min.sub(e), this.max.add(e), this;
}
/**
* Expands each dimension of the box by the given scalar. If negative, the
* dimensions of the box will be contracted.
*
* @param {number} scalar - The scalar value that should expand the bounding box.
* @return {Box3} A reference to this bounding box.
*/
expandByScalar(e) {
return this.min.addScalar(-e), this.max.addScalar(e), this;
}
/**
* Expands the boundaries of this box to include the given 3D object and
* its children, accounting for the object's, and children's, world
* transforms. The function may result in a larger box than strictly
* necessary (unless the precise parameter is set to true).
*
* @param {Object3D} object - The 3D object that should expand the bounding box.
* @param {boolean} precise - If set to `true`, the method expands the bounding box
* as little as necessary at the expense of more computation.
* @return {Box3} A reference to this bounding box.
*/
expandByObject(e, t = !1) {
e.updateWorldMatrix(!1, !1);
const i = e.geometry;
if (i !== void 0) {
const n = i.getAttribute("position");
if (t === !0 && n !== void 0 && e.isInstancedMesh !== !0)
for (let a = 0, o = n.count; a < o; a++)
e.isMesh === !0 ? e.getVertexPosition(a, ri) : ri.fromBufferAttribute(n, a), ri.applyMatrix4(e.matrixWorld), this.expandByPoint(ri);
else
e.boundingBox !== void 0 ? (e.boundingBox === null && e.computeBoundingBox(), Us.copy(e.boundingBox)) : (i.boundingBox === null && i.computeBoundingBox(), Us.copy(i.boundingBox)), Us.applyMatrix4(e.matrixWorld), this.union(Us);
}
const s = e.children;
for (let n = 0, a = s.length; n < a; n++)
this.expandByObject(s[n], t);
return this;
}
/**
* Returns `true` if the given point lies within or on the boundaries of this box.
*
* @param {Vector3} point - The point to test.
* @return {boolean} Whether the bounding box contains the given point or not.
*/
containsPoint(e) {
return e.x >= this.min.x && e.x <= this.max.x && e.y >= this.min.y && e.y <= this.max.y && e.z >= this.min.z && e.z <= this.max.z;
}
/**
* Returns `true` if this bounding box includes the entirety of the given bounding box.
* If this box and the given one are identical, this function also returns `true`.
*
* @param {Box3} box - The bounding box to test.
* @return {boolean} Whether the bounding box contains the given bounding box or not.
*/
containsBox(e) {
return this.min.x <= e.min.x && e.max.x <= this.max.x && this.min.y <= e.min.y && e.max.y <= this.max.y && this.min.z <= e.min.z && e.max.z <= this.max.z;
}
/**
* Returns a point as a proportion of this box's width, height and depth.
*
* @param {Vector3} point - A point in 3D space.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} A point as a proportion of this box's width, height and depth.
*/
getParameter(e, t) {
return t.set(
(e.x - this.min.x) / (this.max.x - this.min.x),
(e.y - this.min.y) / (this.max.y - this.min.y),
(e.z - this.min.z) / (this.max.z - this.min.z)
);
}
/**
* Returns `true` if the given bounding box intersects with this bounding box.
*
* @param {Box3} box - The bounding box to test.
* @return {boolean} Whether the given bounding box intersects with this bounding box.
*/
intersectsBox(e) {
return e.max.x >= this.min.x && e.min.x <= this.max.x && e.max.y >= this.min.y && e.min.y <= this.max.y && e.max.z >= this.min.z && e.min.z <= this.max.z;
}
/**
* Returns `true` if the given bounding sphere intersects with this bounding box.
*
* @param {Sphere} sphere - The bounding sphere to test.
* @return {boolean} Whether the given bounding sphere intersects with this bounding box.
*/
intersectsSphere(e) {
return this.clampPoint(e.center, ri), ri.distanceToSquared(e.center) <= e.radius * e.radius;
}
/**
* Returns `true` if the given plane intersects with this bounding box.
*
* @param {Plane} plane - The plane to test.
* @return {boolean} Whether the given plane intersects with this bounding box.
*/
intersectsPlane(e) {
let t, i;
return e.normal.x > 0 ? (t = e.normal.x * this.min.x, i = e.normal.x * this.max.x) : (t = e.normal.x * this.max.x, i = e.normal.x * this.min.x), e.normal.y > 0 ? (t += e.normal.y * this.min.y, i += e.normal.y * this.max.y) : (t += e.normal.y * this.max.y, i += e.normal.y * this.min.y), e.normal.z > 0 ? (t += e.normal.z * this.min.z, i += e.normal.z * this.max.z) : (t += e.normal.z * this.max.z, i += e.normal.z * this.min.z), t <= -e.constant && i >= -e.constant;
}
/**
* Returns `true` if the given triangle intersects with this bounding box.
*
* @param {Triangle} triangle - The triangle to test.
* @return {boolean} Whether the given triangle intersects with this bounding box.
*/
intersectsTriangle(e) {
if (this.isEmpty())
return !1;
this.getCenter(ns), Ns.subVectors(this.max, ns), yr.subVectors(e.a, ns), Mr.subVectors(e.b, ns), Sr.subVectors(e.c, ns), Vi.subVectors(Mr, yr), Gi.subVectors(Sr, Mr), sr.subVectors(yr, Sr);
let t = [
0,
-Vi.z,
Vi.y,
0,
-Gi.z,
Gi.y,
0,
-sr.z,
sr.y,
Vi.z,
0,
-Vi.x,
Gi.z,
0,
-Gi.x,
sr.z,
0,
-sr.x,
-Vi.y,
Vi.x,
0,
-Gi.y,
Gi.x,
0,
-sr.y,
sr.x,
0
];
return !Gn(t, yr, Mr, Sr, Ns) || (t = [1, 0, 0, 0, 1, 0, 0, 0, 1], !Gn(t, yr, Mr, Sr, Ns)) ? !1 : (Os.crossVectors(Vi, Gi), t = [Os.x, Os.y, Os.z], Gn(t, yr, Mr, Sr, Ns));
}
/**
* Clamps the given point within the bounds of this box.
*
* @param {Vector3} point - The point to clamp.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The clamped point.
*/
clampPoint(e, t) {
return t.copy(e).clamp(this.min, this.max);
}
/**
* Returns the euclidean distance from any edge of this box to the specified point. If
* the given point lies inside of this box, the distance will be `0`.
*
* @param {Vector3} point - The point to compute the distance to.
* @return {number} The euclidean distance.
*/
distanceToPoint(e) {
return this.clampPoint(e, ri).distanceTo(e);
}
/**
* Returns a bounding sphere that encloses this bounding box.
*
* @param {Sphere} target - The target sphere that is used to store the method's result.
* @return {Sphere} The bounding sphere that encloses this bounding box.
*/
getBoundingSphere(e) {
return this.isEmpty() ? e.makeEmpty() : (this.getCenter(e.center), e.radius = this.getSize(ri).length() * 0.5), e;
}
/**
* Computes the intersection of this bounding box and the given one, setting the upper
* bound of this box to the lesser of the two boxes' upper bounds and the
* lower bound of this box to the greater of the two boxes' lower bounds. If
* there's no overlap, makes this box empty.
*
* @param {Box3} box - The bounding box to intersect with.
* @return {Box3} A reference to this bounding box.
*/
intersect(e) {
return this.min.max(e.min), this.max.min(e.max), this.isEmpty() && this.makeEmpty(), this;
}
/**
* Computes the union of this box and another and the given one, setting the upper
* bound of this box to the greater of the two boxes' upper bounds and the
* lower bound of this box to the lesser of the two boxes' lower bounds.
*
* @param {Box3} box - The bounding box that will be unioned with this instance.
* @return {Box3} A reference to this bounding box.
*/
union(e) {
return this.min.min(e.min), this.max.max(e.max), this;
}
/**
* Transforms this bounding box by the given 4x4 transformation matrix.
*
* @param {Matrix4} matrix - The transformation matrix.
* @return {Box3} A reference to this bounding box.
*/
applyMatrix4(e) {
return this.isEmpty() ? this : (Pi[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(e), Pi[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(e), Pi[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(e), Pi[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(e), Pi[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(e), Pi[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(e), Pi[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(e), Pi[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(e), this.setFromPoints(Pi), this);
}
/**
* Adds the given offset to both the upper and lower bounds of this bounding box,
* effectively moving it in 3D space.
*
* @param {Vector3} offset - The offset that should be used to translate the bounding box.
* @return {Box3} A reference to this bounding box.
*/
translate(e) {
return this.min.add(e), this.max.add(e), this;
}
/**
* Returns `true` if this bounding box is equal with the given one.
*
* @param {Box3} box - The box to test for equality.
* @return {boolean} Whether this bounding box is equal with the given one.
*/
equals(e) {
return e.min.equals(this.min) && e.max.equals(this.max);
}
/**
* Returns a serialized structure of the bounding box.
*
* @return {Object} Serialized structure with fields representing the object state.
*/
toJSON() {
return {
min: this.min.toArray(),
max: this.max.toArray()
};
}
/**
* Returns a serialized structure of the bounding box.
*
* @param {Object} json - The serialized json to set the box from.
* @return {Box3} A reference to this bounding box.
*/
fromJSON(e) {
return this.min.fromArray(e.min), this.max.fromArray(e.max), this;
}
}
const Pi = [
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w(),
/* @__PURE__ */ new w()
], ri = /* @__PURE__ */ new w(), Us = /* @__PURE__ */ new Rt(), yr = /* @__PURE__ */ new w(), Mr = /* @__PURE__ */ new w(), Sr = /* @__PURE__ */ new w(), Vi = /* @__PURE__ */ new w(), Gi = /* @__PURE__ */ new w(), sr = /* @__PURE__ */ new w(), ns = /* @__PURE__ */ new w(), Ns = /* @__PURE__ */ new w(), Os = /* @__PURE__ */ new w(), nr = /* @__PURE__ */ new w();
function Gn(r, e, t, i, s) {
for (let n = 0, a = r.length - 3; n <= a; n += 3) {
nr.fromArray(r, n);
const o = s.x * Math.abs(nr.x) + s.y * Math.abs(nr.y) + s.z * Math.abs(nr.z), l = e.dot(nr), c = t.dot(nr), h = i.dot(nr);
if (Math.max(-Math.max(l, c, h), Math.min(l, c, h)) > o)
return !1;
}
return !0;
}
const $u = /* @__PURE__ */ new Rt(), as = /* @__PURE__ */ new w(), Wn = /* @__PURE__ */ new w();
class Ci {
/**
* Constructs a new sphere.
*
* @param {Vector3} [center=(0,0,0)] - The center of the sphere
* @param {number} [radius=-1] - The radius of the sphere.
*/
constructor(e = new w(), t = -1) {
this.isSphere = !0, this.center = e, this.radius = t;
}
/**
* Sets the sphere's components by copying the given values.
*
* @param {Vector3} center - The center.
* @param {number} radius - The radius.
* @return {Sphere} A reference to this sphere.
*/
set(e, t) {
return this.center.copy(e), this.radius = t, this;
}
/**
* Computes the minimum bounding sphere for list of points.
* If the optional center point is given, it is used as the sphere's
* center. Otherwise, the center of the axis-aligned bounding box
* encompassing the points is calculated.
*
* @param {Array} points - A list of points in 3D space.
* @param {Vector3} [optionalCenter] - The center of the sphere.
* @return {Sphere} A reference to this sphere.
*/
setFromPoints(e, t) {
const i = this.center;
t !== void 0 ? i.copy(t) : $u.setFromPoints(e).getCenter(i);
let s = 0;
for (let n = 0, a = e.length; n < a; n++)
s = Math.max(s, i.distanceToSquared(e[n]));
return this.radius = Math.sqrt(s), this;
}
/**
* Copies the values of the given sphere to this instance.
*
* @param {Sphere} sphere - The sphere to copy.
* @return {Sphere} A reference to this sphere.
*/
copy(e) {
return this.center.copy(e.center), this.radius = e.radius, this;
}
/**
* Returns `true` if the sphere is empty (the radius set to a negative number).
*
* Spheres with a radius of `0` contain only their center point and are not
* considered to be empty.
*
* @return {boolean} Whether this sphere is empty or not.
*/
isEmpty() {
return this.radius < 0;
}
/**
* Makes this sphere empty which means in encloses a zero space in 3D.
*
* @return {Sphere} A reference to this sphere.
*/
makeEmpty() {
return this.center.set(0, 0, 0), this.radius = -1, this;
}
/**
* Returns `true` if this sphere contains the given point inclusive of
* the surface of the sphere.
*
* @param {Vector3} point - The point to check.
* @return {boolean} Whether this sphere contains the given point or not.
*/
containsPoint(e) {
return e.distanceToSquared(this.center) <= this.radius * this.radius;
}
/**
* Returns the closest distance from the boundary of the sphere to the
* given point. If the sphere contains the point, the distance will
* be negative.
*
* @param {Vector3} point - The point to compute the distance to.
* @return {number} The distance to the point.
*/
distanceToPoint(e) {
return e.distanceTo(this.center) - this.radius;
}
/**
* Returns `true` if this sphere intersects with the given one.
*
* @param {Sphere} sphere - The sphere to test.
* @return {boolean} Whether this sphere intersects with the given one or not.
*/
intersectsSphere(e) {
const t = this.radius + e.radius;
return e.center.distanceToSquared(this.center) <= t * t;
}
/**
* Returns `true` if this sphere intersects with the given box.
*
* @param {Box3} box - The box to test.
* @return {boolean} Whether this sphere intersects with the given box or not.
*/
intersectsBox(e) {
return e.intersectsSphere(this);
}
/**
* Returns `true` if this sphere intersects with the given plane.
*
* @param {Plane} plane - The plane to test.
* @return {boolean} Whether this sphere intersects with the given plane or not.
*/
intersectsPlane(e) {
return Math.abs(e.distanceToPoint(this.center)) <= this.radius;
}
/**
* Clamps a point within the sphere. If the point is outside the sphere, it
* will clamp it to the closest point on the edge of the sphere. Points
* already inside the sphere will not be affected.
*
* @param {Vector3} point - The plane to clamp.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The clamped point.
*/
clampPoint(e, t) {
const i = this.center.distanceToSquared(e);
return t.copy(e), i > this.radius * this.radius && (t.sub(this.center).normalize(), t.multiplyScalar(this.radius).add(this.center)), t;
}
/**
* Returns a bounding box that encloses this sphere.
*
* @param {Box3} target - The target box that is used to store the method's result.
* @return {Box3} The bounding box that encloses this sphere.
*/
getBoundingBox(e) {
return this.isEmpty() ? (e.makeEmpty(), e) : (e.set(this.center, this.center), e.expandByScalar(this.radius), e);
}
/**
* Transforms this sphere with the given 4x4 transformation matrix.
*
* @param {Matrix4} matrix - The transformation matrix.
* @return {Sphere} A reference to this sphere.
*/
applyMatrix4(e) {
return this.center.applyMatrix4(e), this.radius = this.radius * e.getMaxScaleOnAxis(), this;
}
/**
* Translates the sphere's center by the given offset.
*
* @param {Vector3} offset - The offset.
* @return {Sphere} A reference to this sphere.
*/
translate(e) {
return this.center.add(e), this;
}
/**
* Expands the boundaries of this sphere to include the given point.
*
* @param {Vector3} point - The point to include.
* @return {Sphere} A reference to this sphere.
*/
expandByPoint(e) {
if (this.isEmpty())
return this.center.copy(e), this.radius = 0, this;
as.subVectors(e, this.center);
const t = as.lengthSq();
if (t > this.radius * this.radius) {
const i = Math.sqrt(t), s = (i - this.radius) * 0.5;
this.center.addScaledVector(as, s / i), this.radius += s;
}
return this;
}
/**
* Expands this sphere to enclose both the original sphere and the given sphere.
*
* @param {Sphere} sphere - The sphere to include.
* @return {Sphere} A reference to this sphere.
*/
union(e) {
return e.isEmpty() ? this : this.isEmpty() ? (this.copy(e), this) : (this.center.equals(e.center) === !0 ? this.radius = Math.max(this.radius, e.radius) : (Wn.subVectors(e.center, this.center).setLength(e.radius), this.expandByPoint(as.copy(e.center).add(Wn)), this.expandByPoint(as.copy(e.center).sub(Wn))), this);
}
/**
* Returns `true` if this sphere is equal with the given one.
*
* @param {Sphere} sphere - The sphere to test for equality.
* @return {boolean} Whether this bounding sphere is equal with the given one.
*/
equals(e) {
return e.center.equals(this.center) && e.radius === this.radius;
}
/**
* Returns a new sphere with copied values from this instance.
*
* @return {Sphere} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Returns a serialized structure of the bounding sphere.
*
* @return {Object} Serialized structure with fields representing the object state.
*/
toJSON() {
return {
radius: this.radius,
center: this.center.toArray()
};
}
/**
* Returns a serialized structure of the bounding sphere.
*
* @param {Object} json - The serialized json to set the sphere from.
* @return {Box3} A reference to this bounding sphere.
*/
fromJSON(e) {
return this.radius = e.radius, this.center.fromArray(e.center), this;
}
}
const Di = /* @__PURE__ */ new w(), jn = /* @__PURE__ */ new w(), Bs = /* @__PURE__ */ new w(), Wi = /* @__PURE__ */ new w(), Xn = /* @__PURE__ */ new w(), Fs = /* @__PURE__ */ new w(), qn = /* @__PURE__ */ new w();
class Qr {
/**
* Constructs a new ray.
*
* @param {Vector3} [origin=(0,0,0)] - The origin of the ray.
* @param {Vector3} [direction=(0,0,-1)] - The (normalized) direction of the ray.
*/
constructor(e = new w(), t = new w(0, 0, -1)) {
this.origin = e, this.direction = t;
}
/**
* Sets the ray's components by copying the given values.
*
* @param {Vector3} origin - The origin.
* @param {Vector3} direction - The direction.
* @return {Ray} A reference to this ray.
*/
set(e, t) {
return this.origin.copy(e), this.direction.copy(t), this;
}
/**
* Copies the values of the given ray to this instance.
*
* @param {Ray} ray - The ray to copy.
* @return {Ray} A reference to this ray.
*/
copy(e) {
return this.origin.copy(e.origin), this.direction.copy(e.direction), this;
}
/**
* Returns a vector that is located at a given distance along this ray.
*
* @param {number} t - The distance along the ray to retrieve a position for.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} A position on the ray.
*/
at(e, t) {
return t.copy(this.origin).addScaledVector(this.direction, e);
}
/**
* Adjusts the direction of the ray to point at the given vector in world space.
*
* @param {Vector3} v - The target position.
* @return {Ray} A reference to this ray.
*/
lookAt(e) {
return this.direction.copy(e).sub(this.origin).normalize(), this;
}
/**
* Shift the origin of this ray along its direction by the given distance.
*
* @param {number} t - The distance along the ray to interpolate.
* @return {Ray} A reference to this ray.
*/
recast(e) {
return this.origin.copy(this.at(e, Di)), this;
}
/**
* Returns the point along this ray that is closest to the given point.
*
* @param {Vector3} point - A point in 3D space to get the closet location on the ray for.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The closest point on this ray.
*/
closestPointToPoint(e, t) {
t.subVectors(e, this.origin);
const i = t.dot(this.direction);
return i < 0 ? t.copy(this.origin) : t.copy(this.origin).addScaledVector(this.direction, i);
}
/**
* Returns the distance of the closest approach between this ray and the given point.
*
* @param {Vector3} point - A point in 3D space to compute the distance to.
* @return {number} The distance.
*/
distanceToPoint(e) {
return Math.sqrt(this.distanceSqToPoint(e));
}
/**
* Returns the squared distance of the closest approach between this ray and the given point.
*
* @param {Vector3} point - A point in 3D space to compute the distance to.
* @return {number} The squared distance.
*/
distanceSqToPoint(e) {
const t = Di.subVectors(e, this.origin).dot(this.direction);
return t < 0 ? this.origin.distanceToSquared(e) : (Di.copy(this.origin).addScaledVector(this.direction, t), Di.distanceToSquared(e));
}
/**
* Returns the squared distance between this ray and the given line segment.
*
* @param {Vector3} v0 - The start point of the line segment.
* @param {Vector3} v1 - The end point of the line segment.
* @param {Vector3} [optionalPointOnRay] - When provided, it receives the point on this ray that is closest to the segment.
* @param {Vector3} [optionalPointOnSegment] - When provided, it receives the point on the line segment that is closest to this ray.
* @return {number} The squared distance.
*/
distanceSqToSegment(e, t, i, s) {
jn.copy(e).add(t).multiplyScalar(0.5), Bs.copy(t).sub(e).normalize(), Wi.copy(this.origin).sub(jn);
const n = e.distanceTo(t) * 0.5, a = -this.direction.dot(Bs), o = Wi.dot(this.direction), l = -Wi.dot(Bs), c = Wi.lengthSq(), h = Math.abs(1 - a * a);
let u, d, f, g;
if (h > 0)
if (u = a * l - o, d = a * o - l, g = n * h, u >= 0)
if (d >= -g)
if (d <= g) {
const v = 1 / h;
u *= v, d *= v, f = u * (u + a * d + 2 * o) + d * (a * u + d + 2 * l) + c;
} else
d = n, u = Math.max(0, -(a * d + o)), f = -u * u + d * (d + 2 * l) + c;
else
d = -n, u = Math.max(0, -(a * d + o)), f = -u * u + d * (d + 2 * l) + c;
else
d <= -g ? (u = Math.max(0, -(-a * n + o)), d = u > 0 ? -n : Math.min(Math.max(-n, -l), n), f = -u * u + d * (d + 2 * l) + c) : d <= g ? (u = 0, d = Math.min(Math.max(-n, -l), n), f = d * (d + 2 * l) + c) : (u = Math.max(0, -(a * n + o)), d = u > 0 ? n : Math.min(Math.max(-n, -l), n), f = -u * u + d * (d + 2 * l) + c);
else
d = a > 0 ? -n : n, u = Math.max(0, -(a * d + o)), f = -u * u + d * (d + 2 * l) + c;
return i && i.copy(this.origin).addScaledVector(this.direction, u), s && s.copy(jn).addScaledVector(Bs, d), f;
}
/**
* Intersects this ray with the given sphere, returning the intersection
* point or `null` if there is no intersection.
*
* @param {Sphere} sphere - The sphere to intersect.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {?Vector3} The intersection point.
*/
intersectSphere(e, t) {
Di.subVectors(e.center, this.origin);
const i = Di.dot(this.direction), s = Di.dot(Di) - i * i, n = e.radius * e.radius;
if (s > n) return null;
const a = Math.sqrt(n - s), o = i - a, l = i + a;
return l < 0 ? null : o < 0 ? this.at(l, t) : this.at(o, t);
}
/**
* Returns `true` if this ray intersects with the given sphere.
*
* @param {Sphere} sphere - The sphere to intersect.
* @return {boolean} Whether this ray intersects with the given sphere or not.
*/
intersectsSphere(e) {
return e.radius < 0 ? !1 : this.distanceSqToPoint(e.center) <= e.radius * e.radius;
}
/**
* Computes the distance from the ray's origin to the given plane. Returns `null` if the ray
* does not intersect with the plane.
*
* @param {Plane} plane - The plane to compute the distance to.
* @return {?number} Whether this ray intersects with the given sphere or not.
*/
distanceToPlane(e) {
const t = e.normal.dot(this.direction);
if (t === 0)
return e.distanceToPoint(this.origin) === 0 ? 0 : null;
const i = -(this.origin.dot(e.normal) + e.constant) / t;
return i >= 0 ? i : null;
}
/**
* Intersects this ray with the given plane, returning the intersection
* point or `null` if there is no intersection.
*
* @param {Plane} plane - The plane to intersect.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {?Vector3} The intersection point.
*/
intersectPlane(e, t) {
const i = this.distanceToPlane(e);
return i === null ? null : this.at(i, t);
}
/**
* Returns `true` if this ray intersects with the given plane.
*
* @param {Plane} plane - The plane to intersect.
* @return {boolean} Whether this ray intersects with the given plane or not.
*/
intersectsPlane(e) {
const t = e.distanceToPoint(this.origin);
return t === 0 || e.normal.dot(this.direction) * t < 0;
}
/**
* Intersects this ray with the given bounding box, returning the intersection
* point or `null` if there is no intersection.
*
* @param {Box3} box - The box to intersect.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {?Vector3} The intersection point.
*/
intersectBox(e, t) {
let i, s, n, a, o, l;
const c = 1 / this.direction.x, h = 1 / this.direction.y, u = 1 / this.direction.z, d = this.origin;
return c >= 0 ? (i = (e.min.x - d.x) * c, s = (e.max.x - d.x) * c) : (i = (e.max.x - d.x) * c, s = (e.min.x - d.x) * c), h >= 0 ? (n = (e.min.y - d.y) * h, a = (e.max.y - d.y) * h) : (n = (e.max.y - d.y) * h, a = (e.min.y - d.y) * h), i > a || n > s || ((n > i || isNaN(i)) && (i = n), (a < s || isNaN(s)) && (s = a), u >= 0 ? (o = (e.min.z - d.z) * u, l = (e.max.z - d.z) * u) : (o = (e.max.z - d.z) * u, l = (e.min.z - d.z) * u), i > l || o > s) || ((o > i || i !== i) && (i = o), (l < s || s !== s) && (s = l), s < 0) ? null : this.at(i >= 0 ? i : s, t);
}
/**
* Returns `true` if this ray intersects with the given box.
*
* @param {Box3} box - The box to intersect.
* @return {boolean} Whether this ray intersects with the given box or not.
*/
intersectsBox(e) {
return this.intersectBox(e, Di) !== null;
}
/**
* Intersects this ray with the given triangle, returning the intersection
* point or `null` if there is no intersection.
*
* @param {Vector3} a - The first vertex of the triangle.
* @param {Vector3} b - The second vertex of the triangle.
* @param {Vector3} c - The third vertex of the triangle.
* @param {boolean} backfaceCulling - Whether to use backface culling or not.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {?Vector3} The intersection point.
*/
intersectTriangle(e, t, i, s, n) {
Xn.subVectors(t, e), Fs.subVectors(i, e), qn.crossVectors(Xn, Fs);
let a = this.direction.dot(qn), o;
if (a > 0) {
if (s) return null;
o = 1;
} else if (a < 0)
o = -1, a = -a;
else
return null;
Wi.subVectors(this.origin, e);
const l = o * this.direction.dot(Fs.crossVectors(Wi, Fs));
if (l < 0)
return null;
const c = o * this.direction.dot(Xn.cross(Wi));
if (c < 0 || l + c > a)
return null;
const h = -o * Wi.dot(qn);
return h < 0 ? null : this.at(h / a, n);
}
/**
* Transforms this ray with the given 4x4 transformation matrix.
*
* @param {Matrix4} matrix4 - The transformation matrix.
* @return {Ray} A reference to this ray.
*/
applyMatrix4(e) {
return this.origin.applyMatrix4(e), this.direction.transformDirection(e), this;
}
/**
* Returns `true` if this ray is equal with the given one.
*
* @param {Ray} ray - The ray to test for equality.
* @return {boolean} Whether this ray is equal with the given one.
*/
equals(e) {
return e.origin.equals(this.origin) && e.direction.equals(this.direction);
}
/**
* Returns a new ray with copied values from this instance.
*
* @return {Ray} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
}
class Ue {
/**
* Constructs a new 4x4 matrix. The arguments are supposed to be
* in row-major order. If no arguments are provided, the constructor
* initializes the matrix as an identity matrix.
*
* @param {number} [n11] - 1-1 matrix element.
* @param {number} [n12] - 1-2 matrix element.
* @param {number} [n13] - 1-3 matrix element.
* @param {number} [n14] - 1-4 matrix element.
* @param {number} [n21] - 2-1 matrix element.
* @param {number} [n22] - 2-2 matrix element.
* @param {number} [n23] - 2-3 matrix element.
* @param {number} [n24] - 2-4 matrix element.
* @param {number} [n31] - 3-1 matrix element.
* @param {number} [n32] - 3-2 matrix element.
* @param {number} [n33] - 3-3 matrix element.
* @param {number} [n34] - 3-4 matrix element.
* @param {number} [n41] - 4-1 matrix element.
* @param {number} [n42] - 4-2 matrix element.
* @param {number} [n43] - 4-3 matrix element.
* @param {number} [n44] - 4-4 matrix element.
*/
constructor(e, t, i, s, n, a, o, l, c, h, u, d, f, g, v, m) {
Ue.prototype.isMatrix4 = !0, this.elements = [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
], e !== void 0 && this.set(e, t, i, s, n, a, o, l, c, h, u, d, f, g, v, m);
}
/**
* Sets the elements of the matrix.The arguments are supposed to be
* in row-major order.
*
* @param {number} [n11] - 1-1 matrix element.
* @param {number} [n12] - 1-2 matrix element.
* @param {number} [n13] - 1-3 matrix element.
* @param {number} [n14] - 1-4 matrix element.
* @param {number} [n21] - 2-1 matrix element.
* @param {number} [n22] - 2-2 matrix element.
* @param {number} [n23] - 2-3 matrix element.
* @param {number} [n24] - 2-4 matrix element.
* @param {number} [n31] - 3-1 matrix element.
* @param {number} [n32] - 3-2 matrix element.
* @param {number} [n33] - 3-3 matrix element.
* @param {number} [n34] - 3-4 matrix element.
* @param {number} [n41] - 4-1 matrix element.
* @param {number} [n42] - 4-2 matrix element.
* @param {number} [n43] - 4-3 matrix element.
* @param {number} [n44] - 4-4 matrix element.
* @return {Matrix4} A reference to this matrix.
*/
set(e, t, i, s, n, a, o, l, c, h, u, d, f, g, v, m) {
const p = this.elements;
return p[0] = e, p[4] = t, p[8] = i, p[12] = s, p[1] = n, p[5] = a, p[9] = o, p[13] = l, p[2] = c, p[6] = h, p[10] = u, p[14] = d, p[3] = f, p[7] = g, p[11] = v, p[15] = m, this;
}
/**
* Sets this matrix to the 4x4 identity matrix.
*
* @return {Matrix4} A reference to this matrix.
*/
identity() {
return this.set(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
), this;
}
/**
* Returns a matrix with copied values from this instance.
*
* @return {Matrix4} A clone of this instance.
*/
clone() {
return new Ue().fromArray(this.elements);
}
/**
* Copies the values of the given matrix to this instance.
*
* @param {Matrix4} m - The matrix to copy.
* @return {Matrix4} A reference to this matrix.
*/
copy(e) {
const t = this.elements, i = e.elements;
return t[0] = i[0], t[1] = i[1], t[2] = i[2], t[3] = i[3], t[4] = i[4], t[5] = i[5], t[6] = i[6], t[7] = i[7], t[8] = i[8], t[9] = i[9], t[10] = i[10], t[11] = i[11], t[12] = i[12], t[13] = i[13], t[14] = i[14], t[15] = i[15], this;
}
/**
* Copies the translation component of the given matrix
* into this matrix's translation component.
*
* @param {Matrix4} m - The matrix to copy the translation component.
* @return {Matrix4} A reference to this matrix.
*/
copyPosition(e) {
const t = this.elements, i = e.elements;
return t[12] = i[12], t[13] = i[13], t[14] = i[14], this;
}
/**
* Set the upper 3x3 elements of this matrix to the values of given 3x3 matrix.
*
* @param {Matrix3} m - The 3x3 matrix.
* @return {Matrix4} A reference to this matrix.
*/
setFromMatrix3(e) {
const t = e.elements;
return this.set(
t[0],
t[3],
t[6],
0,
t[1],
t[4],
t[7],
0,
t[2],
t[5],
t[8],
0,
0,
0,
0,
1
), this;
}
/**
* Extracts the basis of this matrix into the three axis vectors provided.
*
* @param {Vector3} xAxis - The basis's x axis.
* @param {Vector3} yAxis - The basis's y axis.
* @param {Vector3} zAxis - The basis's z axis.
* @return {Matrix4} A reference to this matrix.
*/
extractBasis(e, t, i) {
return e.setFromMatrixColumn(this, 0), t.setFromMatrixColumn(this, 1), i.setFromMatrixColumn(this, 2), this;
}
/**
* Sets the given basis vectors to this matrix.
*
* @param {Vector3} xAxis - The basis's x axis.
* @param {Vector3} yAxis - The basis's y axis.
* @param {Vector3} zAxis - The basis's z axis.
* @return {Matrix4} A reference to this matrix.
*/
makeBasis(e, t, i) {
return this.set(
e.x,
t.x,
i.x,
0,
e.y,
t.y,
i.y,
0,
e.z,
t.z,
i.z,
0,
0,
0,
0,
1
), this;
}
/**
* Extracts the rotation component of the given matrix
* into this matrix's rotation component.
*
* Note: This method does not support reflection matrices.
*
* @param {Matrix4} m - The matrix.
* @return {Matrix4} A reference to this matrix.
*/
extractRotation(e) {
const t = this.elements, i = e.elements, s = 1 / br.setFromMatrixColumn(e, 0).length(), n = 1 / br.setFromMatrixColumn(e, 1).length(), a = 1 / br.setFromMatrixColumn(e, 2).length();
return t[0] = i[0] * s, t[1] = i[1] * s, t[2] = i[2] * s, t[3] = 0, t[4] = i[4] * n, t[5] = i[5] * n, t[6] = i[6] * n, t[7] = 0, t[8] = i[8] * a, t[9] = i[9] * a, t[10] = i[10] * a, t[11] = 0, t[12] = 0, t[13] = 0, t[14] = 0, t[15] = 1, this;
}
/**
* Sets the rotation component (the upper left 3x3 matrix) of this matrix to
* the rotation specified by the given Euler angles. The rest of
* the matrix is set to the identity. Depending on the {@link Euler#order},
* there are six possible outcomes. See [this page](https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix)
* for a complete list.
*
* @param {Euler} euler - The Euler angles.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationFromEuler(e) {
const t = this.elements, i = e.x, s = e.y, n = e.z, a = Math.cos(i), o = Math.sin(i), l = Math.cos(s), c = Math.sin(s), h = Math.cos(n), u = Math.sin(n);
if (e.order === "XYZ") {
const d = a * h, f = a * u, g = o * h, v = o * u;
t[0] = l * h, t[4] = -l * u, t[8] = c, t[1] = f + g * c, t[5] = d - v * c, t[9] = -o * l, t[2] = v - d * c, t[6] = g + f * c, t[10] = a * l;
} else if (e.order === "YXZ") {
const d = l * h, f = l * u, g = c * h, v = c * u;
t[0] = d + v * o, t[4] = g * o - f, t[8] = a * c, t[1] = a * u, t[5] = a * h, t[9] = -o, t[2] = f * o - g, t[6] = v + d * o, t[10] = a * l;
} else if (e.order === "ZXY") {
const d = l * h, f = l * u, g = c * h, v = c * u;
t[0] = d - v * o, t[4] = -a * u, t[8] = g + f * o, t[1] = f + g * o, t[5] = a * h, t[9] = v - d * o, t[2] = -a * c, t[6] = o, t[10] = a * l;
} else if (e.order === "ZYX") {
const d = a * h, f = a * u, g = o * h, v = o * u;
t[0] = l * h, t[4] = g * c - f, t[8] = d * c + v, t[1] = l * u, t[5] = v * c + d, t[9] = f * c - g, t[2] = -c, t[6] = o * l, t[10] = a * l;
} else if (e.order === "YZX") {
const d = a * l, f = a * c, g = o * l, v = o * c;
t[0] = l * h, t[4] = v - d * u, t[8] = g * u + f, t[1] = u, t[5] = a * h, t[9] = -o * h, t[2] = -c * h, t[6] = f * u + g, t[10] = d - v * u;
} else if (e.order === "XZY") {
const d = a * l, f = a * c, g = o * l, v = o * c;
t[0] = l * h, t[4] = -u, t[8] = c * h, t[1] = d * u + v, t[5] = a * h, t[9] = f * u - g, t[2] = g * u - f, t[6] = o * h, t[10] = v * u + d;
}
return t[3] = 0, t[7] = 0, t[11] = 0, t[12] = 0, t[13] = 0, t[14] = 0, t[15] = 1, this;
}
/**
* Sets the rotation component of this matrix to the rotation specified by
* the given Quaternion as outlined [here](https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion)
* The rest of the matrix is set to the identity.
*
* @param {Quaternion} q - The Quaternion.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationFromQuaternion(e) {
return this.compose(Qu, e, ed);
}
/**
* Sets the rotation component of the transformation matrix, looking from `eye` towards
* `target`, and oriented by the up-direction.
*
* @param {Vector3} eye - The eye vector.
* @param {Vector3} target - The target vector.
* @param {Vector3} up - The up vector.
* @return {Matrix4} A reference to this matrix.
*/
lookAt(e, t, i) {
const s = this.elements;
return jt.subVectors(e, t), jt.lengthSq() === 0 && (jt.z = 1), jt.normalize(), ji.crossVectors(i, jt), ji.lengthSq() === 0 && (Math.abs(i.z) === 1 ? jt.x += 1e-4 : jt.z += 1e-4, jt.normalize(), ji.crossVectors(i, jt)), ji.normalize(), zs.crossVectors(jt, ji), s[0] = ji.x, s[4] = zs.x, s[8] = jt.x, s[1] = ji.y, s[5] = zs.y, s[9] = jt.y, s[2] = ji.z, s[6] = zs.z, s[10] = jt.z, this;
}
/**
* Post-multiplies this matrix by the given 4x4 matrix.
*
* @param {Matrix4} m - The matrix to multiply with.
* @return {Matrix4} A reference to this matrix.
*/
multiply(e) {
return this.multiplyMatrices(this, e);
}
/**
* Pre-multiplies this matrix by the given 4x4 matrix.
*
* @param {Matrix4} m - The matrix to multiply with.
* @return {Matrix4} A reference to this matrix.
*/
premultiply(e) {
return this.multiplyMatrices(e, this);
}
/**
* Multiples the given 4x4 matrices and stores the result
* in this matrix.
*
* @param {Matrix4} a - The first matrix.
* @param {Matrix4} b - The second matrix.
* @return {Matrix4} A reference to this matrix.
*/
multiplyMatrices(e, t) {
const i = e.elements, s = t.elements, n = this.elements, a = i[0], o = i[4], l = i[8], c = i[12], h = i[1], u = i[5], d = i[9], f = i[13], g = i[2], v = i[6], m = i[10], p = i[14], y = i[3], _ = i[7], E = i[11], A = i[15], T = s[0], R = s[4], I = s[8], b = s[12], S = s[1], D = s[5], N = s[9], k = s[13], H = s[2], j = s[6], q = s[10], te = s[14], G = s[3], Z = s[7], se = s[11], Pe = s[15];
return n[0] = a * T + o * S + l * H + c * G, n[4] = a * R + o * D + l * j + c * Z, n[8] = a * I + o * N + l * q + c * se, n[12] = a * b + o * k + l * te + c * Pe, n[1] = h * T + u * S + d * H + f * G, n[5] = h * R + u * D + d * j + f * Z, n[9] = h * I + u * N + d * q + f * se, n[13] = h * b + u * k + d * te + f * Pe, n[2] = g * T + v * S + m * H + p * G, n[6] = g * R + v * D + m * j + p * Z, n[10] = g * I + v * N + m * q + p * se, n[14] = g * b + v * k + m * te + p * Pe, n[3] = y * T + _ * S + E * H + A * G, n[7] = y * R + _ * D + E * j + A * Z, n[11] = y * I + _ * N + E * q + A * se, n[15] = y * b + _ * k + E * te + A * Pe, this;
}
/**
* Multiplies every component of the matrix by the given scalar.
*
* @param {number} s - The scalar.
* @return {Matrix4} A reference to this matrix.
*/
multiplyScalar(e) {
const t = this.elements;
return t[0] *= e, t[4] *= e, t[8] *= e, t[12] *= e, t[1] *= e, t[5] *= e, t[9] *= e, t[13] *= e, t[2] *= e, t[6] *= e, t[10] *= e, t[14] *= e, t[3] *= e, t[7] *= e, t[11] *= e, t[15] *= e, this;
}
/**
* Computes and returns the determinant of this matrix.
*
* Based on the method outlined [here](http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.html).
*
* @return {number} The determinant.
*/
determinant() {
const e = this.elements, t = e[0], i = e[4], s = e[8], n = e[12], a = e[1], o = e[5], l = e[9], c = e[13], h = e[2], u = e[6], d = e[10], f = e[14], g = e[3], v = e[7], m = e[11], p = e[15];
return g * (+n * l * u - s * c * u - n * o * d + i * c * d + s * o * f - i * l * f) + v * (+t * l * f - t * c * d + n * a * d - s * a * f + s * c * h - n * l * h) + m * (+t * c * u - t * o * f - n * a * u + i * a * f + n * o * h - i * c * h) + p * (-s * o * h - t * l * u + t * o * d + s * a * u - i * a * d + i * l * h);
}
/**
* Transposes this matrix in place.
*
* @return {Matrix4} A reference to this matrix.
*/
transpose() {
const e = this.elements;
let t;
return t = e[1], e[1] = e[4], e[4] = t, t = e[2], e[2] = e[8], e[8] = t, t = e[6], e[6] = e[9], e[9] = t, t = e[3], e[3] = e[12], e[12] = t, t = e[7], e[7] = e[13], e[13] = t, t = e[11], e[11] = e[14], e[14] = t, this;
}
/**
* Sets the position component for this matrix from the given vector,
* without affecting the rest of the matrix.
*
* @param {number|Vector3} x - The x component of the vector or alternatively the vector object.
* @param {number} y - The y component of the vector.
* @param {number} z - The z component of the vector.
* @return {Matrix4} A reference to this matrix.
*/
setPosition(e, t, i) {
const s = this.elements;
return e.isVector3 ? (s[12] = e.x, s[13] = e.y, s[14] = e.z) : (s[12] = e, s[13] = t, s[14] = i), this;
}
/**
* Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
* You can not invert with a determinant of zero. If you attempt this, the method produces
* a zero matrix instead.
*
* @return {Matrix4} A reference to this matrix.
*/
invert() {
const e = this.elements, t = e[0], i = e[1], s = e[2], n = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8], u = e[9], d = e[10], f = e[11], g = e[12], v = e[13], m = e[14], p = e[15], y = u * m * c - v * d * c + v * l * f - o * m * f - u * l * p + o * d * p, _ = g * d * c - h * m * c - g * l * f + a * m * f + h * l * p - a * d * p, E = h * v * c - g * u * c + g * o * f - a * v * f - h * o * p + a * u * p, A = g * u * l - h * v * l - g * o * d + a * v * d + h * o * m - a * u * m, T = t * y + i * _ + s * E + n * A;
if (T === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
const R = 1 / T;
return e[0] = y * R, e[1] = (v * d * n - u * m * n - v * s * f + i * m * f + u * s * p - i * d * p) * R, e[2] = (o * m * n - v * l * n + v * s * c - i * m * c - o * s * p + i * l * p) * R, e[3] = (u * l * n - o * d * n - u * s * c + i * d * c + o * s * f - i * l * f) * R, e[4] = _ * R, e[5] = (h * m * n - g * d * n + g * s * f - t * m * f - h * s * p + t * d * p) * R, e[6] = (g * l * n - a * m * n - g * s * c + t * m * c + a * s * p - t * l * p) * R, e[7] = (a * d * n - h * l * n + h * s * c - t * d * c - a * s * f + t * l * f) * R, e[8] = E * R, e[9] = (g * u * n - h * v * n - g * i * f + t * v * f + h * i * p - t * u * p) * R, e[10] = (a * v * n - g * o * n + g * i * c - t * v * c - a * i * p + t * o * p) * R, e[11] = (h * o * n - a * u * n - h * i * c + t * u * c + a * i * f - t * o * f) * R, e[12] = A * R, e[13] = (h * v * s - g * u * s + g * i * d - t * v * d - h * i * m + t * u * m) * R, e[14] = (g * o * s - a * v * s - g * i * l + t * v * l + a * i * m - t * o * m) * R, e[15] = (a * u * s - h * o * s + h * i * l - t * u * l - a * i * d + t * o * d) * R, this;
}
/**
* Multiplies the columns of this matrix by the given vector.
*
* @param {Vector3} v - The scale vector.
* @return {Matrix4} A reference to this matrix.
*/
scale(e) {
const t = this.elements, i = e.x, s = e.y, n = e.z;
return t[0] *= i, t[4] *= s, t[8] *= n, t[1] *= i, t[5] *= s, t[9] *= n, t[2] *= i, t[6] *= s, t[10] *= n, t[3] *= i, t[7] *= s, t[11] *= n, this;
}
/**
* Gets the maximum scale value of the three axes.
*
* @return {number} The maximum scale.
*/
getMaxScaleOnAxis() {
const e = this.elements, t = e[0] * e[0] + e[1] * e[1] + e[2] * e[2], i = e[4] * e[4] + e[5] * e[5] + e[6] * e[6], s = e[8] * e[8] + e[9] * e[9] + e[10] * e[10];
return Math.sqrt(Math.max(t, i, s));
}
/**
* Sets this matrix as a translation transform from the given vector.
*
* @param {number|Vector3} x - The amount to translate in the X axis or alternatively a translation vector.
* @param {number} y - The amount to translate in the Y axis.
* @param {number} z - The amount to translate in the z axis.
* @return {Matrix4} A reference to this matrix.
*/
makeTranslation(e, t, i) {
return e.isVector3 ? this.set(
1,
0,
0,
e.x,
0,
1,
0,
e.y,
0,
0,
1,
e.z,
0,
0,
0,
1
) : this.set(
1,
0,
0,
e,
0,
1,
0,
t,
0,
0,
1,
i,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a rotational transformation around the X axis by
* the given angle.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationX(e) {
const t = Math.cos(e), i = Math.sin(e);
return this.set(
1,
0,
0,
0,
0,
t,
-i,
0,
0,
i,
t,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a rotational transformation around the Y axis by
* the given angle.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationY(e) {
const t = Math.cos(e), i = Math.sin(e);
return this.set(
t,
0,
i,
0,
0,
1,
0,
0,
-i,
0,
t,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a rotational transformation around the Z axis by
* the given angle.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationZ(e) {
const t = Math.cos(e), i = Math.sin(e);
return this.set(
t,
-i,
0,
0,
i,
t,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a rotational transformation around the given axis by
* the given angle.
*
* This is a somewhat controversial but mathematically sound alternative to
* rotating via Quaternions. See the discussion [here](https://www.gamedev.net/articles/programming/math-and-physics/do-we-really-need-quaternions-r1199).
*
* @param {Vector3} axis - The normalized rotation axis.
* @param {number} angle - The rotation in radians.
* @return {Matrix4} A reference to this matrix.
*/
makeRotationAxis(e, t) {
const i = Math.cos(t), s = Math.sin(t), n = 1 - i, a = e.x, o = e.y, l = e.z, c = n * a, h = n * o;
return this.set(
c * a + i,
c * o - s * l,
c * l + s * o,
0,
c * o + s * l,
h * o + i,
h * l - s * a,
0,
c * l - s * o,
h * l + s * a,
n * l * l + i,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a scale transformation.
*
* @param {number} x - The amount to scale in the X axis.
* @param {number} y - The amount to scale in the Y axis.
* @param {number} z - The amount to scale in the Z axis.
* @return {Matrix4} A reference to this matrix.
*/
makeScale(e, t, i) {
return this.set(
e,
0,
0,
0,
0,
t,
0,
0,
0,
0,
i,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix as a shear transformation.
*
* @param {number} xy - The amount to shear X by Y.
* @param {number} xz - The amount to shear X by Z.
* @param {number} yx - The amount to shear Y by X.
* @param {number} yz - The amount to shear Y by Z.
* @param {number} zx - The amount to shear Z by X.
* @param {number} zy - The amount to shear Z by Y.
* @return {Matrix4} A reference to this matrix.
*/
makeShear(e, t, i, s, n, a) {
return this.set(
1,
i,
n,
0,
e,
1,
a,
0,
t,
s,
1,
0,
0,
0,
0,
1
), this;
}
/**
* Sets this matrix to the transformation composed of the given position,
* rotation (Quaternion) and scale.
*
* @param {Vector3} position - The position vector.
* @param {Quaternion} quaternion - The rotation as a Quaternion.
* @param {Vector3} scale - The scale vector.
* @return {Matrix4} A reference to this matrix.
*/
compose(e, t, i) {
const s = this.elements, n = t._x, a = t._y, o = t._z, l = t._w, c = n + n, h = a + a, u = o + o, d = n * c, f = n * h, g = n * u, v = a * h, m = a * u, p = o * u, y = l * c, _ = l * h, E = l * u, A = i.x, T = i.y, R = i.z;
return s[0] = (1 - (v + p)) * A, s[1] = (f + E) * A, s[2] = (g - _) * A, s[3] = 0, s[4] = (f - E) * T, s[5] = (1 - (d + p)) * T, s[6] = (m + y) * T, s[7] = 0, s[8] = (g + _) * R, s[9] = (m - y) * R, s[10] = (1 - (d + v)) * R, s[11] = 0, s[12] = e.x, s[13] = e.y, s[14] = e.z, s[15] = 1, this;
}
/**
* Decomposes this matrix into its position, rotation and scale components
* and provides the result in the given objects.
*
* Note: Not all matrices are decomposable in this way. For example, if an
* object has a non-uniformly scaled parent, then the object's world matrix
* may not be decomposable, and this method may not be appropriate.
*
* @param {Vector3} position - The position vector.
* @param {Quaternion} quaternion - The rotation as a Quaternion.
* @param {Vector3} scale - The scale vector.
* @return {Matrix4} A reference to this matrix.
*/
decompose(e, t, i) {
const s = this.elements;
let n = br.set(s[0], s[1], s[2]).length();
const a = br.set(s[4], s[5], s[6]).length(), o = br.set(s[8], s[9], s[10]).length();
this.determinant() < 0 && (n = -n), e.x = s[12], e.y = s[13], e.z = s[14], si.copy(this);
const l = 1 / n, c = 1 / a, h = 1 / o;
return si.elements[0] *= l, si.elements[1] *= l, si.elements[2] *= l, si.elements[4] *= c, si.elements[5] *= c, si.elements[6] *= c, si.elements[8] *= h, si.elements[9] *= h, si.elements[10] *= h, t.setFromRotationMatrix(si), i.x = n, i.y = a, i.z = o, this;
}
/**
* Creates a perspective projection matrix. This is used internally by
* {@link PerspectiveCamera#updateProjectionMatrix}.
* @param {number} left - Left boundary of the viewing frustum at the near plane.
* @param {number} right - Right boundary of the viewing frustum at the near plane.
* @param {number} top - Top boundary of the viewing frustum at the near plane.
* @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
* @param {number} near - The distance from the camera to the near plane.
* @param {number} far - The distance from the camera to the far plane.
* @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
* @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
* @return {Matrix4} A reference to this matrix.
*/
makePerspective(e, t, i, s, n, a, o = bi, l = !1) {
const c = this.elements, h = 2 * n / (t - e), u = 2 * n / (i - s), d = (t + e) / (t - e), f = (i + s) / (i - s);
let g, v;
if (l)
g = n / (a - n), v = a * n / (a - n);
else if (o === bi)
g = -(a + n) / (a - n), v = -2 * a * n / (a - n);
else if (o === Tn)
g = -a / (a - n), v = -a * n / (a - n);
else
throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: " + o);
return c[0] = h, c[4] = 0, c[8] = d, c[12] = 0, c[1] = 0, c[5] = u, c[9] = f, c[13] = 0, c[2] = 0, c[6] = 0, c[10] = g, c[14] = v, c[3] = 0, c[7] = 0, c[11] = -1, c[15] = 0, this;
}
/**
* Creates a orthographic projection matrix. This is used internally by
* {@link OrthographicCamera#updateProjectionMatrix}.
* @param {number} left - Left boundary of the viewing frustum at the near plane.
* @param {number} right - Right boundary of the viewing frustum at the near plane.
* @param {number} top - Top boundary of the viewing frustum at the near plane.
* @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
* @param {number} near - The distance from the camera to the near plane.
* @param {number} far - The distance from the camera to the far plane.
* @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
* @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
* @return {Matrix4} A reference to this matrix.
*/
makeOrthographic(e, t, i, s, n, a, o = bi, l = !1) {
const c = this.elements, h = 2 / (t - e), u = 2 / (i - s), d = -(t + e) / (t - e), f = -(i + s) / (i - s);
let g, v;
if (l)
g = 1 / (a - n), v = a / (a - n);
else if (o === bi)
g = -2 / (a - n), v = -(a + n) / (a - n);
else if (o === Tn)
g = -1 / (a - n), v = -n / (a - n);
else
throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: " + o);
return c[0] = h, c[4] = 0, c[8] = 0, c[12] = d, c[1] = 0, c[5] = u, c[9] = 0, c[13] = f, c[2] = 0, c[6] = 0, c[10] = g, c[14] = v, c[3] = 0, c[7] = 0, c[11] = 0, c[15] = 1, this;
}
/**
* Returns `true` if this matrix is equal with the given one.
*
* @param {Matrix4} matrix - The matrix to test for equality.
* @return {boolean} Whether this matrix is equal with the given one.
*/
equals(e) {
const t = this.elements, i = e.elements;
for (let s = 0; s < 16; s++)
if (t[s] !== i[s]) return !1;
return !0;
}
/**
* Sets the elements of the matrix from the given array.
*
* @param {Array} array - The matrix elements in column-major order.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Matrix4} A reference to this matrix.
*/
fromArray(e, t = 0) {
for (let i = 0; i < 16; i++)
this.elements[i] = e[i + t];
return this;
}
/**
* Writes the elements of this matrix to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the matrix elements in column-major order.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The matrix elements in column-major order.
*/
toArray(e = [], t = 0) {
const i = this.elements;
return e[t] = i[0], e[t + 1] = i[1], e[t + 2] = i[2], e[t + 3] = i[3], e[t + 4] = i[4], e[t + 5] = i[5], e[t + 6] = i[6], e[t + 7] = i[7], e[t + 8] = i[8], e[t + 9] = i[9], e[t + 10] = i[10], e[t + 11] = i[11], e[t + 12] = i[12], e[t + 13] = i[13], e[t + 14] = i[14], e[t + 15] = i[15], e;
}
}
const br = /* @__PURE__ */ new w(), si = /* @__PURE__ */ new Ue(), Qu = /* @__PURE__ */ new w(0, 0, 0), ed = /* @__PURE__ */ new w(1, 1, 1), ji = /* @__PURE__ */ new w(), zs = /* @__PURE__ */ new w(), jt = /* @__PURE__ */ new w(), _l = /* @__PURE__ */ new Ue(), xl = /* @__PURE__ */ new mi();
class gi {
/**
* Constructs a new euler instance.
*
* @param {number} [x=0] - The angle of the x axis in radians.
* @param {number} [y=0] - The angle of the y axis in radians.
* @param {number} [z=0] - The angle of the z axis in radians.
* @param {string} [order=Euler.DEFAULT_ORDER] - A string representing the order that the rotations are applied.
*/
constructor(e = 0, t = 0, i = 0, s = gi.DEFAULT_ORDER) {
this.isEuler = !0, this._x = e, this._y = t, this._z = i, this._order = s;
}
/**
* The angle of the x axis in radians.
*
* @type {number}
* @default 0
*/
get x() {
return this._x;
}
set x(e) {
this._x = e, this._onChangeCallback();
}
/**
* The angle of the y axis in radians.
*
* @type {number}
* @default 0
*/
get y() {
return this._y;
}
set y(e) {
this._y = e, this._onChangeCallback();
}
/**
* The angle of the z axis in radians.
*
* @type {number}
* @default 0
*/
get z() {
return this._z;
}
set z(e) {
this._z = e, this._onChangeCallback();
}
/**
* A string representing the order that the rotations are applied.
*
* @type {string}
* @default 'XYZ'
*/
get order() {
return this._order;
}
set order(e) {
this._order = e, this._onChangeCallback();
}
/**
* Sets the Euler components.
*
* @param {number} x - The angle of the x axis in radians.
* @param {number} y - The angle of the y axis in radians.
* @param {number} z - The angle of the z axis in radians.
* @param {string} [order] - A string representing the order that the rotations are applied.
* @return {Euler} A reference to this Euler instance.
*/
set(e, t, i, s = this._order) {
return this._x = e, this._y = t, this._z = i, this._order = s, this._onChangeCallback(), this;
}
/**
* Returns a new Euler instance with copied values from this instance.
*
* @return {Euler} A clone of this instance.
*/
clone() {
return new this.constructor(this._x, this._y, this._z, this._order);
}
/**
* Copies the values of the given Euler instance to this instance.
*
* @param {Euler} euler - The Euler instance to copy.
* @return {Euler} A reference to this Euler instance.
*/
copy(e) {
return this._x = e._x, this._y = e._y, this._z = e._z, this._order = e._order, this._onChangeCallback(), this;
}
/**
* Sets the angles of this Euler instance from a pure rotation matrix.
*
* @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
* @param {string} [order] - A string representing the order that the rotations are applied.
* @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
* @return {Euler} A reference to this Euler instance.
*/
setFromRotationMatrix(e, t = this._order, i = !0) {
const s = e.elements, n = s[0], a = s[4], o = s[8], l = s[1], c = s[5], h = s[9], u = s[2], d = s[6], f = s[10];
switch (t) {
case "XYZ":
this._y = Math.asin(ze(o, -1, 1)), Math.abs(o) < 0.9999999 ? (this._x = Math.atan2(-h, f), this._z = Math.atan2(-a, n)) : (this._x = Math.atan2(d, c), this._z = 0);
break;
case "YXZ":
this._x = Math.asin(-ze(h, -1, 1)), Math.abs(h) < 0.9999999 ? (this._y = Math.atan2(o, f), this._z = Math.atan2(l, c)) : (this._y = Math.atan2(-u, n), this._z = 0);
break;
case "ZXY":
this._x = Math.asin(ze(d, -1, 1)), Math.abs(d) < 0.9999999 ? (this._y = Math.atan2(-u, f), this._z = Math.atan2(-a, c)) : (this._y = 0, this._z = Math.atan2(l, n));
break;
case "ZYX":
this._y = Math.asin(-ze(u, -1, 1)), Math.abs(u) < 0.9999999 ? (this._x = Math.atan2(d, f), this._z = Math.atan2(l, n)) : (this._x = 0, this._z = Math.atan2(-a, c));
break;
case "YZX":
this._z = Math.asin(ze(l, -1, 1)), Math.abs(l) < 0.9999999 ? (this._x = Math.atan2(-h, c), this._y = Math.atan2(-u, n)) : (this._x = 0, this._y = Math.atan2(o, f));
break;
case "XZY":
this._z = Math.asin(-ze(a, -1, 1)), Math.abs(a) < 0.9999999 ? (this._x = Math.atan2(d, c), this._y = Math.atan2(o, n)) : (this._x = Math.atan2(-h, f), this._y = 0);
break;
default:
Se("Euler: .setFromRotationMatrix() encountered an unknown order: " + t);
}
return this._order = t, i === !0 && this._onChangeCallback(), this;
}
/**
* Sets the angles of this Euler instance from a normalized quaternion.
*
* @param {Quaternion} q - A normalized Quaternion.
* @param {string} [order] - A string representing the order that the rotations are applied.
* @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
* @return {Euler} A reference to this Euler instance.
*/
setFromQuaternion(e, t, i) {
return _l.makeRotationFromQuaternion(e), this.setFromRotationMatrix(_l, t, i);
}
/**
* Sets the angles of this Euler instance from the given vector.
*
* @param {Vector3} v - The vector.
* @param {string} [order] - A string representing the order that the rotations are applied.
* @return {Euler} A reference to this Euler instance.
*/
setFromVector3(e, t = this._order) {
return this.set(e.x, e.y, e.z, t);
}
/**
* Resets the euler angle with a new order by creating a quaternion from this
* euler angle and then setting this euler angle with the quaternion and the
* new order.
*
* Warning: This discards revolution information.
*
* @param {string} [newOrder] - A string representing the new order that the rotations are applied.
* @return {Euler} A reference to this Euler instance.
*/
reorder(e) {
return xl.setFromEuler(this), this.setFromQuaternion(xl, e);
}
/**
* Returns `true` if this Euler instance is equal with the given one.
*
* @param {Euler} euler - The Euler instance to test for equality.
* @return {boolean} Whether this Euler instance is equal with the given one.
*/
equals(e) {
return e._x === this._x && e._y === this._y && e._z === this._z && e._order === this._order;
}
/**
* Sets this Euler instance's components to values from the given array. The first three
* entries of the array are assign to the x,y and z components. An optional fourth entry
* defines the Euler order.
*
* @param {Array} array - An array holding the Euler component values.
* @return {Euler} A reference to this Euler instance.
*/
fromArray(e) {
return this._x = e[0], this._y = e[1], this._z = e[2], e[3] !== void 0 && (this._order = e[3]), this._onChangeCallback(), this;
}
/**
* Writes the components of this Euler instance to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array} [array=[]] - The target array holding the Euler components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array} The Euler components.
*/
toArray(e = [], t = 0) {
return e[t] = this._x, e[t + 1] = this._y, e[t + 2] = this._z, e[t + 3] = this._order, e;
}
_onChange(e) {
return this._onChangeCallback = e, this;
}
_onChangeCallback() {
}
*[Symbol.iterator]() {
yield this._x, yield this._y, yield this._z, yield this._order;
}
}
gi.DEFAULT_ORDER = "XYZ";
class Bo {
/**
* Constructs a new layers instance, with membership
* initially set to layer `0`.
*/
constructor() {
this.mask = 1;
}
/**
* Sets membership to the given layer, and remove membership all other layers.
*
* @param {number} layer - The layer to set.
*/
set(e) {
this.mask = (1 << e | 0) >>> 0;
}
/**
* Adds membership of the given layer.
*
* @param {number} layer - The layer to enable.
*/
enable(e) {
this.mask |= 1 << e | 0;
}
/**
* Adds membership to all layers.
*/
enableAll() {
this.mask = -1;
}
/**
* Toggles the membership of the given layer.
*
* @param {number} layer - The layer to toggle.
*/
toggle(e) {
this.mask ^= 1 << e | 0;
}
/**
* Removes membership of the given layer.
*
* @param {number} layer - The layer to enable.
*/
disable(e) {
this.mask &= ~(1 << e | 0);
}
/**
* Removes the membership from all layers.
*/
disableAll() {
this.mask = 0;
}
/**
* Returns `true` if this and the given layers object have at least one
* layer in common.
*
* @param {Layers} layers - The layers to test.
* @return {boolean } Whether this and the given layers object have at least one layer in common or not.
*/
test(e) {
return (this.mask & e.mask) !== 0;
}
/**
* Returns `true` if the given layer is enabled.
*
* @param {number} layer - The layer to test.
* @return {boolean } Whether the given layer is enabled or not.
*/
isEnabled(e) {
return (this.mask & (1 << e | 0)) !== 0;
}
}
let td = 0;
const yl = /* @__PURE__ */ new w(), Tr = /* @__PURE__ */ new mi(), Li = /* @__PURE__ */ new Ue(), ks = /* @__PURE__ */ new w(), os = /* @__PURE__ */ new w(), id = /* @__PURE__ */ new w(), rd = /* @__PURE__ */ new mi(), Ml = /* @__PURE__ */ new w(1, 0, 0), Sl = /* @__PURE__ */ new w(0, 1, 0), bl = /* @__PURE__ */ new w(0, 0, 1), Tl = { type: "added" }, sd = { type: "removed" }, Er = { type: "childadded", child: null }, Yn = { type: "childremoved", child: null };
class dt extends gr {
/**
* Constructs a new 3D object.
*/
constructor() {
super(), this.isObject3D = !0, Object.defineProperty(this, "id", { value: td++ }), this.uuid = di(), this.name = "", this.type = "Object3D", this.parent = null, this.children = [], this.up = dt.DEFAULT_UP.clone();
const e = new w(), t = new gi(), i = new mi(), s = new w(1, 1, 1);
function n() {
i.setFromEuler(t, !1);
}
function a() {
t.setFromQuaternion(i, void 0, !1);
}
t._onChange(n), i._onChange(a), Object.defineProperties(this, {
/**
* Represents the object's local position.
*
* @name Object3D#position
* @type {Vector3}
* @default (0,0,0)
*/
position: {
configurable: !0,
enumerable: !0,
value: e
},
/**
* Represents the object's local rotation as Euler angles, in radians.
*
* @name Object3D#rotation
* @type {Euler}
* @default (0,0,0)
*/
rotation: {
configurable: !0,
enumerable: !0,
value: t
},
/**
* Represents the object's local rotation as Quaternions.
*
* @name Object3D#quaternion
* @type {Quaternion}
*/
quaternion: {
configurable: !0,
enumerable: !0,
value: i
},
/**
* Represents the object's local scale.
*
* @name Object3D#scale
* @type {Vector3}
* @default (1,1,1)
*/
scale: {
configurable: !0,
enumerable: !0,
value: s
},
/**
* Represents the object's model-view matrix.
*
* @name Object3D#modelViewMatrix
* @type {Matrix4}
*/
modelViewMatrix: {
value: new Ue()
},
/**
* Represents the object's normal matrix.
*
* @name Object3D#normalMatrix
* @type {Matrix3}
*/
normalMatrix: {
value: new Be()
}
}), this.matrix = new Ue(), this.matrixWorld = new Ue(), this.matrixAutoUpdate = dt.DEFAULT_MATRIX_AUTO_UPDATE, this.matrixWorldAutoUpdate = dt.DEFAULT_MATRIX_WORLD_AUTO_UPDATE, this.matrixWorldNeedsUpdate = !1, this.layers = new Bo(), this.visible = !0, this.castShadow = !1, this.receiveShadow = !1, this.frustumCulled = !0, this.renderOrder = 0, this.animations = [], this.customDepthMaterial = void 0, this.customDistanceMaterial = void 0, this.userData = {};
}
/**
* A callback that is executed immediately before a 3D object is rendered to a shadow map.
*
* @param {Renderer|WebGLRenderer} renderer - The renderer.
* @param {Object3D} object - The 3D object.
* @param {Camera} camera - The camera that is used to render the scene.
* @param {Camera} shadowCamera - The shadow camera.
* @param {BufferGeometry} geometry - The 3D object's geometry.
* @param {Material} depthMaterial - The depth material.
* @param {Object} group - The geometry group data.
*/
onBeforeShadow() {
}
/**
* A callback that is executed immediately after a 3D object is rendered to a shadow map.
*
* @param {Renderer|WebGLRenderer} renderer - The renderer.
* @param {Object3D} object - The 3D object.
* @param {Camera} camera - The camera that is used to render the scene.
* @param {Camera} shadowCamera - The shadow camera.
* @param {BufferGeometry} geometry - The 3D object's geometry.
* @param {Material} depthMaterial - The depth material.
* @param {Object} group - The geometry group data.
*/
onAfterShadow() {
}
/**
* A callback that is executed immediately before a 3D object is rendered.
*
* @param {Renderer|WebGLRenderer} renderer - The renderer.
* @param {Object3D} object - The 3D object.
* @param {Camera} camera - The camera that is used to render the scene.
* @param {BufferGeometry} geometry - The 3D object's geometry.
* @param {Material} material - The 3D object's material.
* @param {Object} group - The geometry group data.
*/
onBeforeRender() {
}
/**
* A callback that is executed immediately after a 3D object is rendered.
*
* @param {Renderer|WebGLRenderer} renderer - The renderer.
* @param {Object3D} object - The 3D object.
* @param {Camera} camera - The camera that is used to render the scene.
* @param {BufferGeometry} geometry - The 3D object's geometry.
* @param {Material} material - The 3D object's material.
* @param {Object} group - The geometry group data.
*/
onAfterRender() {
}
/**
* Applies the given transformation matrix to the object and updates the object's position,
* rotation and scale.
*
* @param {Matrix4} matrix - The transformation matrix.
*/
applyMatrix4(e) {
this.matrixAutoUpdate && this.updateMatrix(), this.matrix.premultiply(e), this.matrix.decompose(this.position, this.quaternion, this.scale);
}
/**
* Applies a rotation represented by given the quaternion to the 3D object.
*
* @param {Quaternion} q - The quaternion.
* @return {Object3D} A reference to this instance.
*/
applyQuaternion(e) {
return this.quaternion.premultiply(e), this;
}
/**
* Sets the given rotation represented as an axis/angle couple to the 3D object.
*
* @param {Vector3} axis - The (normalized) axis vector.
* @param {number} angle - The angle in radians.
*/
setRotationFromAxisAngle(e, t) {
this.quaternion.setFromAxisAngle(e, t);
}
/**
* Sets the given rotation represented as Euler angles to the 3D object.
*
* @param {Euler} euler - The Euler angles.
*/
setRotationFromEuler(e) {
this.quaternion.setFromEuler(e, !0);
}
/**
* Sets the given rotation represented as rotation matrix to the 3D object.
*
* @param {Matrix4} m - Although a 4x4 matrix is expected, the upper 3x3 portion must be
* a pure rotation matrix (i.e, unscaled).
*/
setRotationFromMatrix(e) {
this.quaternion.setFromRotationMatrix(e);
}
/**
* Sets the given rotation represented as a Quaternion to the 3D object.
*
* @param {Quaternion} q - The Quaternion
*/
setRotationFromQuaternion(e) {
this.quaternion.copy(e);
}
/**
* Rotates the 3D object along an axis in local space.
*
* @param {Vector3} axis - The (normalized) axis vector.
* @param {number} angle - The angle in radians.
* @return {Object3D} A reference to this instance.
*/
rotateOnAxis(e, t) {
return Tr.setFromAxisAngle(e, t), this.quaternion.multiply(Tr), this;
}
/**
* Rotates the 3D object along an axis in world space.
*
* @param {Vector3} axis - The (normalized) axis vector.
* @param {number} angle - The angle in radians.
* @return {Object3D} A reference to this instance.
*/
rotateOnWorldAxis(e, t) {
return Tr.setFromAxisAngle(e, t), this.quaternion.premultiply(Tr), this;
}
/**
* Rotates the 3D object around its X axis in local space.
*
* @param {number} angle - The angle in radians.
* @return {Object3D} A reference to this instance.
*/
rotateX(e) {
return this.rotateOnAxis(Ml, e);
}
/**
* Rotates the 3D object around its Y axis in local space.
*
* @param {number} angle - The angle in radians.
* @return {Object3D} A reference to this instance.
*/
rotateY(e) {
return this.rotateOnAxis(Sl, e);
}
/**
* Rotates the 3D object around its Z axis in local space.
*
* @param {number} angle - The angle in radians.
* @return {Object3D} A reference to this instance.
*/
rotateZ(e) {
return this.rotateOnAxis(bl, e);
}
/**
* Translate the 3D object by a distance along the given axis in local space.
*
* @param {Vector3} axis - The (normalized) axis vector.
* @param {number} distance - The distance in world units.
* @return {Object3D} A reference to this instance.
*/
translateOnAxis(e, t) {
return yl.copy(e).applyQuaternion(this.quaternion), this.position.add(yl.multiplyScalar(t)), this;
}
/**
* Translate the 3D object by a distance along its X-axis in local space.
*
* @param {number} distance - The distance in world units.
* @return {Object3D} A reference to this instance.
*/
translateX(e) {
return this.translateOnAxis(Ml, e);
}
/**
* Translate the 3D object by a distance along its Y-axis in local space.
*
* @param {number} distance - The distance in world units.
* @return {Object3D} A reference to this instance.
*/
translateY(e) {
return this.translateOnAxis(Sl, e);
}
/**
* Translate the 3D object by a distance along its Z-axis in local space.
*
* @param {number} distance - The distance in world units.
* @return {Object3D} A reference to this instance.
*/
translateZ(e) {
return this.translateOnAxis(bl, e);
}
/**
* Converts the given vector from this 3D object's local space to world space.
*
* @param {Vector3} vector - The vector to convert.
* @return {Vector3} The converted vector.
*/
localToWorld(e) {
return this.updateWorldMatrix(!0, !1), e.applyMatrix4(this.matrixWorld);
}
/**
* Converts the given vector from this 3D object's word space to local space.
*
* @param {Vector3} vector - The vector to convert.
* @return {Vector3} The converted vector.
*/
worldToLocal(e) {
return this.updateWorldMatrix(!0, !1), e.applyMatrix4(Li.copy(this.matrixWorld).invert());
}
/**
* Rotates the object to face a point in world space.
*
* This method does not support objects having non-uniformly-scaled parent(s).
*
* @param {number|Vector3} x - The x coordinate in world space. Alternatively, a vector representing a position in world space
* @param {number} [y] - The y coordinate in world space.
* @param {number} [z] - The z coordinate in world space.
*/
lookAt(e, t, i) {
e.isVector3 ? ks.copy(e) : ks.set(e, t, i);
const s = this.parent;
this.updateWorldMatrix(!0, !1), os.setFromMatrixPosition(this.matrixWorld), this.isCamera || this.isLight ? Li.lookAt(os, ks, this.up) : Li.lookAt(ks, os, this.up), this.quaternion.setFromRotationMatrix(Li), s && (Li.extractRotation(s.matrixWorld), Tr.setFromRotationMatrix(Li), this.quaternion.premultiply(Tr.invert()));
}
/**
* Adds the given 3D object as a child to this 3D object. An arbitrary number of
* objects may be added. Any current parent on an object passed in here will be
* removed, since an object can have at most one parent.
*
* @fires Object3D#added
* @fires Object3D#childadded
* @param {Object3D} object - The 3D object to add.
* @return {Object3D} A reference to this instance.
*/
add(e) {
if (arguments.length > 1) {
for (let t = 0; t < arguments.length; t++)
this.add(arguments[t]);
return this;
}
return e === this ? (He("Object3D.add: object can't be added as a child of itself.", e), this) : (e && e.isObject3D ? (e.removeFromParent(), e.parent = this, this.children.push(e), e.dispatchEvent(Tl), Er.child = e, this.dispatchEvent(Er), Er.child = null) : He("Object3D.add: object not an instance of THREE.Object3D.", e), this);
}
/**
* Removes the given 3D object as child from this 3D object.
* An arbitrary number of objects may be removed.
*
* @fires Object3D#removed
* @fires Object3D#childremoved
* @param {Object3D} object - The 3D object to remove.
* @return {Object3D} A reference to this instance.
*/
remove(e) {
if (arguments.length > 1) {
for (let i = 0; i < arguments.length; i++)
this.remove(arguments[i]);
return this;
}
const t = this.children.indexOf(e);
return t !== -1 && (e.parent = null, this.children.splice(t, 1), e.dispatchEvent(sd), Yn.child = e, this.dispatchEvent(Yn), Yn.child = null), this;
}
/**
* Removes this 3D object from its current parent.
*
* @fires Object3D#removed
* @fires Object3D#childremoved
* @return {Object3D} A reference to this instance.
*/
removeFromParent() {
const e = this.parent;
return e !== null && e.remove(this), this;
}
/**
* Removes all child objects.
*
* @fires Object3D#removed
* @fires Object3D#childremoved
* @return {Object3D} A reference to this instance.
*/
clear() {
return this.remove(...this.children);
}
/**
* Adds the given 3D object as a child of this 3D object, while maintaining the object's world
* transform. This method does not support scene graphs having non-uniformly-scaled nodes(s).
*
* @fires Object3D#added
* @fires Object3D#childadded
* @param {Object3D} object - The 3D object to attach.
* @return {Object3D} A reference to this instance.
*/
attach(e) {
return this.updateWorldMatrix(!0, !1), Li.copy(this.matrixWorld).invert(), e.parent !== null && (e.parent.updateWorldMatrix(!0, !1), Li.multiply(e.parent.matrixWorld)), e.applyMatrix4(Li), e.removeFromParent(), e.parent = this, this.children.push(e), e.updateWorldMatrix(!1, !0), e.dispatchEvent(Tl), Er.child = e, this.dispatchEvent(Er), Er.child = null, this;
}
/**
* Searches through the 3D object and its children, starting with the 3D object
* itself, and returns the first with a matching ID.
*
* @param {number} id - The id.
* @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
*/
getObjectById(e) {
return this.getObjectByProperty("id", e);
}
/**
* Searches through the 3D object and its children, starting with the 3D object
* itself, and returns the first with a matching name.
*
* @param {string} name - The name.
* @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
*/
getObjectByName(e) {
return this.getObjectByProperty("name", e);
}
/**
* Searches through the 3D object and its children, starting with the 3D object
* itself, and returns the first with a matching property value.
*
* @param {string} name - The name of the property.
* @param {any} value - The value.
* @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
*/
getObjectByProperty(e, t) {
if (this[e] === t) return this;
for (let i = 0, s = this.children.length; i < s; i++) {
const n = this.children[i].getObjectByProperty(e, t);
if (n !== void 0)
return n;
}
}
/**
* Searches through the 3D object and its children, starting with the 3D object
* itself, and returns all 3D objects with a matching property value.
*
* @param {string} name - The name of the property.
* @param {any} value - The value.
* @param {Array} result - The method stores the result in this array.
* @return {Array} The found 3D objects.
*/
getObjectsByProperty(e, t, i = []) {
this[e] === t && i.push(this);
const s = this.children;
for (let n = 0, a = s.length; n < a; n++)
s[n].getObjectsByProperty(e, t, i);
return i;
}
/**
* Returns a vector representing the position of the 3D object in world space.
*
* @param {Vector3} target - The target vector the result is stored to.
* @return {Vector3} The 3D object's position in world space.
*/
getWorldPosition(e) {
return this.updateWorldMatrix(!0, !1), e.setFromMatrixPosition(this.matrixWorld);
}
/**
* Returns a Quaternion representing the position of the 3D object in world space.
*
* @param {Quaternion} target - The target Quaternion the result is stored to.
* @return {Quaternion} The 3D object's rotation in world space.
*/
getWorldQuaternion(e) {
return this.updateWorldMatrix(!0, !1), this.matrixWorld.decompose(os, e, id), e;
}
/**
* Returns a vector representing the scale of the 3D object in world space.
*
* @param {Vector3} target - The target vector the result is stored to.
* @return {Vector3} The 3D object's scale in world space.
*/
getWorldScale(e) {
return this.updateWorldMatrix(!0, !1), this.matrixWorld.decompose(os, rd, e), e;
}
/**
* Returns a vector representing the ("look") direction of the 3D object in world space.
*
* @param {Vector3} target - The target vector the result is stored to.
* @return {Vector3} The 3D object's direction in world space.
*/
getWorldDirection(e) {
this.updateWorldMatrix(!0, !1);
const t = this.matrixWorld.elements;
return e.set(t[8], t[9], t[10]).normalize();
}
/**
* Abstract method to get intersections between a casted ray and this
* 3D object. Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
* implement this method in order to use raycasting.
*
* @abstract
* @param {Raycaster} raycaster - The raycaster.
* @param {Array