Try dragging the title bar or resizing from the bottom-right corner.
'
},
menu: {
info: "Info",
home: "Home"
},
tree: {
searchPlaceholder: "Please enter content to search"
},
constructTree: {
title: "Construct Tree"
},
tab: {
component: "Component",
system: "System",
space: "Space"
},
panel: {
property: {
title: "Component Details",
base: "Basic Info",
material: "Material",
advanced: "Advanced",
tab: {
props: "Properties",
material: "Material"
}
}
},
measure: {
btnName: "Measure",
dialogTitle: "Measure",
modes: {
distance: "Distance",
minDistance: "Min Distance",
angle: "Angle",
elevation: "Elevation",
volume: "Volume",
laserDistance: "Laser Distance",
slope: "Slope",
spaceVolume: "Space Volume"
},
actions: {
expand: "Expand",
collapse: "Collapse",
clearAll: "Clear All",
settings: "Settings"
},
labels: {
currentMode: "Mode:",
x: "X:",
y: "Y:",
z: "Z:",
value: {
distance: "Distance:",
minDistance: "Min Distance:",
angle: "Angle:",
elevation: "Elevation:",
volume: "Volume:",
laserDistance: "Laser Distance:",
slope: "Slope:",
spaceVolume: "Space Volume:"
}
},
units: {
mm: "mm",
cm: "cm",
m: "m",
km: "km",
deg: "°",
m3: "m³",
percent: "%"
},
settings: {
title: "Settings",
unit: "Unit:",
precision: "Precision:",
hint: "Distance, min distance and elevation use this unit by default; angle and volume use their own units.",
save: "Save",
cancel: "Cancel"
}
},
sectionPlane: {
dialogTitle: "Plane Section",
actions: {
hide: "Hide",
reverse: "Reverse",
reset: "Reset"
}
},
sectionAxis: {
dialogTitle: "Axis Section",
actions: {
hide: "Hide",
reverse: "Reverse",
axisX: "X",
axisY: "Y",
axisZ: "Z"
}
},
sectionBox: {
dialogTitle: "Section Box",
actions: {
hide: "Hide",
reverse: "Reverse",
fitToModel: "Fit",
reset: "Reset"
},
axes: {
x: "X",
y: "Y",
z: "Z"
}
},
walkControl: {
speed: "Speed:",
gravity: "Gravity",
collision: "Collision",
characterModel: {
label: "Construction Worker",
constructionWorker: "Construction Worker",
officeMale: "Office Male"
},
walkMode: {
label: "Walk Mode",
walk: "Walk",
run: "Run"
},
exit: "Exit",
path: {
dialogTitle: "Path Walk"
}
},
map: {
dialogTitle: "Map"
}
};
class Ef {
currentLocale = "zh-CN";
messages = {
"zh-CN": wf,
"en-US": Sf
};
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 n = this.messages[this.currentLocale];
for (const i of t)
if (n && typeof n == "object" && i in n)
n = n[i];
else
return e;
return n;
}
/**
* 订阅变更
*/
subscribe(e) {
return this.listeners.push(e), () => {
this.listeners = this.listeners.filter((t) => t !== e);
};
}
notifyListeners() {
this.listeners.forEach((e) => e(this.currentLocale));
}
}
const Vt = new Ef(), Re = (s) => Vt.t(s), Oc = {
name: "dark",
primary: "#0078d4",
primaryHover: "#0063b1",
// 修改:背景色统一为浅灰,不再跟随深色模式变黑
background: "#f5f5f5",
panelBackground: "rgba(30, 30, 30, 0.9)",
textPrimary: "#ffffff",
textSecondary: "#cccccc",
border: "#444444",
icon: "#cccccc",
iconActive: "#ffffff",
componentBackground: "transparent",
componentHover: "#4e4d4dff",
componentActive: "rgba(255, 255, 255, 0.1)"
}, Tf = {
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 Cf {
currentTheme = Oc;
listeners = [];
constructor() {
}
/**
* 获取当前主题配置
*/
getTheme() {
return this.currentTheme;
}
/**
* 切换预设主题
* @param themeName 'dark' | 'light'
*/
setTheme(e) {
e === "light" ? this.applyTheme(Tf) : this.applyTheme(Oc);
}
/**
* 应用自定义主题配置
* @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 st = new Cf();
class Yl {
container;
options;
groups = [];
activeBtnIds = /* @__PURE__ */ new Set();
btnRefs = /* @__PURE__ */ new Map();
dropdownElement = null;
hoverTimeout = null;
customColors = /* @__PURE__ */ new Set();
// 记录用户自定义的颜色属性
unsubscribeLocale = null;
unsubscribeTheme = null;
engine = 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((i) => {
e[i] && this.customColors.add(i);
}), this.initContainer(), this.applyStyles();
}
setEngine(e) {
this.engine = e;
}
emit(e, t) {
this.engine ? this.engine.emit(e, t) : console.warn("[BimButtonGroup] Engine not set, cannot emit event:", e);
}
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(), this.setupEventInterception(this.container);
}
/**
* 设置事件拦截,防止事件冒泡到下层元素(如 3D 引擎)
*/
setupEventInterception(e) {
const t = (i) => {
i.stopPropagation();
};
[
"click",
"dblclick",
"contextmenu",
"wheel",
"mousedown",
"mouseup",
"mousemove",
"touchstart",
"touchend",
"touchmove",
"pointerdown",
"pointerup",
"pointermove",
"pointerenter",
"pointerleave",
"pointerover",
"pointerout"
].forEach((i) => {
e.addEventListener(i, t, { passive: !1 });
});
}
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 n = "20px";
switch (e) {
case "top-left":
t.top = n, t.left = n;
break;
case "top-center":
t.top = n, t.left = "50%", t.transform = "translateX(-50%)";
break;
case "top-right":
t.top = n, t.right = n;
break;
case "bottom-left":
t.bottom = n, t.left = n;
break;
case "bottom-center":
t.bottom = n, t.left = "50%", t.transform = "translateX(-50%)";
break;
case "bottom-right":
t.bottom = n, t.right = n;
break;
case "left-center":
t.left = n, t.top = "50%", t.transform = "translateY(-50%)";
break;
case "right-center":
t.right = n, 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), document.querySelectorAll(".opt-btn-dropdown").forEach((n) => {
const i = n.style;
this.options.iconColor && i.setProperty("--bim-icon-color", this.options.iconColor), this.options.iconActiveColor && i.setProperty("--bim-icon-active-color", this.options.iconActiveColor), this.options.textColor && i.setProperty("--bim-btn-text-color", this.options.textColor), this.options.textActiveColor && i.setProperty("--bim-btn-text-active-color", this.options.textActiveColor), this.options.btnBackgroundColor && i.setProperty("--bim-btn-bg", this.options.btnBackgroundColor), this.options.btnHoverColor && i.setProperty("--bim-btn-hover-bg", this.options.btnHoverColor), this.options.btnActiveColor && i.setProperty("--bim-btn-active-bg", this.options.btnActiveColor);
});
}
/**
* 设置主题的primary颜色(用于边框等)
*/
setPrimaryColor(e) {
this.container.style.setProperty("--bim-primary-color", e), document.querySelectorAll(".opt-btn-dropdown").forEach((n) => {
n.style.setProperty("--bim-primary-color", e);
});
}
/**
* 设置主题颜色
* 只会应用到没有被用户自定义的颜色属性上
*/
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(([n, i]) => {
const r = n;
this.customColors.has(r) || (this.options[r] = i);
}), this.applyStyles(), this.setPrimaryColor(e.primary);
}
/**
* 直接设置颜色(强制覆盖)
* 设置的颜色会被标记为自定义,后续的 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 = Vt.subscribe(() => {
this.setLocales();
}), this.unsubscribeTheme = st.subscribe((e) => {
this.setTheme(e);
});
}
setLocales() {
this.render();
}
addGroup(e, t) {
if (this.groups.some((i) => i.id === e)) return;
const n = { id: e, buttons: [] };
if (t) {
const i = this.groups.findIndex((r) => r.id === t);
i !== -1 ? this.groups.splice(i, 0, n) : this.groups.push(n);
} else
this.groups.push(n);
}
addButton(e) {
const { groupId: t, parentId: n } = e, i = this.groups.find((a) => a.id === t);
if (!i) return;
const r = { ...e, children: e.children || [] };
if (n) {
const a = this.findButton(i.buttons, n);
a && (a.children || (a.children = []), a.children.push(r));
} else
i.buttons.push(r);
}
findButton(e, t) {
for (const n of e) {
if (n.id === t) return n;
if (n.children) {
const i = this.findButton(n.children, t);
if (i) return i;
}
}
}
render() {
this.container.innerHTML = "", this.btnRefs.clear(), this.groups.forEach((e, t) => {
const n = this.renderGroup(e, t, this.groups.length);
this.container.appendChild(n);
});
}
renderGroup(e, t, n) {
const i = document.createElement("div");
return i.className = "bim-btn-group-section", t < n - 1 && i.classList.add("has-divider"), e.buttons.forEach((r) => {
if (this.isVisible(r.id)) {
const a = this.renderButton(r);
i.appendChild(a);
}
}), i;
}
renderButton(e) {
const t = document.createElement("div");
t.className = "opt-btn-wrapper";
const n = document.createElement("div");
n.className = "opt-btn", e.isActive && this.activeBtnIds.add(e.id), (e.align || this.options.align || "vertical") === "horizontal" ? n.classList.add("align-horizontal") : n.classList.add("align-vertical"), this.activeBtnIds.has(e.id) && n.classList.add("active"), e.disabled && n.classList.add("disabled"), this.options.showLabel && e.label || (n.classList.add("no-label"), e.label && (n.title = Re(e.label)));
const a = e.iconSize || 32, o = e.minWidth || 50;
n.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), n.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 = Re(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() && n.appendChild(c), n.addEventListener("click", () => this.handleClick(e)), n.addEventListener("mouseenter", () => this.handleMouseEnter(e, n)), n.addEventListener("mouseleave", () => this.handleMouseLeave()), this.btnRefs.set(e.id, n), t.appendChild(n), t;
}
/**
* 设置按钮的激活状态
* @param id 按钮 ID
* @param active 可选,如果不传则切换(toggle)当前状态
*/
setBtnActive(e, t) {
const n = this.findButtonById(e);
if (!n) return;
const i = t !== void 0 ? t : !this.activeBtnIds.has(e);
i ? this.activeBtnIds.add(e) : this.activeBtnIds.delete(e), n.isActive = i, this.updateButtonState(e);
}
handleClick(e) {
if (!e.disabled && (!e.children || e.children.length === 0)) {
if (e.keepActive) {
const n = !this.activeBtnIds.has(e.id);
this.setBtnActive(e.id, n), n && e.exclusive && e.groupId && this.deactivateExclusiveSiblings(e);
}
this.closeDropdown(), e.onClick && e.onClick(e);
}
}
/**
* 互斥关闭同范围内的其它已激活按钮,并触发它们的 onClick
* @param button 当前被激活的按钮
*/
deactivateExclusiveSiblings(e) {
const t = this.groups.find((n) => n.id === e.groupId);
if (t) {
if (e.parentId) {
const i = this.findButton(t.buttons, e.parentId)?.children || [];
for (const r of i)
r && r.id !== e.id && r.parentId === e.parentId && r.groupId === e.groupId && this.activeBtnIds.has(r.id) && (this.setBtnActive(r.id, !1), r.onClick && r.onClick(r));
return;
}
for (const n of t.buttons)
n.id !== e.id && n.groupId === e.groupId && (n.parentId || this.activeBtnIds.has(n.id) && (this.setBtnActive(n.id, !1), n.onClick && n.onClick(n)));
}
}
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 n = document.createElement("div");
n.className = "opt-btn-dropdown", this.options.backgroundColor && n.style.setProperty("--bim-toolbar-bg", this.options.backgroundColor);
const i = n.style;
this.options.iconColor && i.setProperty("--bim-icon-color", this.options.iconColor), this.options.iconActiveColor && i.setProperty("--bim-icon-active-color", this.options.iconActiveColor), this.options.textColor && i.setProperty("--bim-btn-text-color", this.options.textColor), this.options.textActiveColor && i.setProperty("--bim-btn-text-active-color", this.options.textActiveColor), this.options.btnBackgroundColor && i.setProperty("--bim-btn-bg", this.options.btnBackgroundColor), this.options.btnHoverColor && i.setProperty("--bim-btn-hover-bg", this.options.btnHoverColor), this.options.btnActiveColor && i.setProperty("--bim-btn-active-bg", this.options.btnActiveColor);
const r = t.getBoundingClientRect(), a = this.options.expand || "down";
this.options.direction === "row" ? n.style.flexDirection = "column" : n.style.flexDirection = "row", document.body.appendChild(n), this.setupEventInterception(n), e.children.forEach((l) => {
if (this.isVisible(l.id)) {
const c = this.renderDropdownItem(l);
n.appendChild(c);
}
});
const o = n.getBoundingClientRect();
a === "up" ? (n.style.bottom = window.innerHeight - r.top + 8 + "px", n.style.left = r.left + (r.width - o.width) / 2 + "px") : a === "down" ? (n.style.top = r.bottom + 8 + "px", n.style.left = r.left + (r.width - o.width) / 2 + "px") : a === "right" ? (n.style.top = r.top + (r.height - o.height) / 2 + "px", n.style.left = r.right + 8 + "px") : a === "left" && (n.style.top = r.top + (r.height - o.height) / 2 + "px", n.style.right = window.innerWidth - r.left + 8 + "px"), n.addEventListener("mouseenter", () => {
this.hoverTimeout && clearTimeout(this.hoverTimeout);
}), n.addEventListener("mouseleave", () => this.handleMouseLeave()), this.dropdownElement = n;
}
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"), (this.activeBtnIds.has(e.id) || e.isActive) && t.classList.add("active");
const i = e.iconSize || 32, r = e.minWidth;
r && (t.style.minWidth = `${r}px`);
const a = document.createElement("div");
if (a.className = "opt-btn-icon", a.style.width = `${i}px`, a.style.height = `${i}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 = Re(e.label), t.appendChild(o);
} else e.label && (t.title = Re(e.label));
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 n = this.findButtonById(t);
if (!n) return;
this.options.showLabel && n.label ? (e.classList.remove("no-label"), e.removeAttribute("title")) : (e.classList.add("no-label"), n.label && (e.title = Re(n.label)));
});
}
findButtonById(e) {
for (const t of this.groups) {
const n = this.findButton(t.buttons, e);
if (n) return n;
}
}
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 Af extends Yl {
/**
* 重写初始化,加载默认按钮
*/
async init() {
await super.init();
const { createHomeButton: e } = await Promise.resolve().then(() => DM), { createZoomBoxButton: t } = await Promise.resolve().then(() => NM), { createWalkMenuButton: n } = await Promise.resolve().then(() => kM), { createMapButton: i } = await Promise.resolve().then(() => OM), { createPropertyButton: r } = await Promise.resolve().then(() => zM), { createSettingButton: a } = await Promise.resolve().then(() => VM), { createInfoButton: o } = await Promise.resolve().then(() => XM), { createFullscreenButton: l } = await Promise.resolve().then(() => ZM), { createMeasureButton: c } = await Promise.resolve().then(() => YM), { createSectionMenuButton: h } = await Promise.resolve().then(() => $M), { createSectionPlaneButton: u } = await Promise.resolve().then(() => QM), { createSectionAxisButton: f } = await Promise.resolve().then(() => tw), { createSectionBoxButton: d } = await Promise.resolve().then(() => iw);
this.addGroup("group-1"), this.engine ? (this.addButton(e(this.engine)), this.addButton(t(this.engine)), this.addButton(c(this.engine)), this.addButton(h(this.engine)), this.addButton(u(this.engine)), this.addButton(f(this.engine)), this.addButton(d(this.engine)), this.addButton(n(this.engine)), this.addButton(i(this.engine)), this.addButton(r(this.engine)), this.addGroup("group-2"), this.addButton(a(this.engine)), this.addButton(o(this.engine)), this.addButton(l(this.engine))) : console.warn("[Toolbar] Engine not available when creating buttons."), this.render();
}
}
class cn {
engine;
constructor(e) {
this.engine = e;
}
/**
* Helper to send events easily
*/
emit(e, t) {
this.engine.emit(e, t);
}
/**
* Helper to listen to events easily
* Returns an unsubscribe function
*/
on(e, t) {
return this.engine.on(e, t);
}
}
class Rf extends cn {
toolbar = null;
toolbarContainer = null;
container;
constructor(e, t) {
super(e), this.container = t, 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 Af({
container: this.toolbarContainer,
showLabel: !0,
direction: "row",
position: "bottom-center",
// 底部居中
align: "vertical",
// 图标在上
expand: "up"
// 向上展开
}), this.toolbar.setEngine(this.engine), 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);
}
setBtnActive(e, t) {
this.toolbar?.setBtnActive(e, t);
}
setVisible(e) {
this.toolbarContainer && (this.toolbarContainer.style.visibility = e ? "visible" : "hidden");
}
setBackgroundColor(e) {
this.toolbar?.setBackgroundColor(e);
}
setColors(e) {
this.toolbar?.setColors(e);
}
/**
* 隐藏工具栏
*/
hide() {
this.toolbarContainer && (this.toolbarContainer.style.display = "none");
}
/**
* 显示工具栏
*/
show() {
this.toolbarContainer && (this.toolbarContainer.style.display = "");
}
/**
* 获取工具栏容器
*/
getContainer() {
return this.toolbarContainer;
}
}
class Pf extends cn {
groups = /* @__PURE__ */ new Map();
container;
constructor(e, t) {
super(e), this.container = t;
}
create(e, t) {
const n = new Yl({
container: this.container,
...t
});
return n.setEngine(this.engine), n.init(), this.groups.set(e, n), n;
}
get(e) {
return this.groups.get(e);
}
updateTheme(e) {
this.groups.forEach((t) => t.setTheme(e));
}
destroy() {
this.groups.forEach((e) => e.destroy()), this.groups.clear();
}
}
class zu {
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 = st.subscribe((e) => {
this.setTheme(e);
}), this.unsubscribeLocale = Vt.subscribe(() => {
this.setLocales();
}));
}
setLocales() {
if (this.options.title) {
const e = this.header.querySelector(".bim-dialog-title");
e && (e.textContent = Re(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), this.options.minWidth && (e.style.minWidth = `${this.options.minWidth}px`);
const n = document.createElement("div");
n.className = "bim-dialog-header", this.options.draggable && n.classList.add("draggable");
const i = document.createElement("span");
i.className = "bim-dialog-title", i.textContent = this.options.title ? Re(this.options.title) : "";
const r = document.createElement("span");
r.className = "bim-dialog-close", r.innerHTML = "×", r.onclick = () => {
this.close();
}, n.appendChild(i), n.appendChild(r);
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(n), 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, n) {
t !== void 0 && (t === "auto" || t === "fit-content" ? e.style.width = t : e.style.width = typeof t == "number" ? `${t}px` : t), n !== void 0 && (n === "auto" || n === "fit-content" ? e.style.height = n : e.style.height = typeof n == "number" ? `${n}px` : n);
}
/**
* 根据内容自动调整弹窗宽度
* @param recenter 是否重新计算定位(例如保持居中),默认 true
*/
fitWidth(e = !1) {
this.element.style.width = "fit-content", e && this.initPosition();
}
/**
* 根据内容自动调整弹窗高度
*
* 设计说明:
* - 主要用于“内容展开/收起”场景(比如测量面板展开后,Dialog 高度跟随变化)
* - 默认不改变用户拖拽后的当前位置,只做边界夹紧,避免弹窗超出容器
*
* @param recenter 是否根据 options.position 重新定位(默认 false)
*/
fitHeight(e = !1) {
this.element.style.height = "auto";
const t = this.element.getBoundingClientRect().height, n = this.options.minHeight ?? 100, i = this.container.clientHeight || 0;
let r = Math.max(n, t);
i > 0 && (r = Math.min(r, i)), this.element.style.height = `${r}px`, e ? this.initPosition() : this.clampToContainer();
}
/**
* 边界夹紧:保持当前 left/top 不变的前提下,确保弹窗不超出容器
* 说明:用于 fitHeight / fitWidth 后的“尺寸变化”场景,避免弹窗被裁切。
*/
clampToContainer() {
const e = this.container.clientWidth, t = this.container.clientHeight, n = this.element.offsetWidth, i = this.element.offsetHeight, r = this.element.offsetLeft, a = this.element.offsetTop, o = Math.max(0, e - n), l = Math.max(0, t - i), c = Math.max(0, Math.min(r, o)), h = Math.max(0, Math.min(a, l));
this.element.style.left = `${c}px`, this.element.style.top = `${h}px`;
}
/**
* 初始化弹窗位置
*/
initPosition() {
const e = this.options.position, t = this.element.getBoundingClientRect();
let n = 0, i = 0;
const r = this.container.clientWidth, a = this.container.clientHeight, o = t.width, l = t.height;
if (typeof e == "object" && "x" in e)
n = e.x, i = e.y;
else
switch (e) {
case "center":
n = (r - o) / 2, i = (a - l) / 2;
break;
case "top-left":
n = 0, i = 0;
break;
case "top-center":
n = (r - o) / 2, i = 0;
break;
case "top-right":
n = r - o, i = 0;
break;
case "left-center":
n = 0, i = (a - l) / 2;
break;
case "right-center":
n = r - o, i = (a - l) / 2;
break;
case "bottom-left":
n = 0, i = a - l;
break;
case "bottom-center":
n = (r - o) / 2, i = a - l;
break;
case "bottom-right":
n = r - o, i = a - l;
break;
default:
n = (r - o) / 2, i = (a - l) / 2;
}
n = Math.max(0, Math.min(n, r - o)), i = Math.max(0, Math.min(i, a - l)), this.element.style.left = `${n}px`, this.element.style.top = `${i}px`;
}
/**
* 初始化拖拽功能 (性能优化 + 解决粘手)
*/
initDrag() {
let e = 0, t = 0, n = 0, i = 0, r = 0, a = 0, o = 0, l = 0;
const c = (f) => {
f.preventDefault(), f.stopPropagation(), e = f.clientX, t = f.clientY, n = this.element.offsetLeft, i = this.element.offsetTop, r = 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 = (f) => {
f.preventDefault(), f.stopPropagation(), !this.rafId && (this.rafId = requestAnimationFrame(() => {
const d = f.clientX - e, p = f.clientY - t;
let g = n + d, v = i + p;
const m = r - o, _ = a - l;
g = Math.max(0, Math.min(g, m)), v = Math.max(0, Math.min(v, _)), this.element.style.left = `${g}px`, this.element.style.top = `${v}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, n = 0, i = 0, r = 0;
const a = (c) => {
c.preventDefault(), c.stopPropagation(), t = c.clientX, n = c.clientY, i = this.element.offsetWidth, r = 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 - n, f = Math.max(this.options.minWidth || 100, i + h), d = Math.max(this.options.minHeight || 50, r + u);
this.element.style.width = `${f}px`, this.element.style.height = `${d}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 Lf extends zu {
/**
* 构造函数
* @param container 父容器
*/
constructor(e) {
const t = document.createElement("div");
t.className = "bim-info-dialog-content";
const n = document.createElement("h3");
n.textContent = "Model Information";
const i = document.createElement("ul");
i.innerHTML = `
Name: Sample Project
Version: 1.0.0
Date: ${(/* @__PURE__ */ new Date()).toLocaleDateString()}
Status:Active
`;
const r = document.createElement("button");
r.textContent = "Update Status", r.style.marginTop = "10px", r.onclick = () => {
alert("Status updated!");
}, t.appendChild(n), t.appendChild(i), t.appendChild(r), 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 Df extends cn {
/** 弹窗挂载的父容器 */
container;
/** 活跃的弹窗实例列表 */
activeDialogs = [];
/**
* 构造函数
* @param engine 引擎实例
* @param container 弹窗挂载的目标容器
*/
constructor(e, t) {
super(e), this.container = t, this.on("ui:open-dialog", (n) => {
console.log("[DialogManager] Received open-dialog event:", n), n.id === "info" && this.showInfoDialog();
});
}
/**
* 创建一个通用弹窗
* @param options 弹窗配置选项(不需要传 container,自动使用管理器绑定的容器)
* @returns BimDialog 实例
*/
create(e) {
const t = new zu({
container: this.container,
...e,
onClose: () => {
this.activeDialogs = this.activeDialogs.filter((n) => n !== t), e.onClose && e.onClose();
}
});
return t.setTheme(st.getTheme()), this.activeDialogs.push(t), t;
}
/**
* 显示二次封装的模型信息弹窗
* 演示如何调用特定的业务弹窗组件
*/
showInfoDialog() {
new Lf(this.container);
}
/**
* 响应全局主题变更
* @param theme 全局主题配置
*/
updateTheme(e) {
this.activeDialogs.forEach((t) => {
t.setTheme && t.setTheme(e);
});
}
destroy() {
this.activeDialogs.forEach((e) => e.destroy()), this.activeDialogs = [];
}
}
const Kl = "182", as = { ROTATE: 0, DOLLY: 1, PAN: 2 }, ss = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }, If = 0, Fc = 1, Nf = 2, aa = 1, Hu = 2, Gs = 3, Gn = 0, rn = 1, Ht = 2, Ot = 0, os = 1, Oo = 2, zc = 3, Hc = 4, Vu = 5, Cn = 100, Uf = 101, kf = 102, Bf = 103, Of = 104, Ws = 200, Ff = 201, zf = 202, Hf = 203, Fo = 204, zo = 205, Ho = 206, Vf = 207, Vo = 208, Gf = 209, Wf = 210, Xf = 211, jf = 212, Zf = 213, qf = 214, Go = 0, Wo = 1, Xo = 2, us = 3, jo = 4, Zo = 5, qo = 6, Yo = 7, Ea = 0, Yf = 1, Kf = 2, Vn = 0, $l = 1, Jl = 2, Ql = 3, Ta = 4, ec = 5, tc = 6, nc = 7, Vc = "attached", $f = "detached", Gu = 300, Di = 301, ds = 302, Ko = 303, $o = 304, Ca = 306, Wn = 1e3, zn = 1001, va = 1002, Pt = 1003, Wu = 1004, Xs = 1005, Nt = 1006, oa = 1007, ii = 1008, sn = 1009, Xu = 1010, ju = 1011, tr = 1012, ic = 1013, Xn = 1014, bn = 1015, Jt = 1016, sc = 1017, rc = 1018, fs = 1020, Zu = 35902, qu = 35899, Yu = 1021, Ku = 1022, mn = 1023, ai = 1026, gi = 1027, ac = 1028, oc = 1029, ps = 1030, lc = 1031, cc = 1033, la = 33776, ca = 33777, ha = 33778, ua = 33779, Jo = 35840, Qo = 35841, el = 35842, tl = 35843, nl = 36196, il = 37492, sl = 37496, rl = 37488, al = 37489, ol = 37490, ll = 37491, cl = 37808, hl = 37809, ul = 37810, dl = 37811, fl = 37812, pl = 37813, ml = 37814, gl = 37815, vl = 37816, _l = 37817, xl = 37818, bl = 37819, yl = 37820, Ml = 37821, wl = 36492, Sl = 36494, El = 36495, Tl = 36283, Cl = 36284, Al = 36285, Rl = 36286, nr = 2300, ir = 2301, Ga = 2302, Gc = 2400, Wc = 2401, Xc = 2402, Jf = 2500, Qf = 0, $u = 1, Pl = 2, ep = 3200, ur = 0, tp = 1, mi = "", pt = "srgb", Tt = "srgb-linear", _a = "linear", at = "srgb", Vi = 7680, jc = 519, np = 512, ip = 513, sp = 514, hc = 515, rp = 516, ap = 517, uc = 518, op = 519, Ll = 35044, Zc = "300 es", Hn = 2e3, xa = 2001;
function Ju(s) {
for (let e = s.length - 1; e >= 0; --e)
if (s[e] >= 65535) return !0;
return !1;
}
function lp(s) {
return ArrayBuffer.isView(s) && !(s instanceof DataView);
}
function sr(s) {
return document.createElementNS("http://www.w3.org/1999/xhtml", s);
}
function cp() {
const s = sr("canvas");
return s.style.display = "block", s;
}
const qc = {};
function ba(...s) {
const e = "THREE." + s.shift();
console.log(e, ...s);
}
function He(...s) {
const e = "THREE." + s.shift();
console.warn(e, ...s);
}
function Xe(...s) {
const e = "THREE." + s.shift();
console.error(e, ...s);
}
function rr(...s) {
const e = s.join(" ");
e in qc || (qc[e] = !0, He(...s));
}
function hp(s, e, t) {
return new Promise(function(n, i) {
function r() {
switch (s.clientWaitSync(e, s.SYNC_FLUSH_COMMANDS_BIT, 0)) {
case s.WAIT_FAILED:
i();
break;
case s.TIMEOUT_EXPIRED:
setTimeout(r, t);
break;
default:
n();
}
}
setTimeout(r, t);
});
}
class Bi {
/**
* 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 n = this._listeners;
n[e] === void 0 && (n[e] = []), n[e].indexOf(t) === -1 && n[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 n = this._listeners;
return n === void 0 ? !1 : n[e] !== void 0 && n[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 n = this._listeners;
if (n === void 0) return;
const i = n[e];
if (i !== void 0) {
const r = i.indexOf(t);
r !== -1 && i.splice(r, 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 n = t[e.type];
if (n !== void 0) {
e.target = this;
const i = n.slice(0);
for (let r = 0, a = i.length; r < a; r++)
i[r].call(this, e);
e.target = null;
}
}
}
const Gt = ["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 Yc = 1234567;
const Ys = Math.PI / 180, ms = 180 / Math.PI;
function Mn() {
const s = Math.random() * 4294967295 | 0, e = Math.random() * 4294967295 | 0, t = Math.random() * 4294967295 | 0, n = Math.random() * 4294967295 | 0;
return (Gt[s & 255] + Gt[s >> 8 & 255] + Gt[s >> 16 & 255] + Gt[s >> 24 & 255] + "-" + Gt[e & 255] + Gt[e >> 8 & 255] + "-" + Gt[e >> 16 & 15 | 64] + Gt[e >> 24 & 255] + "-" + Gt[t & 63 | 128] + Gt[t >> 8 & 255] + "-" + Gt[t >> 16 & 255] + Gt[t >> 24 & 255] + Gt[n & 255] + Gt[n >> 8 & 255] + Gt[n >> 16 & 255] + Gt[n >> 24 & 255]).toLowerCase();
}
function Qe(s, e, t) {
return Math.max(e, Math.min(t, s));
}
function dc(s, e) {
return (s % e + e) % e;
}
function up(s, e, t, n, i) {
return n + (s - e) * (i - n) / (t - e);
}
function dp(s, e, t) {
return s !== e ? (t - s) / (e - s) : 0;
}
function Ks(s, e, t) {
return (1 - t) * s + t * e;
}
function fp(s, e, t, n) {
return Ks(s, e, 1 - Math.exp(-t * n));
}
function pp(s, e = 1) {
return e - Math.abs(dc(s, e * 2) - e);
}
function mp(s, e, t) {
return s <= e ? 0 : s >= t ? 1 : (s = (s - e) / (t - e), s * s * (3 - 2 * s));
}
function gp(s, e, t) {
return s <= e ? 0 : s >= t ? 1 : (s = (s - e) / (t - e), s * s * s * (s * (s * 6 - 15) + 10));
}
function vp(s, e) {
return s + Math.floor(Math.random() * (e - s + 1));
}
function _p(s, e) {
return s + Math.random() * (e - s);
}
function xp(s) {
return s * (0.5 - Math.random());
}
function bp(s) {
s !== void 0 && (Yc = s);
let e = Yc += 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 yp(s) {
return s * Ys;
}
function Mp(s) {
return s * ms;
}
function wp(s) {
return (s & s - 1) === 0 && s !== 0;
}
function Sp(s) {
return Math.pow(2, Math.ceil(Math.log(s) / Math.LN2));
}
function Ep(s) {
return Math.pow(2, Math.floor(Math.log(s) / Math.LN2));
}
function Tp(s, e, t, n, i) {
const r = Math.cos, a = Math.sin, o = r(t / 2), l = a(t / 2), c = r((e + n) / 2), h = a((e + n) / 2), u = r((e - n) / 2), f = a((e - n) / 2), d = r((n - e) / 2), p = a((n - e) / 2);
switch (i) {
case "XYX":
s.set(o * h, l * u, l * f, o * c);
break;
case "YZY":
s.set(l * f, o * h, l * u, o * c);
break;
case "ZXZ":
s.set(l * u, l * f, o * h, o * c);
break;
case "XZX":
s.set(o * h, l * p, l * d, o * c);
break;
case "YXY":
s.set(l * d, o * h, l * p, o * c);
break;
case "ZYZ":
s.set(l * p, l * d, o * h, o * c);
break;
default:
He("MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: " + i);
}
}
function An(s, e) {
switch (e.constructor) {
case Float32Array:
return s;
case Uint32Array:
return s / 4294967295;
case Uint16Array:
return s / 65535;
case Uint8Array:
return s / 255;
case Int32Array:
return Math.max(s / 2147483647, -1);
case Int16Array:
return Math.max(s / 32767, -1);
case Int8Array:
return Math.max(s / 127, -1);
default:
throw new Error("Invalid component type.");
}
}
function ct(s, e) {
switch (e.constructor) {
case Float32Array:
return s;
case Uint32Array:
return Math.round(s * 4294967295);
case Uint16Array:
return Math.round(s * 65535);
case Uint8Array:
return Math.round(s * 255);
case Int32Array:
return Math.round(s * 2147483647);
case Int16Array:
return Math.round(s * 32767);
case Int8Array:
return Math.round(s * 127);
default:
throw new Error("Invalid component type.");
}
}
const Qu = {
DEG2RAD: Ys,
RAD2DEG: ms,
/**
* Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
* (universally unique identifier).
*
* @static
* @method
* @return {string} The UUID.
*/
generateUUID: Mn,
/**
* 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: Qe,
/**
* 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: dc,
/**
* 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: up,
/**
* 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: dp,
/**
* 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: Ks,
/**
* 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: fp,
/**
* 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: pp,
/**
* 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: mp,
/**
* 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: gp,
/**
* 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: vp,
/**
* 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: _p,
/**
* 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: xp,
/**
* 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: bp,
/**
* Converts degrees to radians.
*
* @static
* @method
* @param {number} degrees - A value in degrees.
* @return {number} The converted value in radians.
*/
degToRad: yp,
/**
* Converts radians to degrees.
*
* @static
* @method
* @param {number} radians - A value in radians.
* @return {number} The converted value in degrees.
*/
radToDeg: Mp,
/**
* 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: wp,
/**
* 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: Sp,
/**
* 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: Ep,
/**
* 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: Tp,
/**
* 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: ct,
/**
* 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: An
};
class fe {
/**
* 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) {
fe.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, n = this.y, i = e.elements;
return this.x = i[0] * t + i[3] * n + i[6], this.y = i[1] * t + i[4] * n + i[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 = Qe(this.x, e.x, t.x), this.y = Qe(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 = Qe(this.x, e, t), this.y = Qe(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 n = this.length();
return this.divideScalar(n || 1).multiplyScalar(Qe(n, 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 n = this.dot(e) / t;
return Math.acos(Qe(n, -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, n = this.y - e.y;
return t * t + n * n;
}
/**
* 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, n) {
return this.x = e.x + (t.x - e.x) * n, this.y = e.y + (t.y - e.y) * n, 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 n = Math.cos(t), i = Math.sin(t), r = this.x - e.x, a = this.y - e.y;
return this.x = r * n - a * i + e.x, this.y = r * i + a * n + 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 Pn {
/**
* 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, n = 0, i = 1) {
this.isQuaternion = !0, this._x = e, this._y = t, this._z = n, this._w = i;
}
/**
* 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, n, i, r, a, o) {
let l = n[i + 0], c = n[i + 1], h = n[i + 2], u = n[i + 3], f = r[a + 0], d = r[a + 1], p = r[a + 2], g = r[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] = f, e[t + 1] = d, e[t + 2] = p, e[t + 3] = g;
return;
}
if (u !== g || l !== f || c !== d || h !== p) {
let v = l * f + c * d + h * p + u * g;
v < 0 && (f = -f, d = -d, p = -p, g = -g, v = -v);
let m = 1 - o;
if (v < 0.9995) {
const _ = Math.acos(v), x = Math.sin(_);
m = Math.sin(m * _) / x, o = Math.sin(o * _) / x, l = l * m + f * o, c = c * m + d * o, h = h * m + p * o, u = u * m + g * o;
} else {
l = l * m + f * o, c = c * m + d * o, h = h * m + p * o, u = u * m + g * o;
const _ = 1 / Math.sqrt(l * l + c * c + h * h + u * u);
l *= _, c *= _, h *= _, u *= _;
}
}
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, n, i, r, a) {
const o = n[i], l = n[i + 1], c = n[i + 2], h = n[i + 3], u = r[a], f = r[a + 1], d = r[a + 2], p = r[a + 3];
return e[t] = o * p + h * u + l * d - c * f, e[t + 1] = l * p + h * f + c * u - o * d, e[t + 2] = c * p + h * d + o * f - l * u, e[t + 3] = h * p - o * u - l * f - c * d, 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, n, i) {
return this._x = e, this._y = t, this._z = n, this._w = i, 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 n = e._x, i = e._y, r = e._z, a = e._order, o = Math.cos, l = Math.sin, c = o(n / 2), h = o(i / 2), u = o(r / 2), f = l(n / 2), d = l(i / 2), p = l(r / 2);
switch (a) {
case "XYZ":
this._x = f * h * u + c * d * p, this._y = c * d * u - f * h * p, this._z = c * h * p + f * d * u, this._w = c * h * u - f * d * p;
break;
case "YXZ":
this._x = f * h * u + c * d * p, this._y = c * d * u - f * h * p, this._z = c * h * p - f * d * u, this._w = c * h * u + f * d * p;
break;
case "ZXY":
this._x = f * h * u - c * d * p, this._y = c * d * u + f * h * p, this._z = c * h * p + f * d * u, this._w = c * h * u - f * d * p;
break;
case "ZYX":
this._x = f * h * u - c * d * p, this._y = c * d * u + f * h * p, this._z = c * h * p - f * d * u, this._w = c * h * u + f * d * p;
break;
case "YZX":
this._x = f * h * u + c * d * p, this._y = c * d * u + f * h * p, this._z = c * h * p - f * d * u, this._w = c * h * u - f * d * p;
break;
case "XZY":
this._x = f * h * u - c * d * p, this._y = c * d * u - f * h * p, this._z = c * h * p + f * d * u, this._w = c * h * u + f * d * p;
break;
default:
He("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 n = t / 2, i = Math.sin(n);
return this._x = e.x * i, this._y = e.y * i, this._z = e.z * i, this._w = Math.cos(n), 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, n = t[0], i = t[4], r = t[8], a = t[1], o = t[5], l = t[9], c = t[2], h = t[6], u = t[10], f = n + o + u;
if (f > 0) {
const d = 0.5 / Math.sqrt(f + 1);
this._w = 0.25 / d, this._x = (h - l) * d, this._y = (r - c) * d, this._z = (a - i) * d;
} else if (n > o && n > u) {
const d = 2 * Math.sqrt(1 + n - o - u);
this._w = (h - l) / d, this._x = 0.25 * d, this._y = (i + a) / d, this._z = (r + c) / d;
} else if (o > u) {
const d = 2 * Math.sqrt(1 + o - n - u);
this._w = (r - c) / d, this._x = (i + a) / d, this._y = 0.25 * d, this._z = (l + h) / d;
} else {
const d = 2 * Math.sqrt(1 + u - n - o);
this._w = (a - i) / d, this._x = (r + c) / d, this._y = (l + h) / d, this._z = 0.25 * d;
}
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 n = e.dot(t) + 1;
return n < 1e-8 ? (n = 0, Math.abs(e.x) > Math.abs(e.z) ? (this._x = -e.y, this._y = e.x, this._z = 0, this._w = n) : (this._x = 0, this._y = -e.z, this._z = e.y, this._w = n)) : (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 = n), 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(Qe(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 n = this.angleTo(e);
if (n === 0) return this;
const i = Math.min(1, t / n);
return this.slerp(e, i), 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 n = e._x, i = e._y, r = e._z, a = e._w, o = t._x, l = t._y, c = t._z, h = t._w;
return this._x = n * h + a * o + i * c - r * l, this._y = i * h + a * l + r * o - n * c, this._z = r * h + a * c + n * l - i * o, this._w = a * h - n * o - i * l - r * 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 n = e._x, i = e._y, r = e._z, a = e._w, o = this.dot(e);
o < 0 && (n = -n, i = -i, r = -r, 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 + n * t, this._y = this._y * l + i * t, this._z = this._z * l + r * t, this._w = this._w * l + a * t, this._onChangeCallback();
} else
this._x = this._x * l + n * t, this._y = this._y * l + i * t, this._z = this._z * l + r * 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, n) {
return this.copy(e).slerp(t, n);
}
/**
* 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(), n = Math.random(), i = Math.sqrt(1 - n), r = Math.sqrt(n);
return this.set(
i * Math.sin(e),
i * Math.cos(e),
r * Math.sin(t),
r * 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 L {
/**
* 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, n = 0) {
L.prototype.isVector3 = !0, this.x = e, this.y = t, this.z = n;
}
/**
* 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, n) {
return n === void 0 && (n = this.z), this.x = e, this.y = t, this.z = n, 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(Kc.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(Kc.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, n = this.y, i = this.z, r = e.elements;
return this.x = r[0] * t + r[3] * n + r[6] * i, this.y = r[1] * t + r[4] * n + r[7] * i, this.z = r[2] * t + r[5] * n + r[8] * i, 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, n = this.y, i = this.z, r = e.elements, a = 1 / (r[3] * t + r[7] * n + r[11] * i + r[15]);
return this.x = (r[0] * t + r[4] * n + r[8] * i + r[12]) * a, this.y = (r[1] * t + r[5] * n + r[9] * i + r[13]) * a, this.z = (r[2] * t + r[6] * n + r[10] * i + r[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, n = this.y, i = this.z, r = e.x, a = e.y, o = e.z, l = e.w, c = 2 * (a * i - o * n), h = 2 * (o * t - r * i), u = 2 * (r * n - a * t);
return this.x = t + l * c + a * u - o * h, this.y = n + l * h + o * c - r * u, this.z = i + l * u + r * 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, n = this.y, i = this.z, r = e.elements;
return this.x = r[0] * t + r[4] * n + r[8] * i, this.y = r[1] * t + r[5] * n + r[9] * i, this.z = r[2] * t + r[6] * n + r[10] * i, 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 = Qe(this.x, e.x, t.x), this.y = Qe(this.y, e.y, t.y), this.z = Qe(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 = Qe(this.x, e, t), this.y = Qe(this.y, e, t), this.z = Qe(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 n = this.length();
return this.divideScalar(n || 1).multiplyScalar(Qe(n, 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;
}
/**
* 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, n) {
return this.x = e.x + (t.x - e.x) * n, this.y = e.y + (t.y - e.y) * n, this.z = e.z + (t.z - e.z) * n, 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 n = e.x, i = e.y, r = e.z, a = t.x, o = t.y, l = t.z;
return this.x = i * l - r * o, this.y = r * a - n * l, this.z = n * o - i * 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 n = e.dot(this) / t;
return this.copy(e).multiplyScalar(n);
}
/**
* 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 Wa.copy(this).projectOnVector(e), this.sub(Wa);
}
/**
* 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(Wa.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 n = this.dot(e) / t;
return Math.acos(Qe(n, -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, n = this.y - e.y, i = this.z - e.z;
return t * t + n * n + i * i;
}
/**
* 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, n) {
const i = Math.sin(t) * e;
return this.x = i * Math.sin(n), this.y = Math.cos(t) * e, this.z = i * Math.cos(n), 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, n) {
return this.x = e * Math.sin(t), this.y = n, 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(), n = this.setFromMatrixColumn(e, 1).length(), i = this.setFromMatrixColumn(e, 2).length();
return this.x = t, this.y = n, this.z = i, 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, n = Math.sqrt(1 - t * t);
return this.x = n * Math.cos(e), this.y = t, this.z = n * Math.sin(e), this;
}
*[Symbol.iterator]() {
yield this.x, yield this.y, yield this.z;
}
}
const Wa = /* @__PURE__ */ new L(), Kc = /* @__PURE__ */ new Pn();
class Je {
/**
* 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, n, i, r, a, o, l, c) {
Je.prototype.isMatrix3 = !0, this.elements = [
1,
0,
0,
0,
1,
0,
0,
0,
1
], e !== void 0 && this.set(e, t, n, i, r, 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, n, i, r, a, o, l, c) {
const h = this.elements;
return h[0] = e, h[1] = i, h[2] = o, h[3] = t, h[4] = r, h[5] = l, h[6] = n, 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, n = e.elements;
return t[0] = n[0], t[1] = n[1], t[2] = n[2], t[3] = n[3], t[4] = n[4], t[5] = n[5], t[6] = n[6], t[7] = n[7], t[8] = n[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, n) {
return e.setFromMatrix3Column(this, 0), t.setFromMatrix3Column(this, 1), n.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 n = e.elements, i = t.elements, r = this.elements, a = n[0], o = n[3], l = n[6], c = n[1], h = n[4], u = n[7], f = n[2], d = n[5], p = n[8], g = i[0], v = i[3], m = i[6], _ = i[1], x = i[4], M = i[7], T = i[2], A = i[5], P = i[8];
return r[0] = a * g + o * _ + l * T, r[3] = a * v + o * x + l * A, r[6] = a * m + o * M + l * P, r[1] = c * g + h * _ + u * T, r[4] = c * v + h * x + u * A, r[7] = c * m + h * M + u * P, r[2] = f * g + d * _ + p * T, r[5] = f * v + d * x + p * A, r[8] = f * m + d * M + p * P, 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], n = e[1], i = e[2], r = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8];
return t * a * h - t * o * c - n * r * h + n * o * l + i * r * c - i * 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], n = e[1], i = e[2], r = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8], u = h * a - o * c, f = o * l - h * r, d = c * r - a * l, p = t * u + n * f + i * d;
if (p === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
const g = 1 / p;
return e[0] = u * g, e[1] = (i * c - h * n) * g, e[2] = (o * n - i * a) * g, e[3] = f * g, e[4] = (h * t - i * l) * g, e[5] = (i * r - o * t) * g, e[6] = d * g, e[7] = (n * l - c * t) * g, e[8] = (a * t - n * r) * g, 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, n, i, r, a, o) {
const l = Math.cos(r), c = Math.sin(r);
return this.set(
n * l,
n * c,
-n * (l * a + c * o) + a + e,
-i * c,
i * l,
-i * (-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(Xa.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(Xa.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(Xa.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), n = Math.sin(e);
return this.set(
t,
-n,
0,
n,
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, n = e.elements;
for (let i = 0; i < 9; i++)
if (t[i] !== n[i]) 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 n = 0; n < 9; n++)
this.elements[n] = e[n + 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 n = this.elements;
return e[t] = n[0], e[t + 1] = n[1], e[t + 2] = n[2], e[t + 3] = n[3], e[t + 4] = n[4], e[t + 5] = n[5], e[t + 6] = n[6], e[t + 7] = n[7], e[t + 8] = n[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 Xa = /* @__PURE__ */ new Je(), $c = /* @__PURE__ */ new Je().set(
0.4123908,
0.3575843,
0.1804808,
0.212639,
0.7151687,
0.0721923,
0.0193308,
0.1191948,
0.9505322
), Jc = /* @__PURE__ */ new Je().set(
3.2409699,
-1.5373832,
-0.4986108,
-0.9692436,
1.8759675,
0.0415551,
0.0556301,
-0.203977,
1.0569715
);
function Cp() {
const s = {
enabled: !0,
workingColorSpace: Tt,
/**
* 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(i, r, a) {
return this.enabled === !1 || r === a || !r || !a || (this.spaces[r].transfer === at && (i.r = ri(i.r), i.g = ri(i.g), i.b = ri(i.b)), this.spaces[r].primaries !== this.spaces[a].primaries && (i.applyMatrix3(this.spaces[r].toXYZ), i.applyMatrix3(this.spaces[a].fromXYZ)), this.spaces[a].transfer === at && (i.r = ls(i.r), i.g = ls(i.g), i.b = ls(i.b))), i;
},
workingToColorSpace: function(i, r) {
return this.convert(i, this.workingColorSpace, r);
},
colorSpaceToWorking: function(i, r) {
return this.convert(i, r, this.workingColorSpace);
},
getPrimaries: function(i) {
return this.spaces[i].primaries;
},
getTransfer: function(i) {
return i === mi ? _a : this.spaces[i].transfer;
},
getToneMappingMode: function(i) {
return this.spaces[i].outputColorSpaceConfig.toneMappingMode || "standard";
},
getLuminanceCoefficients: function(i, r = this.workingColorSpace) {
return i.fromArray(this.spaces[r].luminanceCoefficients);
},
define: function(i) {
Object.assign(this.spaces, i);
},
// Internal APIs
_getMatrix: function(i, r, a) {
return i.copy(this.spaces[r].toXYZ).multiply(this.spaces[a].fromXYZ);
},
_getDrawingBufferColorSpace: function(i) {
return this.spaces[i].outputColorSpaceConfig.drawingBufferColorSpace;
},
_getUnpackColorSpace: function(i = this.workingColorSpace) {
return this.spaces[i].workingColorSpaceConfig.unpackColorSpace;
},
// Deprecated
fromWorkingColorSpace: function(i, r) {
return rr("ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace()."), s.workingToColorSpace(i, r);
},
toWorkingColorSpace: function(i, r) {
return rr("ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking()."), s.colorSpaceToWorking(i, r);
}
}, e = [0.64, 0.33, 0.3, 0.6, 0.15, 0.06], t = [0.2126, 0.7152, 0.0722], n = [0.3127, 0.329];
return s.define({
[Tt]: {
primaries: e,
whitePoint: n,
transfer: _a,
toXYZ: $c,
fromXYZ: Jc,
luminanceCoefficients: t,
workingColorSpaceConfig: { unpackColorSpace: pt },
outputColorSpaceConfig: { drawingBufferColorSpace: pt }
},
[pt]: {
primaries: e,
whitePoint: n,
transfer: at,
toXYZ: $c,
fromXYZ: Jc,
luminanceCoefficients: t,
outputColorSpaceConfig: { drawingBufferColorSpace: pt }
}
}), s;
}
const nt = /* @__PURE__ */ Cp();
function ri(s) {
return s < 0.04045 ? s * 0.0773993808 : Math.pow(s * 0.9478672986 + 0.0521327014, 2.4);
}
function ls(s) {
return s < 31308e-7 ? s * 12.92 : 1.055 * Math.pow(s, 0.41666) - 0.055;
}
let Gi;
class Ap {
/**
* 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 n;
if (e instanceof HTMLCanvasElement)
n = e;
else {
Gi === void 0 && (Gi = sr("canvas")), Gi.width = e.width, Gi.height = e.height;
const i = Gi.getContext("2d");
e instanceof ImageData ? i.putImageData(e, 0, 0) : i.drawImage(e, 0, 0, e.width, e.height), n = Gi;
}
return n.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 = sr("canvas");
t.width = e.width, t.height = e.height;
const n = t.getContext("2d");
n.drawImage(e, 0, 0, e.width, e.height);
const i = n.getImageData(0, 0, e.width, e.height), r = i.data;
for (let a = 0; a < r.length; a++)
r[a] = ri(r[a] / 255) * 255;
return n.putImageData(i, 0, 0), t;
} else if (e.data) {
const t = e.data.slice(0);
for (let n = 0; n < t.length; n++)
t instanceof Uint8Array || t instanceof Uint8ClampedArray ? t[n] = Math.floor(ri(t[n] / 255) * 255) : t[n] = ri(t[n]);
return {
data: t,
width: e.width,
height: e.height
};
} else
return He("ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied."), e;
}
}
let Rp = 0;
class fc {
/**
* 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: Rp++ }), this.uuid = Mn(), 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) : typeof VideoFrame < "u" && 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 n = {
uuid: this.uuid,
url: ""
}, i = this.data;
if (i !== null) {
let r;
if (Array.isArray(i)) {
r = [];
for (let a = 0, o = i.length; a < o; a++)
i[a].isDataTexture ? r.push(ja(i[a].image)) : r.push(ja(i[a]));
} else
r = ja(i);
n.url = r;
}
return t || (e.images[this.uuid] = n), n;
}
}
function ja(s) {
return typeof HTMLImageElement < "u" && s instanceof HTMLImageElement || typeof HTMLCanvasElement < "u" && s instanceof HTMLCanvasElement || typeof ImageBitmap < "u" && s instanceof ImageBitmap ? Ap.getDataURL(s) : s.data ? {
data: Array.from(s.data),
width: s.width,
height: s.height,
type: s.data.constructor.name
} : (He("Texture: Unable to serialize Texture."), {});
}
let Pp = 0;
const Za = /* @__PURE__ */ new L();
class zt extends Bi {
/**
* 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 = zt.DEFAULT_IMAGE, t = zt.DEFAULT_MAPPING, n = zn, i = zn, r = Nt, a = ii, o = mn, l = sn, c = zt.DEFAULT_ANISOTROPY, h = mi) {
super(), this.isTexture = !0, Object.defineProperty(this, "id", { value: Pp++ }), this.uuid = Mn(), this.name = "", this.source = new fc(e), this.mipmaps = [], this.mapping = t, this.channel = 0, this.wrapS = n, this.wrapT = i, this.magFilter = r, this.minFilter = a, this.anisotropy = c, this.format = o, this.internalFormat = null, this.type = l, this.offset = new fe(0, 0), this.repeat = new fe(1, 1), this.center = new fe(0, 0), this.rotation = 0, this.matrixAutoUpdate = !0, this.matrix = new Je(), 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(Za).x;
}
/**
* The height of the texture in pixels.
*/
get height() {
return this.source.getSize(Za).y;
}
/**
* The depth of the texture in pixels.
*/
get depth() {
return this.source.getSize(Za).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 n = e[t];
if (n === void 0) {
He(`Texture.setValues(): parameter '${t}' has value of undefined.`);
continue;
}
const i = this[t];
if (i === void 0) {
He(`Texture.setValues(): property '${t}' does not exist.`);
continue;
}
i && n && i.isVector2 && n.isVector2 || i && n && i.isVector3 && n.isVector3 || i && n && i.isMatrix3 && n.isMatrix3 ? i.copy(n) : this[t] = n;
}
}
/**
* 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 n = {
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 && (n.userData = this.userData), t || (e.textures[this.uuid] = n), n;
}
/**
* 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 !== Gu) return e;
if (e.applyMatrix3(this.matrix), e.x < 0 || e.x > 1)
switch (this.wrapS) {
case Wn:
e.x = e.x - Math.floor(e.x);
break;
case zn:
e.x = e.x < 0 ? 0 : 1;
break;
case va:
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 Wn:
e.y = e.y - Math.floor(e.y);
break;
case zn:
e.y = e.y < 0 ? 0 : 1;
break;
case va:
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++;
}
}
zt.DEFAULT_IMAGE = null;
zt.DEFAULT_MAPPING = Gu;
zt.DEFAULT_ANISOTROPY = 1;
class xt {
/**
* 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, n = 0, i = 1) {
xt.prototype.isVector4 = !0, this.x = e, this.y = t, this.z = n, this.w = i;
}
/**
* 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, n, i) {
return this.x = e, this.y = t, this.z = n, this.w = i, 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, n = this.y, i = this.z, r = this.w, a = e.elements;
return this.x = a[0] * t + a[4] * n + a[8] * i + a[12] * r, this.y = a[1] * t + a[5] * n + a[9] * i + a[13] * r, this.z = a[2] * t + a[6] * n + a[10] * i + a[14] * r, this.w = a[3] * t + a[7] * n + a[11] * i + a[15] * r, 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, n, i, r;
const l = e.elements, c = l[0], h = l[4], u = l[8], f = l[1], d = l[5], p = l[9], g = l[2], v = l[6], m = l[10];
if (Math.abs(h - f) < 0.01 && Math.abs(u - g) < 0.01 && Math.abs(p - v) < 0.01) {
if (Math.abs(h + f) < 0.1 && Math.abs(u + g) < 0.1 && Math.abs(p + v) < 0.1 && Math.abs(c + d + m - 3) < 0.1)
return this.set(1, 0, 0, 0), this;
t = Math.PI;
const x = (c + 1) / 2, M = (d + 1) / 2, T = (m + 1) / 2, A = (h + f) / 4, P = (u + g) / 4, U = (p + v) / 4;
return x > M && x > T ? x < 0.01 ? (n = 0, i = 0.707106781, r = 0.707106781) : (n = Math.sqrt(x), i = A / n, r = P / n) : M > T ? M < 0.01 ? (n = 0.707106781, i = 0, r = 0.707106781) : (i = Math.sqrt(M), n = A / i, r = U / i) : T < 0.01 ? (n = 0.707106781, i = 0.707106781, r = 0) : (r = Math.sqrt(T), n = P / r, i = U / r), this.set(n, i, r, t), this;
}
let _ = Math.sqrt((v - p) * (v - p) + (u - g) * (u - g) + (f - h) * (f - h));
return Math.abs(_) < 1e-3 && (_ = 1), this.x = (v - p) / _, this.y = (u - g) / _, this.z = (f - h) / _, this.w = Math.acos((c + d + m - 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 = Qe(this.x, e.x, t.x), this.y = Qe(this.y, e.y, t.y), this.z = Qe(this.z, e.z, t.z), this.w = Qe(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 = Qe(this.x, e, t), this.y = Qe(this.y, e, t), this.z = Qe(this.z, e, t), this.w = Qe(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 n = this.length();
return this.divideScalar(n || 1).multiplyScalar(Qe(n, 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, n) {
return this.x = e.x + (t.x - e.x) * n, this.y = e.y + (t.y - e.y) * n, this.z = e.z + (t.z - e.z) * n, this.w = e.w + (t.w - e.w) * n, 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 Lp extends Bi {
/**
* 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, n = {}) {
super(), n = Object.assign({
generateMipmaps: !1,
internalFormat: null,
minFilter: Nt,
depthBuffer: !0,
stencilBuffer: !1,
resolveDepthBuffer: !0,
resolveStencilBuffer: !0,
depthTexture: null,
samples: 0,
count: 1,
depth: 1,
multiview: !1
}, n), this.isRenderTarget = !0, this.width = e, this.height = t, this.depth = n.depth, this.scissor = new xt(0, 0, e, t), this.scissorTest = !1, this.viewport = new xt(0, 0, e, t);
const i = { width: e, height: t, depth: n.depth }, r = new zt(i);
this.textures = [];
const a = n.count;
for (let o = 0; o < a; o++)
this.textures[o] = r.clone(), this.textures[o].isRenderTargetTexture = !0, this.textures[o].renderTarget = this;
this._setTextureOptions(n), this.depthBuffer = n.depthBuffer, this.stencilBuffer = n.stencilBuffer, this.resolveDepthBuffer = n.resolveDepthBuffer, this.resolveStencilBuffer = n.resolveStencilBuffer, this._depthTexture = null, this.depthTexture = n.depthTexture, this.samples = n.samples, this.multiview = n.multiview;
}
_setTextureOptions(e = {}) {
const t = {
minFilter: Nt,
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 n = 0; n < this.textures.length; n++)
this.textures[n].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, n = 1) {
if (this.width !== e || this.height !== t || this.depth !== n) {
this.width = e, this.height = t, this.depth = n;
for (let i = 0, r = this.textures.length; i < r; i++)
this.textures[i].image.width = e, this.textures[i].image.height = t, this.textures[i].image.depth = n, this.textures[i].isData3DTexture !== !0 && (this.textures[i].isArrayTexture = this.textures[i].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, n = e.textures.length; t < n; t++) {
this.textures[t] = e.textures[t].clone(), this.textures[t].isRenderTargetTexture = !0, this.textures[t].renderTarget = this;
const i = Object.assign({}, e.textures[t].image);
this.textures[t].source = new fc(i);
}
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 Zt extends Lp {
/**
* 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, n = {}) {
super(e, t, n), this.isWebGLRenderTarget = !0;
}
}
class ed extends zt {
/**
* 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, n = 1, i = 1) {
super(null), this.isDataArrayTexture = !0, this.image = { data: e, width: t, height: n, depth: i }, this.magFilter = Pt, this.minFilter = Pt, this.wrapR = zn, 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 Dp extends zt {
/**
* 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, n = 1, i = 1) {
super(null), this.isData3DTexture = !0, this.image = { data: e, width: t, height: n, depth: i }, this.magFilter = Pt, this.minFilter = Pt, this.wrapR = zn, this.generateMipmaps = !1, this.flipY = !1, this.unpackAlignment = 1;
}
}
class qt {
/**
* 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 L(1 / 0, 1 / 0, 1 / 0), t = new L(-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, n = e.length; t < n; t += 3)
this.expandByPoint(wn.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, n = e.count; t < n; t++)
this.expandByPoint(wn.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, n = e.length; t < n; 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 n = wn.copy(t).multiplyScalar(0.5);
return this.min.copy(e).sub(n), this.max.copy(e).add(n), 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 n = e.geometry;
if (n !== void 0) {
const r = n.getAttribute("position");
if (t === !0 && r !== void 0 && e.isInstancedMesh !== !0)
for (let a = 0, o = r.count; a < o; a++)
e.isMesh === !0 ? e.getVertexPosition(a, wn) : wn.fromBufferAttribute(r, a), wn.applyMatrix4(e.matrixWorld), this.expandByPoint(wn);
else
e.boundingBox !== void 0 ? (e.boundingBox === null && e.computeBoundingBox(), br.copy(e.boundingBox)) : (n.boundingBox === null && n.computeBoundingBox(), br.copy(n.boundingBox)), br.applyMatrix4(e.matrixWorld), this.union(br);
}
const i = e.children;
for (let r = 0, a = i.length; r < a; r++)
this.expandByObject(i[r], 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, wn), wn.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, n;
return e.normal.x > 0 ? (t = e.normal.x * this.min.x, n = e.normal.x * this.max.x) : (t = e.normal.x * this.max.x, n = e.normal.x * this.min.x), e.normal.y > 0 ? (t += e.normal.y * this.min.y, n += e.normal.y * this.max.y) : (t += e.normal.y * this.max.y, n += e.normal.y * this.min.y), e.normal.z > 0 ? (t += e.normal.z * this.min.z, n += e.normal.z * this.max.z) : (t += e.normal.z * this.max.z, n += e.normal.z * this.min.z), t <= -e.constant && n >= -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(Ds), yr.subVectors(this.max, Ds), Wi.subVectors(e.a, Ds), Xi.subVectors(e.b, Ds), ji.subVectors(e.c, Ds), li.subVectors(Xi, Wi), ci.subVectors(ji, Xi), yi.subVectors(Wi, ji);
let t = [
0,
-li.z,
li.y,
0,
-ci.z,
ci.y,
0,
-yi.z,
yi.y,
li.z,
0,
-li.x,
ci.z,
0,
-ci.x,
yi.z,
0,
-yi.x,
-li.y,
li.x,
0,
-ci.y,
ci.x,
0,
-yi.y,
yi.x,
0
];
return !qa(t, Wi, Xi, ji, yr) || (t = [1, 0, 0, 0, 1, 0, 0, 0, 1], !qa(t, Wi, Xi, ji, yr)) ? !1 : (Mr.crossVectors(li, ci), t = [Mr.x, Mr.y, Mr.z], qa(t, Wi, Xi, ji, yr));
}
/**
* 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, wn).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(wn).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 : ($n[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(e), $n[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(e), $n[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(e), $n[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(e), $n[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(e), $n[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(e), $n[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(e), $n[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(e), this.setFromPoints($n), 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 $n = [
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L(),
/* @__PURE__ */ new L()
], wn = /* @__PURE__ */ new L(), br = /* @__PURE__ */ new qt(), Wi = /* @__PURE__ */ new L(), Xi = /* @__PURE__ */ new L(), ji = /* @__PURE__ */ new L(), li = /* @__PURE__ */ new L(), ci = /* @__PURE__ */ new L(), yi = /* @__PURE__ */ new L(), Ds = /* @__PURE__ */ new L(), yr = /* @__PURE__ */ new L(), Mr = /* @__PURE__ */ new L(), Mi = /* @__PURE__ */ new L();
function qa(s, e, t, n, i) {
for (let r = 0, a = s.length - 3; r <= a; r += 3) {
Mi.fromArray(s, r);
const o = i.x * Math.abs(Mi.x) + i.y * Math.abs(Mi.y) + i.z * Math.abs(Mi.z), l = e.dot(Mi), c = t.dot(Mi), h = n.dot(Mi);
if (Math.max(-Math.max(l, c, h), Math.min(l, c, h)) > o)
return !1;
}
return !0;
}
const Ip = /* @__PURE__ */ new qt(), Is = /* @__PURE__ */ new L(), Ya = /* @__PURE__ */ new L();
class qn {
/**
* 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 L(), 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 n = this.center;
t !== void 0 ? n.copy(t) : Ip.setFromPoints(e).getCenter(n);
let i = 0;
for (let r = 0, a = e.length; r < a; r++)
i = Math.max(i, n.distanceToSquared(e[r]));
return this.radius = Math.sqrt(i), 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 n = this.center.distanceToSquared(e);
return t.copy(e), n > 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;
Is.subVectors(e, this.center);
const t = Is.lengthSq();
if (t > this.radius * this.radius) {
const n = Math.sqrt(t), i = (n - this.radius) * 0.5;
this.center.addScaledVector(Is, i / n), this.radius += i;
}
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) : (Ya.subVectors(e.center, this.center).setLength(e.radius), this.expandByPoint(Is.copy(e.center).add(Ya)), this.expandByPoint(Is.copy(e.center).sub(Ya))), 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 {Sphere} A reference to this bounding sphere.
*/
fromJSON(e) {
return this.radius = e.radius, this.center.fromArray(e.center), this;
}
}
const Jn = /* @__PURE__ */ new L(), Ka = /* @__PURE__ */ new L(), wr = /* @__PURE__ */ new L(), hi = /* @__PURE__ */ new L(), $a = /* @__PURE__ */ new L(), Sr = /* @__PURE__ */ new L(), Ja = /* @__PURE__ */ new L();
class Ss {
/**
* 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 L(), t = new L(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, Jn)), 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 n = t.dot(this.direction);
return n < 0 ? t.copy(this.origin) : t.copy(this.origin).addScaledVector(this.direction, n);
}
/**
* 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 = Jn.subVectors(e, this.origin).dot(this.direction);
return t < 0 ? this.origin.distanceToSquared(e) : (Jn.copy(this.origin).addScaledVector(this.direction, t), Jn.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, n, i) {
Ka.copy(e).add(t).multiplyScalar(0.5), wr.copy(t).sub(e).normalize(), hi.copy(this.origin).sub(Ka);
const r = e.distanceTo(t) * 0.5, a = -this.direction.dot(wr), o = hi.dot(this.direction), l = -hi.dot(wr), c = hi.lengthSq(), h = Math.abs(1 - a * a);
let u, f, d, p;
if (h > 0)
if (u = a * l - o, f = a * o - l, p = r * h, u >= 0)
if (f >= -p)
if (f <= p) {
const g = 1 / h;
u *= g, f *= g, d = u * (u + a * f + 2 * o) + f * (a * u + f + 2 * l) + c;
} else
f = r, u = Math.max(0, -(a * f + o)), d = -u * u + f * (f + 2 * l) + c;
else
f = -r, u = Math.max(0, -(a * f + o)), d = -u * u + f * (f + 2 * l) + c;
else
f <= -p ? (u = Math.max(0, -(-a * r + o)), f = u > 0 ? -r : Math.min(Math.max(-r, -l), r), d = -u * u + f * (f + 2 * l) + c) : f <= p ? (u = 0, f = Math.min(Math.max(-r, -l), r), d = f * (f + 2 * l) + c) : (u = Math.max(0, -(a * r + o)), f = u > 0 ? r : Math.min(Math.max(-r, -l), r), d = -u * u + f * (f + 2 * l) + c);
else
f = a > 0 ? -r : r, u = Math.max(0, -(a * f + o)), d = -u * u + f * (f + 2 * l) + c;
return n && n.copy(this.origin).addScaledVector(this.direction, u), i && i.copy(Ka).addScaledVector(wr, f), d;
}
/**
* 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) {
Jn.subVectors(e.center, this.origin);
const n = Jn.dot(this.direction), i = Jn.dot(Jn) - n * n, r = e.radius * e.radius;
if (i > r) return null;
const a = Math.sqrt(r - i), o = n - a, l = n + 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 n = -(this.origin.dot(e.normal) + e.constant) / t;
return n >= 0 ? n : 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 n = this.distanceToPlane(e);
return n === null ? null : this.at(n, 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 n, i, r, a, o, l;
const c = 1 / this.direction.x, h = 1 / this.direction.y, u = 1 / this.direction.z, f = this.origin;
return c >= 0 ? (n = (e.min.x - f.x) * c, i = (e.max.x - f.x) * c) : (n = (e.max.x - f.x) * c, i = (e.min.x - f.x) * c), h >= 0 ? (r = (e.min.y - f.y) * h, a = (e.max.y - f.y) * h) : (r = (e.max.y - f.y) * h, a = (e.min.y - f.y) * h), n > a || r > i || ((r > n || isNaN(n)) && (n = r), (a < i || isNaN(i)) && (i = a), u >= 0 ? (o = (e.min.z - f.z) * u, l = (e.max.z - f.z) * u) : (o = (e.max.z - f.z) * u, l = (e.min.z - f.z) * u), n > l || o > i) || ((o > n || n !== n) && (n = o), (l < i || i !== i) && (i = l), i < 0) ? null : this.at(n >= 0 ? n : i, 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, Jn) !== 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, n, i, r) {
$a.subVectors(t, e), Sr.subVectors(n, e), Ja.crossVectors($a, Sr);
let a = this.direction.dot(Ja), o;
if (a > 0) {
if (i) return null;
o = 1;
} else if (a < 0)
o = -1, a = -a;
else
return null;
hi.subVectors(this.origin, e);
const l = o * this.direction.dot(Sr.crossVectors(hi, Sr));
if (l < 0)
return null;
const c = o * this.direction.dot($a.cross(hi));
if (c < 0 || l + c > a)
return null;
const h = -o * hi.dot(Ja);
return h < 0 ? null : this.at(h / a, r);
}
/**
* 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 je {
/**
* 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, n, i, r, a, o, l, c, h, u, f, d, p, g, v) {
je.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, n, i, r, a, o, l, c, h, u, f, d, p, g, v);
}
/**
* 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, n, i, r, a, o, l, c, h, u, f, d, p, g, v) {
const m = this.elements;
return m[0] = e, m[4] = t, m[8] = n, m[12] = i, m[1] = r, m[5] = a, m[9] = o, m[13] = l, m[2] = c, m[6] = h, m[10] = u, m[14] = f, m[3] = d, m[7] = p, m[11] = g, m[15] = v, 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 je().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, n = e.elements;
return t[0] = n[0], t[1] = n[1], t[2] = n[2], t[3] = n[3], t[4] = n[4], t[5] = n[5], t[6] = n[6], t[7] = n[7], t[8] = n[8], t[9] = n[9], t[10] = n[10], t[11] = n[11], t[12] = n[12], t[13] = n[13], t[14] = n[14], t[15] = n[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, n = e.elements;
return t[12] = n[12], t[13] = n[13], t[14] = n[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, n) {
return this.determinant() === 0 ? (e.set(1, 0, 0), t.set(0, 1, 0), n.set(0, 0, 1), this) : (e.setFromMatrixColumn(this, 0), t.setFromMatrixColumn(this, 1), n.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, n) {
return this.set(
e.x,
t.x,
n.x,
0,
e.y,
t.y,
n.y,
0,
e.z,
t.z,
n.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) {
if (e.determinant() === 0)
return this.identity();
const t = this.elements, n = e.elements, i = 1 / Zi.setFromMatrixColumn(e, 0).length(), r = 1 / Zi.setFromMatrixColumn(e, 1).length(), a = 1 / Zi.setFromMatrixColumn(e, 2).length();
return t[0] = n[0] * i, t[1] = n[1] * i, t[2] = n[2] * i, t[3] = 0, t[4] = n[4] * r, t[5] = n[5] * r, t[6] = n[6] * r, t[7] = 0, t[8] = n[8] * a, t[9] = n[9] * a, t[10] = n[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, n = e.x, i = e.y, r = e.z, a = Math.cos(n), o = Math.sin(n), l = Math.cos(i), c = Math.sin(i), h = Math.cos(r), u = Math.sin(r);
if (e.order === "XYZ") {
const f = a * h, d = a * u, p = o * h, g = o * u;
t[0] = l * h, t[4] = -l * u, t[8] = c, t[1] = d + p * c, t[5] = f - g * c, t[9] = -o * l, t[2] = g - f * c, t[6] = p + d * c, t[10] = a * l;
} else if (e.order === "YXZ") {
const f = l * h, d = l * u, p = c * h, g = c * u;
t[0] = f + g * o, t[4] = p * o - d, t[8] = a * c, t[1] = a * u, t[5] = a * h, t[9] = -o, t[2] = d * o - p, t[6] = g + f * o, t[10] = a * l;
} else if (e.order === "ZXY") {
const f = l * h, d = l * u, p = c * h, g = c * u;
t[0] = f - g * o, t[4] = -a * u, t[8] = p + d * o, t[1] = d + p * o, t[5] = a * h, t[9] = g - f * o, t[2] = -a * c, t[6] = o, t[10] = a * l;
} else if (e.order === "ZYX") {
const f = a * h, d = a * u, p = o * h, g = o * u;
t[0] = l * h, t[4] = p * c - d, t[8] = f * c + g, t[1] = l * u, t[5] = g * c + f, t[9] = d * c - p, t[2] = -c, t[6] = o * l, t[10] = a * l;
} else if (e.order === "YZX") {
const f = a * l, d = a * c, p = o * l, g = o * c;
t[0] = l * h, t[4] = g - f * u, t[8] = p * u + d, t[1] = u, t[5] = a * h, t[9] = -o * h, t[2] = -c * h, t[6] = d * u + p, t[10] = f - g * u;
} else if (e.order === "XZY") {
const f = a * l, d = a * c, p = o * l, g = o * c;
t[0] = l * h, t[4] = -u, t[8] = c * h, t[1] = f * u + g, t[5] = a * h, t[9] = d * u - p, t[2] = p * u - d, t[6] = o * h, t[10] = g * u + f;
}
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(Np, e, Up);
}
/**
* 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, n) {
const i = this.elements;
return dn.subVectors(e, t), dn.lengthSq() === 0 && (dn.z = 1), dn.normalize(), ui.crossVectors(n, dn), ui.lengthSq() === 0 && (Math.abs(n.z) === 1 ? dn.x += 1e-4 : dn.z += 1e-4, dn.normalize(), ui.crossVectors(n, dn)), ui.normalize(), Er.crossVectors(dn, ui), i[0] = ui.x, i[4] = Er.x, i[8] = dn.x, i[1] = ui.y, i[5] = Er.y, i[9] = dn.y, i[2] = ui.z, i[6] = Er.z, i[10] = dn.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 n = e.elements, i = t.elements, r = this.elements, a = n[0], o = n[4], l = n[8], c = n[12], h = n[1], u = n[5], f = n[9], d = n[13], p = n[2], g = n[6], v = n[10], m = n[14], _ = n[3], x = n[7], M = n[11], T = n[15], A = i[0], P = i[4], U = i[8], E = i[12], C = i[1], B = i[5], D = i[9], k = i[13], w = i[2], F = i[6], q = i[10], z = i[14], te = i[3], K = i[7], le = i[11], W = i[15];
return r[0] = a * A + o * C + l * w + c * te, r[4] = a * P + o * B + l * F + c * K, r[8] = a * U + o * D + l * q + c * le, r[12] = a * E + o * k + l * z + c * W, r[1] = h * A + u * C + f * w + d * te, r[5] = h * P + u * B + f * F + d * K, r[9] = h * U + u * D + f * q + d * le, r[13] = h * E + u * k + f * z + d * W, r[2] = p * A + g * C + v * w + m * te, r[6] = p * P + g * B + v * F + m * K, r[10] = p * U + g * D + v * q + m * le, r[14] = p * E + g * k + v * z + m * W, r[3] = _ * A + x * C + M * w + T * te, r[7] = _ * P + x * B + M * F + T * K, r[11] = _ * U + x * D + M * q + T * le, r[15] = _ * E + x * k + M * z + T * W, 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], n = e[4], i = e[8], r = e[12], a = e[1], o = e[5], l = e[9], c = e[13], h = e[2], u = e[6], f = e[10], d = e[14], p = e[3], g = e[7], v = e[11], m = e[15], _ = l * d - c * f, x = o * d - c * u, M = o * f - l * u, T = a * d - c * h, A = a * f - l * h, P = a * u - o * h;
return t * (g * _ - v * x + m * M) - n * (p * _ - v * T + m * A) + i * (p * x - g * T + m * P) - r * (p * M - g * A + v * P);
}
/**
* 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, n) {
const i = this.elements;
return e.isVector3 ? (i[12] = e.x, i[13] = e.y, i[14] = e.z) : (i[12] = e, i[13] = t, i[14] = n), 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], n = e[1], i = e[2], r = e[3], a = e[4], o = e[5], l = e[6], c = e[7], h = e[8], u = e[9], f = e[10], d = e[11], p = e[12], g = e[13], v = e[14], m = e[15], _ = u * v * c - g * f * c + g * l * d - o * v * d - u * l * m + o * f * m, x = p * f * c - h * v * c - p * l * d + a * v * d + h * l * m - a * f * m, M = h * g * c - p * u * c + p * o * d - a * g * d - h * o * m + a * u * m, T = p * u * l - h * g * l - p * o * f + a * g * f + h * o * v - a * u * v, A = t * _ + n * x + i * M + r * T;
if (A === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
const P = 1 / A;
return e[0] = _ * P, e[1] = (g * f * r - u * v * r - g * i * d + n * v * d + u * i * m - n * f * m) * P, e[2] = (o * v * r - g * l * r + g * i * c - n * v * c - o * i * m + n * l * m) * P, e[3] = (u * l * r - o * f * r - u * i * c + n * f * c + o * i * d - n * l * d) * P, e[4] = x * P, e[5] = (h * v * r - p * f * r + p * i * d - t * v * d - h * i * m + t * f * m) * P, e[6] = (p * l * r - a * v * r - p * i * c + t * v * c + a * i * m - t * l * m) * P, e[7] = (a * f * r - h * l * r + h * i * c - t * f * c - a * i * d + t * l * d) * P, e[8] = M * P, e[9] = (p * u * r - h * g * r - p * n * d + t * g * d + h * n * m - t * u * m) * P, e[10] = (a * g * r - p * o * r + p * n * c - t * g * c - a * n * m + t * o * m) * P, e[11] = (h * o * r - a * u * r - h * n * c + t * u * c + a * n * d - t * o * d) * P, e[12] = T * P, e[13] = (h * g * i - p * u * i + p * n * f - t * g * f - h * n * v + t * u * v) * P, e[14] = (p * o * i - a * g * i - p * n * l + t * g * l + a * n * v - t * o * v) * P, e[15] = (a * u * i - h * o * i + h * n * l - t * u * l - a * n * f + t * o * f) * P, 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, n = e.x, i = e.y, r = e.z;
return t[0] *= n, t[4] *= i, t[8] *= r, t[1] *= n, t[5] *= i, t[9] *= r, t[2] *= n, t[6] *= i, t[10] *= r, t[3] *= n, t[7] *= i, t[11] *= r, 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], n = e[4] * e[4] + e[5] * e[5] + e[6] * e[6], i = e[8] * e[8] + e[9] * e[9] + e[10] * e[10];
return Math.sqrt(Math.max(t, n, i));
}
/**
* 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, n) {
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,
n,
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), n = Math.sin(e);
return this.set(
1,
0,
0,
0,
0,
t,
-n,
0,
0,
n,
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), n = Math.sin(e);
return this.set(
t,
0,
n,
0,
0,
1,
0,
0,
-n,
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), n = Math.sin(e);
return this.set(
t,
-n,
0,
0,
n,
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 n = Math.cos(t), i = Math.sin(t), r = 1 - n, a = e.x, o = e.y, l = e.z, c = r * a, h = r * o;
return this.set(
c * a + n,
c * o - i * l,
c * l + i * o,
0,
c * o + i * l,
h * o + n,
h * l - i * a,
0,
c * l - i * o,
h * l + i * a,
r * l * l + n,
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, n) {
return this.set(
e,
0,
0,
0,
0,
t,
0,
0,
0,
0,
n,
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, n, i, r, a) {
return this.set(
1,
n,
r,
0,
e,
1,
a,
0,
t,
i,
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, n) {
const i = this.elements, r = t._x, a = t._y, o = t._z, l = t._w, c = r + r, h = a + a, u = o + o, f = r * c, d = r * h, p = r * u, g = a * h, v = a * u, m = o * u, _ = l * c, x = l * h, M = l * u, T = n.x, A = n.y, P = n.z;
return i[0] = (1 - (g + m)) * T, i[1] = (d + M) * T, i[2] = (p - x) * T, i[3] = 0, i[4] = (d - M) * A, i[5] = (1 - (f + m)) * A, i[6] = (v + _) * A, i[7] = 0, i[8] = (p + x) * P, i[9] = (v - _) * P, i[10] = (1 - (f + g)) * P, i[11] = 0, i[12] = e.x, i[13] = e.y, i[14] = e.z, i[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, n) {
const i = this.elements;
if (e.x = i[12], e.y = i[13], e.z = i[14], this.determinant() === 0)
return n.set(1, 1, 1), t.identity(), this;
let r = Zi.set(i[0], i[1], i[2]).length();
const a = Zi.set(i[4], i[5], i[6]).length(), o = Zi.set(i[8], i[9], i[10]).length();
this.determinant() < 0 && (r = -r), Sn.copy(this);
const c = 1 / r, h = 1 / a, u = 1 / o;
return Sn.elements[0] *= c, Sn.elements[1] *= c, Sn.elements[2] *= c, Sn.elements[4] *= h, Sn.elements[5] *= h, Sn.elements[6] *= h, Sn.elements[8] *= u, Sn.elements[9] *= u, Sn.elements[10] *= u, t.setFromRotationMatrix(Sn), n.x = r, n.y = a, n.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, n, i, r, a, o = Hn, l = !1) {
const c = this.elements, h = 2 * r / (t - e), u = 2 * r / (n - i), f = (t + e) / (t - e), d = (n + i) / (n - i);
let p, g;
if (l)
p = r / (a - r), g = a * r / (a - r);
else if (o === Hn)
p = -(a + r) / (a - r), g = -2 * a * r / (a - r);
else if (o === xa)
p = -a / (a - r), g = -a * r / (a - r);
else
throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: " + o);
return c[0] = h, c[4] = 0, c[8] = f, c[12] = 0, c[1] = 0, c[5] = u, c[9] = d, c[13] = 0, c[2] = 0, c[6] = 0, c[10] = p, c[14] = g, 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, n, i, r, a, o = Hn, l = !1) {
const c = this.elements, h = 2 / (t - e), u = 2 / (n - i), f = -(t + e) / (t - e), d = -(n + i) / (n - i);
let p, g;
if (l)
p = 1 / (a - r), g = a / (a - r);
else if (o === Hn)
p = -2 / (a - r), g = -(a + r) / (a - r);
else if (o === xa)
p = -1 / (a - r), g = -r / (a - r);
else
throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: " + o);
return c[0] = h, c[4] = 0, c[8] = 0, c[12] = f, c[1] = 0, c[5] = u, c[9] = 0, c[13] = d, c[2] = 0, c[6] = 0, c[10] = p, c[14] = g, 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, n = e.elements;
for (let i = 0; i < 16; i++)
if (t[i] !== n[i]) 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 n = 0; n < 16; n++)
this.elements[n] = e[n + 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 n = this.elements;
return e[t] = n[0], e[t + 1] = n[1], e[t + 2] = n[2], e[t + 3] = n[3], e[t + 4] = n[4], e[t + 5] = n[5], e[t + 6] = n[6], e[t + 7] = n[7], e[t + 8] = n[8], e[t + 9] = n[9], e[t + 10] = n[10], e[t + 11] = n[11], e[t + 12] = n[12], e[t + 13] = n[13], e[t + 14] = n[14], e[t + 15] = n[15], e;
}
}
const Zi = /* @__PURE__ */ new L(), Sn = /* @__PURE__ */ new je(), Np = /* @__PURE__ */ new L(0, 0, 0), Up = /* @__PURE__ */ new L(1, 1, 1), ui = /* @__PURE__ */ new L(), Er = /* @__PURE__ */ new L(), dn = /* @__PURE__ */ new L(), Qc = /* @__PURE__ */ new je(), eh = /* @__PURE__ */ new Pn();
class ln {
/**
* 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, n = 0, i = ln.DEFAULT_ORDER) {
this.isEuler = !0, this._x = e, this._y = t, this._z = n, this._order = i;
}
/**
* 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, n, i = this._order) {
return this._x = e, this._y = t, this._z = n, this._order = i, 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, n = !0) {
const i = e.elements, r = i[0], a = i[4], o = i[8], l = i[1], c = i[5], h = i[9], u = i[2], f = i[6], d = i[10];
switch (t) {
case "XYZ":
this._y = Math.asin(Qe(o, -1, 1)), Math.abs(o) < 0.9999999 ? (this._x = Math.atan2(-h, d), this._z = Math.atan2(-a, r)) : (this._x = Math.atan2(f, c), this._z = 0);
break;
case "YXZ":
this._x = Math.asin(-Qe(h, -1, 1)), Math.abs(h) < 0.9999999 ? (this._y = Math.atan2(o, d), this._z = Math.atan2(l, c)) : (this._y = Math.atan2(-u, r), this._z = 0);
break;
case "ZXY":
this._x = Math.asin(Qe(f, -1, 1)), Math.abs(f) < 0.9999999 ? (this._y = Math.atan2(-u, d), this._z = Math.atan2(-a, c)) : (this._y = 0, this._z = Math.atan2(l, r));
break;
case "ZYX":
this._y = Math.asin(-Qe(u, -1, 1)), Math.abs(u) < 0.9999999 ? (this._x = Math.atan2(f, d), this._z = Math.atan2(l, r)) : (this._x = 0, this._z = Math.atan2(-a, c));
break;
case "YZX":
this._z = Math.asin(Qe(l, -1, 1)), Math.abs(l) < 0.9999999 ? (this._x = Math.atan2(-h, c), this._y = Math.atan2(-u, r)) : (this._x = 0, this._y = Math.atan2(o, d));
break;
case "XZY":
this._z = Math.asin(-Qe(a, -1, 1)), Math.abs(a) < 0.9999999 ? (this._x = Math.atan2(f, c), this._y = Math.atan2(o, r)) : (this._x = Math.atan2(-h, d), this._y = 0);
break;
default:
He("Euler: .setFromRotationMatrix() encountered an unknown order: " + t);
}
return this._order = t, n === !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, n) {
return Qc.makeRotationFromQuaternion(e), this.setFromRotationMatrix(Qc, t, n);
}
/**
* 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 eh.setFromEuler(this), this.setFromQuaternion(eh, 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;
}
}
ln.DEFAULT_ORDER = "XYZ";
class pc {
/**
* 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 kp = 0;
const th = /* @__PURE__ */ new L(), qi = /* @__PURE__ */ new Pn(), Qn = /* @__PURE__ */ new je(), Tr = /* @__PURE__ */ new L(), Ns = /* @__PURE__ */ new L(), Bp = /* @__PURE__ */ new L(), Op = /* @__PURE__ */ new Pn(), nh = /* @__PURE__ */ new L(1, 0, 0), ih = /* @__PURE__ */ new L(0, 1, 0), sh = /* @__PURE__ */ new L(0, 0, 1), rh = { type: "added" }, Fp = { type: "removed" }, Yi = { type: "childadded", child: null }, Qa = { type: "childremoved", child: null };
class Mt extends Bi {
/**
* Constructs a new 3D object.
*/
constructor() {
super(), this.isObject3D = !0, Object.defineProperty(this, "id", { value: kp++ }), this.uuid = Mn(), this.name = "", this.type = "Object3D", this.parent = null, this.children = [], this.up = Mt.DEFAULT_UP.clone();
const e = new L(), t = new ln(), n = new Pn(), i = new L(1, 1, 1);
function r() {
n.setFromEuler(t, !1);
}
function a() {
t.setFromQuaternion(n, void 0, !1);
}
t._onChange(r), n._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: n
},
/**
* Represents the object's local scale.
*
* @name Object3D#scale
* @type {Vector3}
* @default (1,1,1)
*/
scale: {
configurable: !0,
enumerable: !0,
value: i
},
/**
* Represents the object's model-view matrix.
*
* @name Object3D#modelViewMatrix
* @type {Matrix4}
*/
modelViewMatrix: {
value: new je()
},
/**
* Represents the object's normal matrix.
*
* @name Object3D#normalMatrix
* @type {Matrix3}
*/
normalMatrix: {
value: new Je()
}
}), this.matrix = new je(), this.matrixWorld = new je(), this.matrixAutoUpdate = Mt.DEFAULT_MATRIX_AUTO_UPDATE, this.matrixWorldAutoUpdate = Mt.DEFAULT_MATRIX_WORLD_AUTO_UPDATE, this.matrixWorldNeedsUpdate = !1, this.layers = new pc(), 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 qi.setFromAxisAngle(e, t), this.quaternion.multiply(qi), 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 qi.setFromAxisAngle(e, t), this.quaternion.premultiply(qi), 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(nh, 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(ih, 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(sh, 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 th.copy(e).applyQuaternion(this.quaternion), this.position.add(th.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(nh, 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(ih, 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(sh, 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(Qn.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, n) {
e.isVector3 ? Tr.copy(e) : Tr.set(e, t, n);
const i = this.parent;
this.updateWorldMatrix(!0, !1), Ns.setFromMatrixPosition(this.matrixWorld), this.isCamera || this.isLight ? Qn.lookAt(Ns, Tr, this.up) : Qn.lookAt(Tr, Ns, this.up), this.quaternion.setFromRotationMatrix(Qn), i && (Qn.extractRotation(i.matrixWorld), qi.setFromRotationMatrix(Qn), this.quaternion.premultiply(qi.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 ? (Xe("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(rh), Yi.child = e, this.dispatchEvent(Yi), Yi.child = null) : Xe("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 n = 0; n < arguments.length; n++)
this.remove(arguments[n]);
return this;
}
const t = this.children.indexOf(e);
return t !== -1 && (e.parent = null, this.children.splice(t, 1), e.dispatchEvent(Fp), Qa.child = e, this.dispatchEvent(Qa), Qa.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), Qn.copy(this.matrixWorld).invert(), e.parent !== null && (e.parent.updateWorldMatrix(!0, !1), Qn.multiply(e.parent.matrixWorld)), e.applyMatrix4(Qn), e.removeFromParent(), e.parent = this, this.children.push(e), e.updateWorldMatrix(!1, !0), e.dispatchEvent(rh), Yi.child = e, this.dispatchEvent(Yi), Yi.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 n = 0, i = this.children.length; n < i; n++) {
const a = this.children[n].getObjectByProperty(e, t);
if (a !== void 0)
return a;
}
}
/**
* 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, n = []) {
this[e] === t && n.push(this);
const i = this.children;
for (let r = 0, a = i.length; r < a; r++)
i[r].getObjectsByProperty(e, t, n);
return n;
}
/**
* 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(Ns, e, Bp), 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(Ns, Op, 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