three三维江南水乡3D划船场景代码
代码语言:html
所属分类:其他
代码由minimx-m3.1-flash ai生成,可能有错误,仅供参考:点击查看提示词
代码描述:三维江南水乡3D划船场景
代码标签: three 三维 江南 水乡 3D 划船 场景 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<title>乌篷船 · 摇橹行舟 | Three.js</title>
<style>
:root{
--ink:#f2f6f8; --dim:rgba(242,246,248,.62);
--glass:rgba(16,28,34,.42); --line:rgba(255,255,255,.16);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden;background:#0a1016;}
body{font-family:"PingFang SC","Microsoft YaHei","Noto Sans SC",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:var(--ink);-webkit-font-smoothing:antialiased;}
canvas{display:block}
#hud{position:fixed;inset:0;pointer-events:none;z-index:10;}
.panel{background:var(--glass);border:1px solid var(--line);backdrop-filter:blur(14px) saturate(1.2);-webkit-backdrop-filter:blur(14px) saturate(1.2);border-radius:14px;}
#brand{position:absolute;left:22px;top:20px;padding:12px 16px 13px;}
#brand h1{margin:0;font-size:16px;letter-spacing:.22em;font-weight:600;}
#brand p{margin:5px 0 0;font-size:11px;letter-spacing:.14em;color:var(--dim);}
#stats{position:absolute;right:22px;top:20px;padding:12px 16px;min-width:150px;}
#stats .row{display:flex;justify-content:space-between;align-items:baseline;gap:18px;font-size:12px;color:var(--dim);margin:3px 0;}
#stats .row b{font-size:15px;color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:.02em;}
#keys{position:absolute;left:50%;bottom:22px;transform:translateX(-50%);padding:10px 18px;display:flex;gap:18px;flex-wrap:wrap;justify-content:center;font-size:11.5px;color:var(--dim);letter-spacing:.06em;}
#keys span b{color:var(--ink);font-weight:600;background:rgba(255,255,255,.10);border:1px solid var(--line);border-radius:6px;padding:2px 7px;margin-right:6px;font-size:11px;}
#hint{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);text-align:center;transition:opacity .8s ease;}
#hint .big{font-size:20px;letter-spacing:.34em;margin-bottom:12px;text-shadow:0 2px 26px rgba(0,0,0,.55);}
#hint .sub{font-size:12px;letter-spacing:.2em;color:var(--dim);}
#hint .pulse{margin-top:20px;width:2px;height:44px;background:linear-gradient(180deg,transparent,rgba(255,255,255,.85));animation:p 1.9s ease-in-out infinite;}
@keyframes p{0%,100%{opacity:.15;transform:scaleY(.5)}50%{opacity:.9;transform:scaleY(1)}}
#loader{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;
background:radial-gradient(120% 90% at 50% 30%,#1b3040 0%,#0a1016 70%);transition:opacity .9s ease;}
#loader .t{font-size:13px;letter-spacing:.4em;color:var(--dim);}
#loader .b{width:190px;height:2px;background:rgba(255,255,255,.14);overflow:hidden;border-radius:2px;}
#loader .b i{display:block;height:100%;width:35%;background:linear-gradient(90deg,transparent,#ffd9c0,transparent);animation:slide 1.25s ease-in-out infinite;}
@keyframes slide{0%{transform:translateX(-120%)}100%{transform:translateX(320%)}}
#fade{position:fixed;inset:0;z-index:20;background:#e9f0f2;opacity:0;pointer-events:none;transition:opacity .7s ease;}
#touch{position:fixed;inset:0;z-index:12;display:none;}
#touch button{position:absolute;pointer-events:auto;border:1px solid var(--line);background:var(--glass);color:var(--ink);
backdrop-filter:blur(12px);border-radius:16px;font-size:13px;letter-spacing:.1em;padding:14px 18px;}
#tRow{left:20px;bottom:96px;} #tL{left:20px;bottom:24px;} #tR{right:20px;bottom:24px;} #tN{right:20px;bottom:96px;}
@media (max-width:760px){
#touch{display:block} #keys{display:none} #brand{left:14px;top:14px;padding:9px 12px} #brand h1{font-size:13px}
#stats{right:14px;top:14px;padding:9px 12px;min-width:120px} #stats .row b{font-size:13px}
}
.hidden{opacity:0 !important;}
</style>
</head>
<body>
<div id="app"></div>
<div id="hud">
<div id="brand" class="panel">
<h1>乌篷船 · 摇橹行舟</h1>
<p>JIANGNAN RIVER · THREE.JS</p>
</div>
<div id="stats" class="panel">
<div class="row"><span>里程</span><b id="sDist">0 m</b></div>
<div class="row"><span>航速</span><b id="sSpeed">0.0</b></div>
<div class="row"><span>状态</span><b id="sState">漂行</b></div>
<div class="row"><span>时辰</span><b id="sTime">晨</b></div>
</div>
<div id="keys" class="panel">
<span><b>按住 W / ↑ / 鼠标左键</b>摇橹</span>
<span><b>A · D</b>转向</span>
<span><b>空格</b>快划</span>
<span><b>C</b>镜头</span>
<span><b>N</b>昼夜</span>
<span><b>M</b>水声</span>
<span><b>H</b>界面</span>
<span><b>R</b>归航</span>
</div>
<div id="hint">
<div class="big">摇橹 · 出发</div>
<div class="sub">按住 W 或拖动水面,船夫会为你撑起长篙</div>
<div class="pulse"></div>
</div>
</div>
<div id="touch">
<button id="tRow">摇橹</button>
<button id="tL">◀</button>
<button id="tR">▶</button>
<button id="tN">昼夜</button>
</div>
<div id="fade"></div>
<div id="loader"><div class="t">正在铺开山河</div><div class="b"><i></i></div></div>
<!-- three.js 已打包进本文件,双击即可运行,无需服务器 / 无需联网 -->
<script>
(() => {
// ../output/kyoto-boat/vendor/three/build/three.core.js
var REVISION = "186";
var CullFaceNone = 0;
var CullFaceBack = 1;
var CullFaceFront = 2;
var PCFShadowMap = 1;
var PCFSoftShadowMap = 2;
var VSMShadowMap = 3;
var FrontSide = 0;
var BackSide = 1;
var DoubleSide = 2;
var NoBlending = 0;
var NormalBlending = 1;
var AdditiveBlending = 2;
var SubtractiveBlending = 3;
var MultiplyBlending = 4;
var CustomBlending = 5;
var AddEquation = 100;
var SubtractEquation = 101;
var ReverseSubtractEquation = 102;
var MinEquation = 103;
var MaxEquation = 104;
var ZeroFactor = 200;
var OneFactor = 201;
var SrcColorFactor = 202;
var OneMinusSrcColorFactor = 203;
var SrcAlphaFactor = 204;
var OneMinusSrcAlphaFactor = 205;
var DstAlphaFactor = 206;
var OneMinusDstAlphaFactor = 207;
var DstColorFactor = 208;
var OneMinusDstColorFactor = 209;
var SrcAlphaSaturateFactor = 210;
var ConstantColorFactor = 211;
var OneMinusConstantColorFactor = 212;
var ConstantAlphaFactor = 213;
var OneMinusConstantAlphaFactor = 214;
var NeverDepth = 0;
var AlwaysDepth = 1;
var LessDepth = 2;
var LessEqualDepth = 3;
var EqualDepth = 4;
var GreaterEqualDepth = 5;
var GreaterDepth = 6;
var NotEqualDepth = 7;
var MultiplyOperation = 0;
var MixOperation = 1;
var AddOperation = 2;
var NoToneMapping = 0;
var LinearToneMapping = 1;
var ReinhardToneMapping = 2;
var CineonToneMapping = 3;
var ACESFilmicToneMapping = 4;
var CustomToneMapping = 5;
var AgXToneMapping = 6;
var NeutralToneMapping = 7;
var UVMapping = 300;
var CubeReflectionMapping = 301;
var CubeRefractionMapping = 302;
var EquirectangularReflectionMapping = 303;
var EquirectangularRefractionMapping = 304;
var CubeUVReflectionMapping = 306;
var RepeatWrapping = 1e3;
var ClampToEdgeWrapping = 1001;
var MirroredRepeatWrapping = 1002;
var NearestFilter = 1003;
var NearestMipmapNearestFilter = 1004;
var NearestMipmapLinearFilter = 1005;
var LinearFilter = 1006;
var LinearMipmapNearestFilter = 1007;
var LinearMipmapLinearFilter = 1008;
var UnsignedByteType = 1009;
var ByteType = 1010;
var ShortType = 1011;
var UnsignedShortType = 1012;
var IntType = 1013;
var UnsignedIntType = 1014;
var FloatType = 1015;
var HalfFloatType = 1016;
var UnsignedShort4444Type = 1017;
var UnsignedShort5551Type = 1018;
var UnsignedInt248Type = 1020;
var UnsignedInt5999Type = 35902;
var UnsignedInt101111Type = 35899;
var AlphaFormat = 1021;
var RGBFormat = 1022;
var RGBAFormat = 1023;
var DepthFormat = 1026;
var DepthStencilFormat = 1027;
var RedFormat = 1028;
var RedIntegerFormat = 1029;
var RGFormat = 1030;
var RGIntegerFormat = 1031;
var RGBAIntegerFormat = 1033;
var RGB_S3TC_DXT1_Format = 33776;
var RGBA_S3TC_DXT1_Format = 33777;
var RGBA_S3TC_DXT3_Format = 33778;
var RGBA_S3TC_DXT5_Format = 33779;
var RGB_PVRTC_4BPPV1_Format = 35840;
var RGB_PVRTC_2BPPV1_Format = 35841;
var RGBA_PVRTC_4BPPV1_Format = 35842;
var RGBA_PVRTC_2BPPV1_Format = 35843;
var RGB_ETC1_Format = 36196;
var RGB_ETC2_Format = 37492;
var RGBA_ETC2_EAC_Format = 37496;
var R11_EAC_Format = 37488;
var SIGNED_R11_EAC_Format = 37489;
var RG11_EAC_Format = 37490;
var SIGNED_RG11_EAC_Format = 37491;
var RGBA_ASTC_4x4_Format = 37808;
var RGBA_ASTC_5x4_Format = 37809;
var RGBA_ASTC_5x5_Format = 37810;
var RGBA_ASTC_6x5_Format = 37811;
var RGBA_ASTC_6x6_Format = 37812;
var RGBA_ASTC_8x5_Format = 37813;
var RGBA_ASTC_8x6_Format = 37814;
var RGBA_ASTC_8x8_Format = 37815;
var RGBA_ASTC_10x5_Format = 37816;
var RGBA_ASTC_10x6_Format = 37817;
var RGBA_ASTC_10x8_Format = 37818;
var RGBA_ASTC_10x10_Format = 37819;
var RGBA_ASTC_12x10_Format = 37820;
var RGBA_ASTC_12x12_Format = 37821;
var RGBA_BPTC_Format = 36492;
var RGB_BPTC_SIGNED_Format = 36494;
var RGB_BPTC_UNSIGNED_Format = 36495;
var RED_RGTC1_Format = 36283;
var SIGNED_RED_RGTC1_Format = 36284;
var RED_GREEN_RGTC2_Format = 36285;
var SIGNED_RED_GREEN_RGTC2_Format = 36286;
var InterpolateDiscrete = 2300;
var InterpolateLinear = 2301;
var InterpolateSmooth = 2302;
var InterpolateBezier = 2303;
var ZeroCurvatureEnding = 2400;
var ZeroSlopeEnding = 2401;
var WrapAroundEnding = 2402;
var BasicDepthPacking = 3200;
var TangentSpaceNormalMap = 0;
var ObjectSpaceNormalMap = 1;
var NoColorSpace = "";
var SRGBColorSpace = "srgb";
var LinearSRGBColorSpace = "srgb-linear";
var LinearTransfer = "linear";
var SRGBTransfer = "srgb";
var KeepStencilOp = 7680;
var AlwaysStencilFunc = 519;
var NeverCompare = 512;
var LessCompare = 513;
var EqualCompare = 514;
var LessEqualCompare = 515;
var GreaterCompare = 516;
var NotEqualCompare = 517;
var GreaterEqualCompare = 518;
var AlwaysCompare = 519;
var StaticDrawUsage = 35044;
var GLSL3 = "300 es";
var WebGLCoordinateSystem = 2e3;
var WebGPUCoordinateSystem = 2001;
function arrayNeedsUint32(array) {
for (let i = array.length - 1; i >= 0; --i) {
if (array[i] >= 65535) return true;
}
return false;
}
function isTypedArray(array) {
return ArrayBuffer.isView(array) && !(array instanceof DataView);
}
function createElementNS(name) {
return document.createElementNS("http://www.w3.org/1999/xhtml", name);
}
function createCanvasElement() {
const canvas = createElementNS("canvas");
canvas.style.display = "block";
return canvas;
}
var _cache = {};
var _setConsoleFunction = null;
function log(...params) {
const message = "THREE." + params.shift();
if (_setConsoleFunction) {
_setConsoleFunction("log", message, ...params);
} else {
console.log(message, ...params);
}
}
function enhanceLogMessage(params) {
const message = params[0];
if (typeof message === "string" && message.startsWith("TSL:")) {
const stackTrace = params[1];
if (stackTrace && stackTrace.isStackTrace) {
params[0] += " " + stackTrace.getLocation();
} else {
params[1] = 'Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.';
}
}
return params;
}
function warn(...params) {
params = enhanceLogMessage(params);
const message = "THREE." + params.shift();
if (_setConsoleFunction) {
_setConsoleFunction("warn", message, ...params);
} else {
const stackTrace = params[0];
if (stackTrace && stackTrace.isStackTrace) {
console.warn(stackTrace.getError(message));
} else {
console.warn(message, ...params);
}
}
}
function error(...params) {
params = enhanceLogMessage(params);
const message = "THREE." + params.shift();
if (_setConsoleFunction) {
_setConsoleFunction("error", message, ...params);
} else {
const stackTrace = params[0];
if (stackTrace && stackTrace.isStackTrace) {
console.error(stackTrace.getError(message));
} else {
console.error(message, ...params);
}
}
}
function warnOnce(...params) {
const message = params.join(" ");
if (message in _cache) return;
_cache[message] = true;
warn(...params);
}
function probeAsync(gl, sync, interval) {
return new Promise(function(resolve, reject) {
function probe() {
switch (gl.clientWaitSync(sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0)) {
case gl.WAIT_FAILED:
reject();
break;
case gl.TIMEOUT_EXPIRED:
setTimeout(probe, interval);
break;
default:
resolve();
}
}
setTimeout(probe, interval);
});
}
var ReversedDepthFuncs = {
[NeverDepth]: AlwaysDepth,
[LessDepth]: GreaterDepth,
[EqualDepth]: NotEqualDepth,
[LessEqualDepth]: GreaterEqualDepth,
[AlwaysDepth]: NeverDepth,
[GreaterDepth]: LessDepth,
[NotEqualDepth]: EqualDepth,
[GreaterEqualDepth]: LessEqualDepth
};
var EventDispatcher = class {
/**
* 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(type, listener) {
if (this._listeners === void 0) this._listeners = {};
const listeners = this._listeners;
if (listeners[type] === void 0) {
listeners[type] = [];
}
if (listeners[type].indexOf(listener) === -1) {
listeners[type].push(listener);
}
}
/**
* 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(type, listener) {
const listeners = this._listeners;
if (listeners === void 0) return false;
return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -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(type, listener) {
const listeners = this._listeners;
if (listeners === void 0) return;
const listenerArray = listeners[type];
if (listenerArray !== void 0) {
const index = listenerArray.indexOf(listener);
if (index !== -1) {
listenerArray.splice(index, 1);
}
}
}
/**
* Dispatches an event object.
*
* @param {Object} event - The event that gets fired.
*/
dispatchEvent(event) {
const listeners = this._listeners;
if (listeners === void 0) return;
const listenerArray = listeners[event.type];
if (listenerArray !== void 0) {
event.target = this;
const array = listenerArray.slice(0);
for (let i = 0, l = array.length; i < l; i++) {
array[i].call(this, event);
}
event.target = null;
}
}
};
var _lut = ["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"];
var DEG2RAD = Math.PI / 180;
var RAD2DEG = 180 / Math.PI;
function generateUUID() {
const d0 = Math.random() * 4294967295 | 0;
const d1 = Math.random() * 4294967295 | 0;
const d2 = Math.random() * 4294967295 | 0;
const d3 = Math.random() * 4294967295 | 0;
const uuid = _lut[d0 & 255] + _lut[d0 >> 8 & 255] + _lut[d0 >> 16 & 255] + _lut[d0 >> 24 & 255] + "-" + _lut[d1 & 255] + _lut[d1 >> 8 & 255] + "-" + _lut[d1 >> 16 & 15 | 64] + _lut[d1 >> 24 & 255] + "-" + _lut[d2 & 63 | 128] + _lut[d2 >> 8 & 255] + "-" + _lut[d2 >> 16 & 255] + _lut[d2 >> 24 & 255] + _lut[d3 & 255] + _lut[d3 >> 8 & 255] + _lut[d3 >> 16 & 255] + _lut[d3 >> 24 & 255];
return uuid.toLowerCase();
}
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
function euclideanModulo(n, m) {
return (n % m + m) % m;
}
function lerp(x, y, t) {
return (1 - t) * x + t * y;
}
function denormalize(value, array) {
switch (array.constructor) {
case Float32Array:
return value;
case Uint32Array:
return value / 4294967295;
case Uint16Array:
return value / 65535;
case Uint8Array:
case Uint8ClampedArray:
return value / 255;
case Int32Array:
return Math.max(value / 2147483647, -1);
case Int16Array:
return Math.max(value / 32767, -1);
case Int8Array:
return Math.max(value / 127, -1);
default:
throw new Error("THREE.MathUtils: Invalid component type.");
}
}
function normalize(value, array) {
switch (array.constructor) {
case Float32Array:
return value;
case Uint32Array:
return Math.round(value * 4294967295);
case Uint16Array:
return Math.round(value * 65535);
case Uint8Array:
case Uint8ClampedArray:
return Math.round(value * 255);
case Int32Array:
return Math.round(value * 2147483647);
case Int16Array:
return Math.round(value * 32767);
case Int8Array:
return Math.round(value * 127);
default:
throw new Error("THREE.MathUtils: Invalid component type.");
}
}
var _Vector2 = class _Vector2 {
/**
* 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(x = 0, y = 0) {
this.x = x;
this.y = y;
}
/**
* Alias for {@link Vector2#x}.
*
* @type {number}
*/
get width() {
return this.x;
}
set width(value) {
this.x = value;
}
/**
* Alias for {@link Vector2#y}.
*
* @type {number}
*/
get height() {
return this.y;
}
set height(value) {
this.y = value;
}
/**
* 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(x, y) {
this.x = x;
this.y = y;
return 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(scalar) {
this.x = scalar;
this.y = scalar;
return 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(x) {
this.x = x;
return 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(y) {
this.y = y;
return 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(index, value) {
switch (index) {
case 0:
this.x = value;
break;
case 1:
this.y = value;
break;
default:
throw new Error("THREE.Vector2: index is out of range: " + index);
}
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(index) {
switch (index) {
case 0:
return this.x;
case 1:
return this.y;
default:
throw new Error("THREE.Vector2: index is out of range: " + index);
}
}
/**
* 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(v) {
this.x = v.x;
this.y = v.y;
return this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector2} v - The vector to add.
* @return {Vector2} A reference to this vector.
*/
add(v) {
this.x += v.x;
this.y += v.y;
return 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(s) {
this.x += s;
this.y += s;
return 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(a, b) {
this.x = a.x + b.x;
this.y = a.y + b.y;
return 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(v, s) {
this.x += v.x * s;
this.y += v.y * s;
return this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector2} v - The vector to subtract.
* @return {Vector2} A reference to this vector.
*/
sub(v) {
this.x -= v.x;
this.y -= v.y;
return 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(s) {
this.x -= s;
this.y -= s;
return 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(a, b) {
this.x = a.x - b.x;
this.y = a.y - b.y;
return this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector2} v - The vector to multiply.
* @return {Vector2} A reference to this vector.
*/
multiply(v) {
this.x *= v.x;
this.y *= v.y;
return 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(scalar) {
this.x *= scalar;
this.y *= scalar;
return this;
}
/**
* Divides this instance by the given vector.
*
* @param {Vector2} v - The vector to divide.
* @return {Vector2} A reference to this vector.
*/
divide(v) {
this.x /= v.x;
this.y /= v.y;
return this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector2} A reference to this vector.
*/
divideScalar(scalar) {
return this.multiplyScalar(1 / scalar);
}
/**
* 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(m) {
const x = this.x, y = this.y;
const e = m.elements;
this.x = e[0] * x + e[3] * y + e[6];
this.y = e[1] * x + e[4] * y + e[7];
return 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(v) {
this.x = Math.min(this.x, v.x);
this.y = Math.min(this.y, v.y);
return 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(v) {
this.x = Math.max(this.x, v.x);
this.y = Math.max(this.y, v.y);
return 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(min, max) {
this.x = clamp(this.x, min.x, max.x);
this.y = clamp(this.y, min.y, max.y);
return 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(minVal, maxVal) {
this.x = clamp(this.x, minVal, maxVal);
this.y = clamp(this.y, minVal, maxVal);
return 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(min, max) {
const length = this.length();
return this.divideScalar(length || 1).multiplyScalar(clamp(length, min, max));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/
floor() {
this.x = Math.floor(this.x);
this.y = Math.floor(this.y);
return this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector2} A reference to this vector.
*/
ceil() {
this.x = Math.ceil(this.x);
this.y = Math.ceil(this.y);
return this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector2} A reference to this vector.
*/
round() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return 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() {
this.x = Math.trunc(this.x);
this.y = Math.trunc(this.y);
return this;
}
/**
* Inverts this vector - i.e. sets x = -x and y = -y.
*
* @return {Vector2} A reference to this vector.
*/
negate() {
this.x = -this.x;
this.y = -this.y;
return 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(v) {
return this.x * v.x + this.y * v.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(v) {
return this.x * v.y - this.y * v.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() {
const angle = Math.atan2(-this.y, -this.x) + Math.PI;
return angle;
}
/**
* 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(v) {
const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
if (denominator === 0) return Math.PI / 2;
const theta = this.dot(v) / denominator;
return Math.acos(clamp(theta, -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(v) {
return Math.sqrt(this.distanceToSquared(v));
}
/**
* 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(v) {
const dx = this.x - v.x, dy = this.y - v.y;
return dx * dx + dy * dy;
}
/**
* 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(v) {
return Math.abs(this.x - v.x) + Math.abs(this.y - v.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(length) {
return this.normalize().multiplyScalar(length);
}
/**
* 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(v, alpha) {
this.x += (v.x - this.x) * alpha;
this.y += (v.y - this.y) * alpha;
return 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(v1, v2, alpha) {
this.x = v1.x + (v2.x - v1.x) * alpha;
this.y = v1.y + (v2.y - v1.y) * alpha;
return 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(v) {
return v.x === this.x && v.y === this.y;
}
/**
* Sets this vector's x value to be `array[ offset ]` and y
* value to be `array[ offset + 1 ]`.
*
* @param {Array<number>} 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(array, offset = 0) {
this.x = array[offset];
this.y = array[offset + 1];
return this;
}
/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array<number>} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array<number>} The vector components.
*/
toArray(array = [], offset = 0) {
array[offset] = this.x;
array[offset + 1] = this.y;
return array;
}
/**
* 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(attribute, index) {
this.x = attribute.getX(index);
this.y = attribute.getY(index);
return 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(center, angle) {
const c = Math.cos(angle), s = Math.sin(angle);
const x = this.x - center.x;
const y = this.y - center.y;
this.x = x * c - y * s + center.x;
this.y = x * s + y * c + center.y;
return 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() {
this.x = Math.random();
this.y = Math.random();
return this;
}
*[Symbol.iterator]() {
yield this.x;
yield this.y;
}
};
_Vector2.prototype.isVector2 = true;
var Vector2 = _Vector2;
var Quaternion = class {
/**
* 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(x = 0, y = 0, z = 0, w = 1) {
this.isQuaternion = true;
this._x = x;
this._y = y;
this._z = z;
this._w = w;
}
/**
* Interpolates between two quaternions via SLERP. This implementation assumes the
* quaternion data are managed in flat arrays.
*
* @param {Array<number>} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array<number>} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array<number>} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
* @see {@link Quaternion#slerp}
*/
static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {
let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3];
let x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3];
if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
let dot = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1;
if (dot < 0) {
x1 = -x1;
y1 = -y1;
z1 = -z1;
w1 = -w1;
dot = -dot;
}
let s = 1 - t;
if (dot < 0.9995) {
const theta = Math.acos(dot);
const sin = Math.sin(theta);
s = Math.sin(s * theta) / sin;
t = Math.sin(t * theta) / sin;
x0 = x0 * s + x1 * t;
y0 = y0 * s + y1 * t;
z0 = z0 * s + z1 * t;
w0 = w0 * s + w1 * t;
} else {
x0 = x0 * s + x1 * t;
y0 = y0 * s + y1 * t;
z0 = z0 * s + z1 * t;
w0 = w0 * s + w1 * t;
const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);
x0 *= f;
y0 *= f;
z0 *= f;
w0 *= f;
}
}
dst[dstOffset] = x0;
dst[dstOffset + 1] = y0;
dst[dstOffset + 2] = z0;
dst[dstOffset + 3] = w0;
}
/**
* Multiplies two quaternions. This implementation assumes the quaternion data are managed
* in flat arrays.
*
* @param {Array<number>} dst - The destination array.
* @param {number} dstOffset - An offset into the destination array.
* @param {Array<number>} src0 - The source array of the first quaternion.
* @param {number} srcOffset0 - An offset into the first source array.
* @param {Array<number>} src1 - The source array of the second quaternion.
* @param {number} srcOffset1 - An offset into the second source array.
* @return {Array<number>} The destination array.
* @see {@link Quaternion#multiplyQuaternions}.
*/
static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) {
const x0 = src0[srcOffset0];
const y0 = src0[srcOffset0 + 1];
const z0 = src0[srcOffset0 + 2];
const w0 = src0[srcOffset0 + 3];
const x1 = src1[srcOffset1];
const y1 = src1[srcOffset1 + 1];
const z1 = src1[srcOffset1 + 2];
const w1 = src1[srcOffset1 + 3];
dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
return dst;
}
/**
* The x value of this quaternion.
*
* @type {number}
* @default 0
*/
get x() {
return this._x;
}
set x(value) {
this._x = value;
this._onChangeCallback();
}
/**
* The y value of this quaternion.
*
* @type {number}
* @default 0
*/
get y() {
return this._y;
}
set y(value) {
this._y = value;
this._onChangeCallback();
}
/**
* The z value of this quaternion.
*
* @type {number}
* @default 0
*/
get z() {
return this._z;
}
set z(value) {
this._z = value;
this._onChangeCallback();
}
/**
* The w value of this quaternion.
*
* @type {number}
* @default 1
*/
get w() {
return this._w;
}
set w(value) {
this._w = value;
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(x, y, z, w) {
this._x = x;
this._y = y;
this._z = z;
this._w = w;
this._onChangeCallback();
return 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(quaternion) {
this._x = quaternion.x;
this._y = quaternion.y;
this._z = quaternion.z;
this._w = quaternion.w;
this._onChangeCallback();
return 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(euler, update = true) {
const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
const cos = Math.cos;
const sin = Math.sin;
const c1 = cos(x / 2);
const c2 = cos(y / 2);
const c3 = cos(z / 2);
const s1 = sin(x / 2);
const s2 = sin(y / 2);
const s3 = sin(z / 2);
switch (order) {
case "XYZ":
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
break;
case "YXZ":
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
break;
case "ZXY":
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
break;
case "ZYX":
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
break;
case "YZX":
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
break;
case "XZY":
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
break;
default:
warn("Quaternion: .setFromEuler() encountered an unknown order: " + order);
}
if (update === true) this._onChangeCallback();
return 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(axis, angle) {
const halfAngle = angle / 2, s = Math.sin(halfAngle);
this._x = axis.x * s;
this._y = axis.y * s;
this._z = axis.z * s;
this._w = Math.cos(halfAngle);
this._onChangeCallback();
return 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(m) {
const te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33;
if (trace > 0) {
const s = 0.5 / Math.sqrt(trace + 1);
this._w = 0.25 / s;
this._x = (m32 - m23) * s;
this._y = (m13 - m31) * s;
this._z = (m21 - m12) * s;
} else if (m11 > m22 && m11 > m33) {
const s = 2 * Math.sqrt(1 + m11 - m22 - m33);
this._w = (m32 - m23) / s;
this._x = 0.25 * s;
this._y = (m12 + m21) / s;
this._z = (m13 + m31) / s;
} else if (m22 > m33) {
const s = 2 * Math.sqrt(1 + m22 - m11 - m33);
this._w = (m13 - m31) / s;
this._x = (m12 + m21) / s;
this._y = 0.25 * s;
this._z = (m23 + m32) / s;
} else {
const s = 2 * Math.sqrt(1 + m33 - m11 - m22);
this._w = (m21 - m12) / s;
this._x = (m13 + m31) / s;
this._y = (m23 + m32) / s;
this._z = 0.25 * s;
}
this._onChangeCallback();
return 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(vFrom, vTo) {
let r = vFrom.dot(vTo) + 1;
if (r < 1e-8) {
r = 0;
if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
this._x = -vFrom.y;
this._y = vFrom.x;
this._z = 0;
this._w = r;
} else {
this._x = 0;
this._y = -vFrom.z;
this._z = vFrom.y;
this._w = r;
}
} else {
this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
this._w = r;
}
return 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(q) {
return 2 * Math.acos(Math.abs(clamp(this.dot(q), -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(q, step) {
const angle = this.angleTo(q);
if (angle === 0) return this;
const t = Math.min(1, step / angle);
this.slerp(q, t);
return 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() {
this._x *= -1;
this._y *= -1;
this._z *= -1;
this._onChangeCallback();
return 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(v) {
return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._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 l = this.length();
if (l === 0) {
this._x = 0;
this._y = 0;
this._z = 0;
this._w = 1;
} else {
l = 1 / l;
this._x = this._x * l;
this._y = this._y * l;
this._z = this._z * l;
this._w = this._w * l;
}
this._onChangeCallback();
return this;
}
/**
* Multiplies this quaternion by the given one.
*
* @param {Quaternion} q - The quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
multiply(q) {
return this.multiplyQuaternions(this, q);
}
/**
* Pre-multiplies this quaternion by the given one.
*
* @param {Quaternion} q - The quaternion.
* @return {Quaternion} A reference to this quaternion.
*/
premultiply(q) {
return this.multiplyQuaternions(q, 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(a, b) {
const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
this._onChangeCallback();
return this;
}
/**
* Performs a spherical linear interpolation between this quaternion and the target quaternion.
*
* @param {Quaternion} qb - The target quaternion.
* @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
* @return {Quaternion} A reference to this quaternion.
*/
slerp(qb, t) {
let x = qb._x, y = qb._y, z = qb._z, w = qb._w;
let dot = this.dot(qb);
if (dot < 0) {
x = -x;
y = -y;
z = -z;
w = -w;
dot = -dot;
}
let s = 1 - t;
if (dot < 0.9995) {
const theta = Math.acos(dot);
const sin = Math.sin(theta);
s = Math.sin(s * theta) / sin;
t = Math.sin(t * theta) / sin;
this._x = this._x * s + x * t;
this._y = this._y * s + y * t;
this._z = this._z * s + z * t;
this._w = this._w * s + w * t;
this._onChangeCallback();
} else {
this._x = this._x * s + x * t;
this._y = this._y * s + y * t;
this._z = this._z * s + z * t;
this._w = this._w * s + w * 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(qa, qb, t) {
return this.copy(qa).slerp(qb, t);
}
/**
* Sets this quaternion to a uniformly random, normalized quaternion.
*
* @return {Quaternion} A reference to this quaternion.
*/
random() {
const theta1 = 2 * Math.PI * Math.random();
const theta2 = 2 * Math.PI * Math.random();
const x0 = Math.random();
const r1 = Math.sqrt(1 - x0);
const r2 = Math.sqrt(x0);
return this.set(
r1 * Math.sin(theta1),
r1 * Math.cos(theta1),
r2 * Math.sin(theta2),
r2 * Math.cos(theta2)
);
}
/**
* 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(quaternion) {
return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w;
}
/**
* Sets this quaternion's components from the given array.
*
* @param {Array<number>} 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(array, offset = 0) {
this._x = array[offset];
this._y = array[offset + 1];
this._z = array[offset + 2];
this._w = array[offset + 3];
this._onChangeCallback();
return this;
}
/**
* Writes the components of this quaternion to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array<number>} [array=[]] - The target array holding the quaternion components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array<number>} The quaternion components.
*/
toArray(array = [], offset = 0) {
array[offset] = this._x;
array[offset + 1] = this._y;
array[offset + 2] = this._z;
array[offset + 3] = this._w;
return array;
}
/**
* 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(attribute, index) {
this._x = attribute.getX(index);
this._y = attribute.getY(index);
this._z = attribute.getZ(index);
this._w = attribute.getW(index);
this._onChangeCallback();
return 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<number>} The serialized quaternion.
*/
toJSON() {
return this.toArray();
}
_onChange(callback) {
this._onChangeCallback = callback;
return this;
}
_onChangeCallback() {
}
*[Symbol.iterator]() {
yield this._x;
yield this._y;
yield this._z;
yield this._w;
}
};
var _Vector3 = class _Vector3 {
/**
* 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(x = 0, y = 0, z = 0) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* 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(x, y, z) {
if (z === void 0) z = this.z;
this.x = x;
this.y = y;
this.z = z;
return 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(scalar) {
this.x = scalar;
this.y = scalar;
this.z = scalar;
return 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(x) {
this.x = x;
return 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(y) {
this.y = y;
return 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(z) {
this.z = z;
return 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(index, value) {
switch (index) {
case 0:
this.x = value;
break;
case 1:
this.y = value;
break;
case 2:
this.z = value;
break;
default:
throw new Error("THREE.Vector3: index is out of range: " + index);
}
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(index) {
switch (index) {
case 0:
return this.x;
case 1:
return this.y;
case 2:
return this.z;
default:
throw new Error("THREE.Vector3: index is out of range: " + index);
}
}
/**
* 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(v) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
return this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector3} v - The vector to add.
* @return {Vector3} A reference to this vector.
*/
add(v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return 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(s) {
this.x += s;
this.y += s;
this.z += s;
return 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(a, b) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
return 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(v, s) {
this.x += v.x * s;
this.y += v.y * s;
this.z += v.z * s;
return this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector3} v - The vector to subtract.
* @return {Vector3} A reference to this vector.
*/
sub(v) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
return 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(s) {
this.x -= s;
this.y -= s;
this.z -= s;
return 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(a, b) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
return this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector3} v - The vector to multiply.
* @return {Vector3} A reference to this vector.
*/
multiply(v) {
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
return 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(scalar) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
return 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(a, b) {
this.x = a.x * b.x;
this.y = a.y * b.y;
this.z = a.z * b.z;
return this;
}
/**
* Applies the given Euler rotation to this vector.
*
* @param {Euler} euler - The Euler angles.
* @return {Vector3} A reference to this vector.
*/
applyEuler(euler) {
return this.applyQuaternion(_quaternion$5.setFromEuler(euler));
}
/**
* 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(axis, angle) {
return this.applyQuaternion(_quaternion$5.setFromAxisAngle(axis, angle));
}
/**
* Multiplies this vector with the given 3x3 matrix.
*
* @param {Matrix3} m - The 3x3 matrix.
* @return {Vector3} A reference to this vector.
*/
applyMatrix3(m) {
const x = this.x, y = this.y, z = this.z;
const e = m.elements;
this.x = e[0] * x + e[3] * y + e[6] * z;
this.y = e[1] * x + e[4] * y + e[7] * z;
this.z = e[2] * x + e[5] * y + e[8] * z;
return 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(m) {
return this.applyMatrix3(m).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(m) {
const x = this.x, y = this.y, z = this.z;
const e = m.elements;
const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
return this;
}
/**
* Applies the given Quaternion to this vector.
*
* @param {Quaternion} q - The Quaternion.
* @return {Vector3} A reference to this vector.
*/
applyQuaternion(q) {
const vx = this.x, vy = this.y, vz = this.z;
const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
const tx = 2 * (qy * vz - qz * vy);
const ty = 2 * (qz * vx - qx * vz);
const tz = 2 * (qx * vy - qy * vx);
this.x = vx + qw * tx + qy * tz - qz * ty;
this.y = vy + qw * ty + qz * tx - qx * tz;
this.z = vz + qw * tz + qx * ty - qy * tx;
return 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(camera2) {
return this.applyMatrix4(camera2.matrixWorldInverse).applyMatrix4(camera2.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(camera2) {
return this.applyMatrix4(camera2.projectionMatrixInverse).applyMatrix4(camera2.matrixWorld);
}
/**
* Transforms this vector by the upper left 3x3 sub-matrix of the given 4x4 matrix,
* and normalizes the result.
*
* @param {Matrix4} m - The matrix.
* @return {Vector3} A reference to this vector.
*/
transformDirection(m) {
const x = this.x, y = this.y, z = this.z;
const e = m.elements;
this.x = e[0] * x + e[4] * y + e[8] * z;
this.y = e[1] * x + e[5] * y + e[9] * z;
this.z = e[2] * x + e[6] * y + e[10] * z;
return this.normalize();
}
/**
* Divides this instance by the given vector.
*
* @param {Vector3} v - The vector to divide.
* @return {Vector3} A reference to this vector.
*/
divide(v) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
return this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector3} A reference to this vector.
*/
divideScalar(scalar) {
return this.multiplyScalar(1 / scalar);
}
/**
* 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(v) {
this.x = Math.min(this.x, v.x);
this.y = Math.min(this.y, v.y);
this.z = Math.min(this.z, v.z);
return 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(v) {
this.x = Math.max(this.x, v.x);
this.y = Math.max(this.y, v.y);
this.z = Math.max(this.z, v.z);
return 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(min, max) {
this.x = clamp(this.x, min.x, max.x);
this.y = clamp(this.y, min.y, max.y);
this.z = clamp(this.z, min.z, max.z);
return 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(minVal, maxVal) {
this.x = clamp(this.x, minVal, maxVal);
this.y = clamp(this.y, minVal, maxVal);
this.z = clamp(this.z, minVal, maxVal);
return 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(min, max) {
const length = this.length();
return this.divideScalar(length || 1).multiplyScalar(clamp(length, min, max));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector3} A reference to this vector.
*/
floor() {
this.x = Math.floor(this.x);
this.y = Math.floor(this.y);
this.z = Math.floor(this.z);
return this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector3} A reference to this vector.
*/
ceil() {
this.x = Math.ceil(this.x);
this.y = Math.ceil(this.y);
this.z = Math.ceil(this.z);
return this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector3} A reference to this vector.
*/
round() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
this.z = Math.round(this.z);
return 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() {
this.x = Math.trunc(this.x);
this.y = Math.trunc(this.y);
this.z = Math.trunc(this.z);
return this;
}
/**
* Inverts this vector - i.e. sets x = -x, y = -y and z = -z.
*
* @return {Vector3} A reference to this vector.
*/
negate() {
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
return 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(v) {
return this.x * v.x + this.y * v.y + this.z * v.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(length) {
return this.normalize().multiplyScalar(length);
}
/**
* 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(v, alpha) {
this.x += (v.x - this.x) * alpha;
this.y += (v.y - this.y) * alpha;
this.z += (v.z - this.z) * alpha;
return 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(v1, v2, alpha) {
this.x = v1.x + (v2.x - v1.x) * alpha;
this.y = v1.y + (v2.y - v1.y) * alpha;
this.z = v1.z + (v2.z - v1.z) * alpha;
return 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(v) {
return this.crossVectors(this, v);
}
/**
* 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(a, b) {
const ax = a.x, ay = a.y, az = a.z;
const bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
}
/**
* Projects this vector onto the given one.
*
* @param {Vector3} v - The vector to project to.
* @return {Vector3} A reference to this vector.
*/
projectOnVector(v) {
const denominator = v.lengthSq();
if (denominator === 0) return this.set(0, 0, 0);
const scalar = v.dot(this) / denominator;
return this.copy(v).multiplyScalar(scalar);
}
/**
* 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(planeNormal) {
_vector$c.copy(this).projectOnVector(planeNormal);
return this.sub(_vector$c);
}
/**
* 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(normal) {
return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)));
}
/**
* 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(v) {
const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
if (denominator === 0) return Math.PI / 2;
const theta = this.dot(v) / denominator;
return Math.acos(clamp(theta, -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(v) {
return Math.sqrt(this.distanceToSquared(v));
}
/**
* 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(v) {
const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
return dx * dx + dy * dy + dz * dz;
}
/**
* 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(v) {
return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);
}
/**
* Sets the vector components from the given spherical coordinates.
*
* @param {Spherical} s - The spherical coordinates.
* @return {Vector3} A reference to this vector.
*/
setFromSpherical(s) {
return this.setFromSphericalCoords(s.radius, s.phi, s.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(radius, phi, theta) {
const sinPhiRadius = Math.sin(phi) * radius;
this.x = sinPhiRadius * Math.sin(theta);
this.y = Math.cos(phi) * radius;
this.z = sinPhiRadius * Math.cos(theta);
return this;
}
/**
* Sets the vector components from the given cylindrical coordinates.
*
* @param {Cylindrical} c - The cylindrical coordinates.
* @return {Vector3} A reference to this vector.
*/
setFromCylindrical(c) {
return this.setFromCylindricalCoords(c.radius, c.theta, c.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(radius, theta, y) {
this.x = radius * Math.sin(theta);
this.y = y;
this.z = radius * Math.cos(theta);
return 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(m) {
const e = m.elements;
this.x = e[12];
this.y = e[13];
this.z = e[14];
return 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(m) {
const sx = this.setFromMatrixColumn(m, 0).length();
const sy = this.setFromMatrixColumn(m, 1).length();
const sz = this.setFromMatrixColumn(m, 2).length();
this.x = sx;
this.y = sy;
this.z = sz;
return 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(m, index) {
return this.fromArray(m.elements, index * 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(m, index) {
return this.fromArray(m.elements, index * 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) {
this.x = e._x;
this.y = e._y;
this.z = e._z;
return 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(c) {
this.x = c.r;
this.y = c.g;
this.z = c.b;
return 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(v) {
return v.x === this.x && v.y === this.y && v.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<number>} 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(array, offset = 0) {
this.x = array[offset];
this.y = array[offset + 1];
this.z = array[offset + 2];
return this;
}
/**
* Writes the components of this vector to the given array. If no array is provided,
* the method returns a new instance.
*
* @param {Array<number>} [array=[]] - The target array holding the vector components.
* @param {number} [offset=0] - Index of the first element in the array.
* @return {Array<number>} The vector components.
*/
toArray(array = [], offset = 0) {
array[offset] = this.x;
array[offset + 1] = this.y;
array[offset + 2] = this.z;
return array;
}
/**
* 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(attribute, index) {
this.x = attribute.getX(index);
this.y = attribute.getY(index);
this.z = attribute.getZ(index);
return 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() {
this.x = Math.random();
this.y = Math.random();
this.z = Math.random();
return this;
}
/**
* Sets this vector to a uniformly random point on a unit sphere.
*
* @return {Vector3} A reference to this vector.
*/
randomDirection() {
const theta = Math.random() * Math.PI * 2;
const u = Math.random() * 2 - 1;
const c = Math.sqrt(1 - u * u);
this.x = c * Math.cos(theta);
this.y = u;
this.z = c * Math.sin(theta);
return this;
}
*[Symbol.iterator]() {
yield this.x;
yield this.y;
yield this.z;
}
};
_Vector3.prototype.isVector3 = true;
var Vector3 = _Vector3;
var _vector$c = /* @__PURE__ */ new Vector3();
var _quaternion$5 = /* @__PURE__ */ new Quaternion();
var _Matrix3 = class _Matrix3 {
/**
* 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(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
this.elements = [
1,
0,
0,
0,
1,
0,
0,
0,
1
];
if (n11 !== void 0) {
this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);
}
}
/**
* 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(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
const te = this.elements;
te[0] = n11;
te[1] = n21;
te[2] = n31;
te[3] = n12;
te[4] = n22;
te[5] = n32;
te[6] = n13;
te[7] = n23;
te[8] = n33;
return this;
}
/**
* Sets this matrix to the 3x3 identity matrix.
*
* @return {Matrix3} A reference to this matrix.
*/
identity() {
this.set(
1,
0,
0,
0,
1,
0,
0,
0,
1
);
return 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(m) {
const te = this.elements;
const me = m.elements;
te[0] = me[0];
te[1] = me[1];
te[2] = me[2];
te[3] = me[3];
te[4] = me[4];
te[5] = me[5];
te[6] = me[6];
te[7] = me[7];
te[8] = me[8];
return 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(xAxis, yAxis, zAxis) {
xAxis.setFromMatrix3Column(this, 0);
yAxis.setFromMatrix3Column(this, 1);
zAxis.setFromMatrix3Column(this, 2);
return 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(m) {
const me = m.elements;
this.set(
me[0],
me[4],
me[8],
me[1],
me[5],
me[9],
me[2],
me[6],
me[10]
);
return 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(m) {
return this.multiplyMatrices(this, m);
}
/**
* 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(m) {
return this.multiplyMatrices(m, 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(a, b) {
const ae = a.elements;
const be = b.elements;
const te = this.elements;
const a11 = ae[0], a12 = ae[3], a13 = ae[6];
const a21 = ae[1], a22 = ae[4], a23 = ae[7];
const a31 = ae[2], a32 = ae[5], a33 = ae[8];
const b11 = be[0], b12 = be[3], b13 = be[6];
const b21 = be[1], b22 = be[4], b23 = be[7];
const b31 = be[2], b32 = be[5], b33 = be[8];
te[0] = a11 * b11 + a12 * b21 + a13 * b31;
te[3] = a11 * b12 + a12 * b22 + a13 * b32;
te[6] = a11 * b13 + a12 * b23 + a13 * b33;
te[1] = a21 * b11 + a22 * b21 + a23 * b31;
te[4] = a21 * b12 + a22 * b22 + a23 * b32;
te[7] = a21 * b13 + a22 * b23 + a23 * b33;
te[2] = a31 * b11 + a32 * b21 + a33 * b31;
te[5] = a31 * b12 + a32 * b22 + a33 * b32;
te[8] = a31 * b13 + a32 * b23 + a33 * b33;
return this;
}
/**
* Multiplies every component of the matrix by the given scalar.
*
* @param {number} s - The scalar.
* @return {Matrix3} A reference to this matrix.
*/
multiplyScalar(s) {
const te = this.elements;
te[0] *= s;
te[3] *= s;
te[6] *= s;
te[1] *= s;
te[4] *= s;
te[7] *= s;
te[2] *= s;
te[5] *= s;
te[8] *= s;
return this;
}
/**
* Computes and returns the determinant of this matrix.
*
* @return {number} The determinant.
*/
determinant() {
const te = this.elements;
const a = te[0], b = te[1], c = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i = te[8];
return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
}
/**
* 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 te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13;
if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
const detInv = 1 / det;
te[0] = t11 * detInv;
te[1] = (n31 * n23 - n33 * n21) * detInv;
te[2] = (n32 * n21 - n31 * n22) * detInv;
te[3] = t12 * detInv;
te[4] = (n33 * n11 - n31 * n13) * detInv;
te[5] = (n31 * n12 - n32 * n11) * detInv;
te[6] = t13 * detInv;
te[7] = (n21 * n13 - n23 * n11) * detInv;
te[8] = (n22 * n11 - n21 * n12) * detInv;
return this;
}
/**
* Transposes this matrix in place.
*
* @return {Matrix3} A reference to this matrix.
*/
transpose() {
let tmp3;
const m = this.elements;
tmp3 = m[1];
m[1] = m[3];
m[3] = tmp3;
tmp3 = m[2];
m[2] = m[6];
m[6] = tmp3;
tmp3 = m[5];
m[5] = m[7];
m[7] = tmp3;
return 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(matrix4) {
return this.setFromMatrix4(matrix4).invert().transpose();
}
/**
* Transposes this matrix into the supplied array, and returns itself unchanged.
*
* @param {Array<number>} r - An array to store the transposed matrix elements.
* @return {Matrix3} A reference to this matrix.
*/
transposeIntoArray(r) {
const m = this.elements;
r[0] = m[0];
r[1] = m[3];
r[2] = m[6];
r[3] = m[1];
r[4] = m[4];
r[5] = m[7];
r[6] = m[2];
r[7] = m[5];
r[8] = m[8];
return 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(tx, ty, sx, sy, rotation, cx, cy) {
const c = Math.cos(rotation);
const s = Math.sin(rotation);
this.set(
sx * c,
sx * s,
-sx * (c * cx + s * cy) + cx + tx,
-sy * s,
sy * c,
-sy * (-s * cx + c * cy) + cy + ty,
0,
0,
1
);
return this;
}
/**
* Scales this matrix with the given scalar values.
*
* @deprecated
* @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(sx, sy) {
warnOnce("Matrix3: .scale() is deprecated. Use .makeScale() instead.");
this.premultiply(_m3.makeScale(sx, sy));
return this;
}
/**
* Rotates this matrix by the given angle.
*
* @deprecated
* @param {number} theta - The rotation in radians.
* @return {Matrix3} A reference to this matrix.
*/
rotate(theta) {
warnOnce("Matrix3: .rotate() is deprecated. Use .makeRotation() instead.");
this.premultiply(_m3.makeRotation(-theta));
return this;
}
/**
* Translates this matrix by the given scalar values.
*
* @deprecated
* @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(tx, ty) {
warnOnce("Matrix3: .translate() is deprecated. Use .makeTranslation() instead.");
this.premultiply(_m3.makeTranslation(tx, ty));
return 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(x, y) {
if (x.isVector2) {
this.set(
1,
0,
x.x,
0,
1,
x.y,
0,
0,
1
);
} else {
this.set(
1,
0,
x,
0,
1,
y,
0,
0,
1
);
}
return this;
}
/**
* Sets this matrix as a 2D rotational transformation.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix3} A reference to this matrix.
*/
makeRotation(theta) {
const c = Math.cos(theta);
const s = Math.sin(theta);
this.set(
c,
-s,
0,
s,
c,
0,
0,
0,
1
);
return 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(x, y) {
this.set(
x,
0,
0,
0,
y,
0,
0,
0,
1
);
return 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(matrix) {
const te = this.elements;
const me = matrix.elements;
for (let i = 0; i < 9; i++) {
if (te[i] !== me[i]) return false;
}
return true;
}
/**
* Sets the elements of the matrix from the given array.
*
* @param {Array<number>} 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(array, offset = 0) {
for (let i = 0; i < 9; i++) {
this.elements[i] = array[i + offset];
}
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<number>} [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<number>} The matrix elements in column-major order.
*/
toArray(array = [], offset = 0) {
const te = this.elements;
array[offset] = te[0];
array[offset + 1] = te[1];
array[offset + 2] = te[2];
array[offset + 3] = te[3];
array[offset + 4] = te[4];
array[offset + 5] = te[5];
array[offset + 6] = te[6];
array[offset + 7] = te[7];
array[offset + 8] = te[8];
return array;
}
/**
* Returns a matrix with copied values from this instance.
*
* @return {Matrix3} A clone of this instance.
*/
clone() {
return new this.constructor().fromArray(this.elements);
}
};
_Matrix3.prototype.isMatrix3 = true;
var Matrix3 = _Matrix3;
var _m3 = /* @__PURE__ */ new Matrix3();
var LINEAR_REC709_TO_XYZ = /* @__PURE__ */ new Matrix3().set(
0.4123908,
0.3575843,
0.1804808,
0.212639,
0.7151687,
0.0721923,
0.0193308,
0.1191948,
0.9505322
);
var XYZ_TO_LINEAR_REC709 = /* @__PURE__ */ new Matrix3().set(
3.2409699,
-1.5373832,
-0.4986108,
-0.9692436,
1.8759675,
0.0415551,
0.0556301,
-0.203977,
1.0569715
);
function createColorManagement() {
const ColorManagement2 = {
enabled: true,
workingColorSpace: LinearSRGBColorSpace,
/**
* 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(color, sourceColorSpace, targetColorSpace) {
if (this.enabled === false || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) {
return color;
}
if (this.spaces[sourceColorSpace].transfer === SRGBTransfer) {
color.r = SRGBToLinear(color.r);
color.g = SRGBToLinear(color.g);
color.b = SRGBToLinear(color.b);
}
if (this.spaces[sourceColorSpace].primaries !== this.spaces[targetColorSpace].primaries) {
color.applyMatrix3(this.spaces[sourceColorSpace].toXYZ);
color.applyMatrix3(this.spaces[targetColorSpace].fromXYZ);
}
if (this.spaces[targetColorSpace].transfer === SRGBTransfer) {
color.r = LinearToSRGB(color.r);
color.g = LinearToSRGB(color.g);
color.b = LinearToSRGB(color.b);
}
return color;
},
workingToColorSpace: function(color, targetColorSpace) {
return this.convert(color, this.workingColorSpace, targetColorSpace);
},
colorSpaceToWorking: function(color, sourceColorSpace) {
return this.convert(color, sourceColorSpace, this.workingColorSpace);
},
getPrimaries: function(colorSpace) {
return this.spaces[colorSpace].primaries;
},
getTransfer: function(colorSpace) {
if (colorSpace === NoColorSpace) return LinearTransfer;
return this.spaces[colorSpace].transfer;
},
getToneMappingMode: function(colorSpace) {
return this.spaces[colorSpace].outputColorSpaceConfig.toneMappingMode || "standard";
},
getLuminanceCoefficients: function(target, colorSpace = this.workingColorSpace) {
return target.fromArray(this.spaces[colorSpace].luminanceCoefficients);
},
define: function(colorSpaces) {
Object.assign(this.spaces, colorSpaces);
},
// Internal APIs
_getMatrix: function(targetMatrix, sourceColorSpace, targetColorSpace) {
return targetMatrix.copy(this.spaces[sourceColorSpace].toXYZ).multiply(this.spaces[targetColorSpace].fromXYZ);
},
_getDrawingBufferColorSpace: function(colorSpace) {
return this.spaces[colorSpace].outputColorSpaceConfig.drawingBufferColorSpace;
},
_getUnpackColorSpace: function(colorSpace = this.workingColorSpace) {
return this.spaces[colorSpace].workingColorSpaceConfig.unpackColorSpace;
},
// Deprecated
fromWorkingColorSpace: function(color, targetColorSpace) {
warnOnce("ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().");
return ColorManagement2.workingToColorSpace(color, targetColorSpace);
},
toWorkingColorSpace: function(color, sourceColorSpace) {
warnOnce("ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().");
return ColorManagement2.colorSpaceToWorking(color, sourceColorSpace);
}
};
const REC709_PRIMARIES = [0.64, 0.33, 0.3, 0.6, 0.15, 0.06];
const REC709_LUMINANCE_COEFFICIENTS = [0.2126, 0.7152, 0.0722];
const D65 = [0.3127, 0.329];
ColorManagement2.define({
[LinearSRGBColorSpace]: {
primaries: REC709_PRIMARIES,
whitePoint: D65,
transfer: LinearTransfer,
toXYZ: LINEAR_REC709_TO_XYZ,
fromXYZ: XYZ_TO_LINEAR_REC709,
luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
workingColorSpaceConfig: { unpackColorSpace: SRGBColorSpace },
outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
},
[SRGBColorSpace]: {
primaries: REC709_PRIMARIES,
whitePoint: D65,
transfer: SRGBTransfer,
toXYZ: LINEAR_REC709_TO_XYZ,
fromXYZ: XYZ_TO_LINEAR_REC709,
luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
}
});
return ColorManagement2;
}
var ColorManagement = /* @__PURE__ */ createColorManagement();
function SRGBToLinear(c) {
return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
}
function LinearToSRGB(c) {
return c < 31308e-7 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055;
}
var _canvas;
var ImageUtils = class {
/**
* 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(image, type = "image/png") {
if (/^data:/i.test(image.src)) {
return image.src;
}
if (typeof HTMLCanvasElement === "undefined") {
return image.src;
}
let canvas;
if (image instanceof HTMLCanvasElement) {
canvas = image;
} else {
if (_canvas === void 0) _canvas = createElementNS("canvas");
_canvas.width = image.width;
_canvas.height = image.height;
const context = _canvas.getContext("2d");
if (image instanceof ImageData) {
context.putImageData(image, 0, 0);
} else {
context.drawImage(image, 0, 0, image.width, image.height);
}
canvas = _canvas;
}
return canvas.toDataURL(type);
}
/**
* 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(image) {
if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) {
const canvas = createElementNS("canvas");
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
const imageData = context.getImageData(0, 0, image.width, image.height);
const data = imageData.data;
for (let i = 0; i < data.length; i++) {
data[i] = SRGBToLinear(data[i] / 255) * 255;
}
context.putImageData(imageData, 0, 0);
return canvas;
} else if (image.data) {
const data = image.data.slice(0);
for (let i = 0; i < data.length; i++) {
if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) {
data[i] = Math.floor(SRGBToLinear(data[i] / 255) * 255);
} else {
data[i] = SRGBToLinear(data[i]);
}
}
return {
data,
width: image.width,
height: image.height
};
} else {
warn("ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.");
return image;
}
}
};
var _sourceId = 0;
var TextureSource = class {
/**
* Constructs a new texture source.
*
* @param {any} [data=null] - The data definition of a texture.
*/
constructor(data = null) {
this.isTextureSource = true;
Object.defineProperty(this, "id", { value: _sourceId++ });
this.uuid = generateUUID();
this.data = data;
this.dataReady = true;
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(target) {
const data = this.data;
if (typeof HTMLVideoElement !== "undefined" && data instanceof HTMLVideoElement) {
target.set(data.videoWidth, data.videoHeight, 0);
} else if (typeof VideoFrame !== "undefined" && data instanceof VideoFrame) {
target.set(data.displayWidth, data.displayHeight, 0);
} else if (data !== null) {
target.set(data.width, data.height, data.depth || 0);
} else {
target.set(0, 0, 0);
}
return target;
}
/**
* 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(value) {
if (value === true) 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(meta) {
const isRootObject = meta === void 0 || typeof meta === "string";
if (!isRootObject && meta.images[this.uuid] !== void 0) {
return meta.images[this.uuid];
}
const output = {
uuid: this.uuid,
url: ""
};
const data = this.data;
if (data !== null) {
let url;
if (Array.isArray(data)) {
url = [];
for (let i = 0, l = data.length; i < l; i++) {
if (data[i].isDataTexture) {
url.push(serializeImage(data[i].image));
} else {
url.push(serializeImage(data[i]));
}
}
} else {
url = serializeImage(data);
}
output.url = url;
}
if (!isRootObject) {
meta.images[this.uuid] = output;
}
return output;
}
};
function serializeImage(image) {
if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) {
return ImageUtils.getDataURL(image);
} else {
if (image.data) {
return {
data: Array.from(image.data),
width: image.width,
height: image.height,
type: image.data.constructor.name
};
} else {
warn("Texture: Unable to serialize Texture.");
return {};
}
}
}
var _textureId = 0;
var _tempVec3 = /* @__PURE__ */ new Vector3();
var Texture = class _Texture extends EventDispatcher {
/**
* 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(image = _Texture.DEFAULT_IMAGE, mapping = _Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = _Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace) {
super();
this.isTexture = true;
Object.defineProperty(this, "id", { value: _textureId++ });
this.uuid = generateUUID();
this.name = "";
this.source = new TextureSource(image);
this.mipmaps = [];
this.mapping = mapping;
this.channel = 0;
this.wrapS = wrapS;
this.wrapT = wrapT;
this.magFilter = magFilter;
this.minFilter = minFilter;
this.anisotropy = anisotropy;
this.format = format;
this.internalFormat = null;
this.type = type;
this.offset = new Vector2(0, 0);
this.repeat = new Vector2(1, 1);
this.center = new Vector2(0, 0);
this.rotation = 0;
this.matrixAutoUpdate = true;
this.matrix = new Matrix3();
this.generateMipmaps = true;
this.premultiplyAlpha = false;
this.flipY = true;
this.unpackAlignment = 4;
this.colorSpace = colorSpace;
this.userData = {};
this.updateRanges = [];
this.version = 0;
this.onUpdate = null;
this.renderTarget = null;
this.isRenderTargetTexture = false;
this.isArrayTexture = image && image.depth && image.depth > 1 ? true : false;
this.pmremVersion = 0;
this.normalized = false;
}
/**
* The width of the texture in pixels.
*/
get width() {
return this.source.getSize(_tempVec3).x;
}
/**
* The height of the texture in pixels.
*/
get height() {
return this.source.getSize(_tempVec3).y;
}
/**
* The depth of the texture in pixels.
*/
get depth() {
return this.source.getSize(_tempVec3).z;
}
/**
* The image object holding the texture data.
*
* @type {?Object}
*/
get image() {
return this.source.data;
}
set image(value) {
this.source.data = value;
}
/**
* Updates the texture transformation matrix 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(start, count) {
this.updateRanges.push({ start, count });
}
/**
* 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(source) {
this.name = source.name;
this.source = source.source;
this.mipmaps = source.mipmaps.slice(0);
this.mapping = source.mapping;
this.channel = source.channel;
this.wrapS = source.wrapS;
this.wrapT = source.wrapT;
this.magFilter = source.magFilter;
this.minFilter = source.minFilter;
this.anisotropy = source.anisotropy;
this.format = source.format;
this.internalFormat = source.internalFormat;
this.type = source.type;
this.normalized = source.normalized;
this.offset.copy(source.offset);
this.repeat.copy(source.repeat);
this.center.copy(source.center);
this.rotation = source.rotation;
this.matrixAutoUpdate = source.matrixAutoUpdate;
this.matrix.copy(source.matrix);
this.generateMipmaps = source.generateMipmaps;
this.premultiplyAlpha = source.premultiplyAlpha;
this.flipY = source.flipY;
this.unpackAlignment = source.unpackAlignment;
this.colorSpace = source.colorSpace;
this.renderTarget = source.renderTarget;
this.isRenderTargetTexture = source.isRenderTargetTexture;
this.isArrayTexture = source.isArrayTexture;
this.userData = JSON.parse(JSON.stringify(source.userData));
this.needsUpdate = true;
return this;
}
/**
* Sets this texture's properties based on `values`.
* @param {Object} values - A container with texture parameters.
*/
setValues(values) {
for (const key in values) {
const newValue = values[key];
if (newValue === void 0) {
warn(`Texture.setValues(): parameter '${key}' has value of undefined.`);
continue;
}
const currentValue = this[key];
if (currentValue === void 0) {
warn(`Texture.setValues(): property '${key}' does not exist.`);
continue;
}
if (currentValue && newValue && (currentValue.isVector2 && newValue.isVector2)) {
currentValue.copy(newValue);
} else if (currentValue && newValue && (currentValue.isVector3 && newValue.isVector3)) {
currentValue.copy(newValue);
} else if (currentValue && newValue && (currentValue.isMatrix3 && newValue.isMatrix3)) {
currentValue.copy(newValue);
} else {
this[key] = newValue;
}
}
}
/**
* 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(meta) {
const isRootObject = meta === void 0 || typeof meta === "string";
if (!isRootObject && meta.textures[this.uuid] !== void 0) {
return meta.textures[this.uuid];
}
const output = {
metadata: {
version: 4.7,
type: "Texture",
generator: "Texture.toJSON"
},
uuid: this.uuid,
name: this.name,
image: this.source.toJSON(meta).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,
normalized: this.normalized,
colorSpace: this.colorSpace,
minFilter: this.minFilter,
magFilter: this.magFilter,
anisotropy: this.anisotropy,
flipY: this.flipY,
generateMipmaps: this.generateMipmaps,
premultiplyAlpha: this.premultiplyAlpha,
unpackAlignment: this.unpackAlignment
};
if (Object.keys(this.userData).length > 0) output.userData = this.userData;
if (!isRootObject) {
meta.textures[this.uuid] = output;
}
return output;
}
/**
* 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(uv) {
if (this.mapping !== UVMapping) return uv;
uv.applyMatrix3(this.matrix);
if (uv.x < 0 || uv.x > 1) {
switch (this.wrapS) {
case RepeatWrapping:
uv.x = uv.x - Math.floor(uv.x);
break;
case ClampToEdgeWrapping:
uv.x = uv.x < 0 ? 0 : 1;
break;
case MirroredRepeatWrapping:
if (Math.abs(Math.floor(uv.x) % 2) === 1) {
uv.x = Math.ceil(uv.x) - uv.x;
} else {
uv.x = uv.x - Math.floor(uv.x);
}
break;
}
}
if (uv.y < 0 || uv.y > 1) {
switch (this.wrapT) {
case RepeatWrapping:
uv.y = uv.y - Math.floor(uv.y);
break;
case ClampToEdgeWrapping:
uv.y = uv.y < 0 ? 0 : 1;
break;
case MirroredRepeatWrapping:
if (Math.abs(Math.floor(uv.y) % 2) === 1) {
uv.y = Math.ceil(uv.y) - uv.y;
} else {
uv.y = uv.y - Math.floor(uv.y);
}
break;
}
}
if (this.flipY) {
uv.y = 1 - uv.y;
}
return uv;
}
/**
* 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(value) {
if (value === true) {
this.version++;
this.source.needsUpdate = true;
}
}
/**
* Setting this property to `true` indicates the engine the PMREM
* must be regenerated.
*
* @type {boolean}
* @default false
* @param {boolean} value
*/
set needsPMREMUpdate(value) {
if (value === true) {
this.pmremVersion++;
}
}
};
Texture.DEFAULT_IMAGE = null;
Texture.DEFAULT_MAPPING = UVMapping;
Texture.DEFAULT_ANISOTROPY = 1;
var _Vector4 = class _Vector4 {
/**
* 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(x = 0, y = 0, z = 0, w = 1) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
/**
* Alias for {@link Vector4#z}.
*
* @type {number}
*/
get width() {
return this.z;
}
set width(value) {
this.z = value;
}
/**
* Alias for {@link Vector4#w}.
*
* @type {number}
*/
get height() {
return this.w;
}
set height(value) {
this.w = value;
}
/**
* 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(x, y, z, w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return 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(scalar) {
this.x = scalar;
this.y = scalar;
this.z = scalar;
this.w = scalar;
return 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(x) {
this.x = x;
return 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(y) {
this.y = y;
return 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(z) {
this.z = z;
return 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(w) {
this.w = w;
return 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(index, value) {
switch (index) {
case 0:
this.x = value;
break;
case 1:
this.y = value;
break;
case 2:
this.z = value;
break;
case 3:
this.w = value;
break;
default:
throw new Error("THREE.Vector4: index is out of range: " + index);
}
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(index) {
switch (index) {
case 0:
return this.x;
case 1:
return this.y;
case 2:
return this.z;
case 3:
return this.w;
default:
throw new Error("THREE.Vector4: index is out of range: " + index);
}
}
/**
* 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(v) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
this.w = v.w !== void 0 ? v.w : 1;
return this;
}
/**
* Adds the given vector to this instance.
*
* @param {Vector4} v - The vector to add.
* @return {Vector4} A reference to this vector.
*/
add(v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
this.w += v.w;
return 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(s) {
this.x += s;
this.y += s;
this.z += s;
this.w += s;
return 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(a, b) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
this.w = a.w + b.w;
return 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(v, s) {
this.x += v.x * s;
this.y += v.y * s;
this.z += v.z * s;
this.w += v.w * s;
return this;
}
/**
* Subtracts the given vector from this instance.
*
* @param {Vector4} v - The vector to subtract.
* @return {Vector4} A reference to this vector.
*/
sub(v) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
this.w -= v.w;
return 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(s) {
this.x -= s;
this.y -= s;
this.z -= s;
this.w -= s;
return 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(a, b) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
this.w = a.w - b.w;
return this;
}
/**
* Multiplies the given vector with this instance.
*
* @param {Vector4} v - The vector to multiply.
* @return {Vector4} A reference to this vector.
*/
multiply(v) {
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
this.w *= v.w;
return 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(scalar) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
this.w *= scalar;
return this;
}
/**
* Multiplies this vector with the given 4x4 matrix.
*
* @param {Matrix4} m - The 4x4 matrix.
* @return {Vector4} A reference to this vector.
*/
applyMatrix4(m) {
const x = this.x, y = this.y, z = this.z, w = this.w;
const e = m.elements;
this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w;
this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w;
this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w;
this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w;
return this;
}
/**
* Divides this instance by the given vector.
*
* @param {Vector4} v - The vector to divide.
* @return {Vector4} A reference to this vector.
*/
divide(v) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
this.w /= v.w;
return this;
}
/**
* Divides this vector by the given scalar.
*
* @param {number} scalar - The scalar to divide.
* @return {Vector4} A reference to this vector.
*/
divideScalar(scalar) {
return this.multiplyScalar(1 / scalar);
}
/**
* 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(q) {
this.w = 2 * Math.acos(q.w);
const s = Math.sqrt(1 - q.w * q.w);
if (s < 1e-4) {
this.x = 1;
this.y = 0;
this.z = 0;
} else {
this.x = q.x / s;
this.y = q.y / s;
this.z = q.z / s;
}
return 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(m) {
let angle, x, y, z;
const epsilon = 0.01, epsilon2 = 0.1, te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10];
if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) {
if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) {
this.set(1, 0, 0, 0);
return this;
}
angle = Math.PI;
const xx = (m11 + 1) / 2;
const yy = (m22 + 1) / 2;
const zz = (m33 + 1) / 2;
const xy = (m12 + m21) / 4;
const xz = (m13 + m31) / 4;
const yz = (m23 + m32) / 4;
if (xx > yy && xx > zz) {
if (xx < epsilon) {
x = 0;
y = 0.707106781;
z = 0.707106781;
} else {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
}
} else if (yy > zz) {
if (yy < epsilon) {
x = 0.707106781;
y = 0;
z = 0.707106781;
} else {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
}
} else {
if (zz < epsilon) {
x = 0.707106781;
y = 0.707106781;
z = 0;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
}
this.set(x, y, z, angle);
return this;
}
let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12));
if (Math.abs(s) < 1e-3) s = 1;
this.x = (m32 - m23) / s;
this.y = (m13 - m31) / s;
this.z = (m21 - m12) / s;
this.w = Math.acos((m11 + m22 + m33 - 1) / 2);
return 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(m) {
const e = m.elements;
this.x = e[12];
this.y = e[13];
this.z = e[14];
this.w = e[15];
return 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(v) {
this.x = Math.min(this.x, v.x);
this.y = Math.min(this.y, v.y);
this.z = Math.min(this.z, v.z);
this.w = Math.min(this.w, v.w);
return 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(v) {
this.x = Math.max(this.x, v.x);
this.y = Math.max(this.y, v.y);
this.z = Math.max(this.z, v.z);
this.w = Math.max(this.w, v.w);
return 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(min, max) {
this.x = clamp(this.x, min.x, max.x);
this.y = clamp(this.y, min.y, max.y);
this.z = clamp(this.z, min.z, max.z);
this.w = clamp(this.w, min.w, max.w);
return 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(minVal, maxVal) {
this.x = clamp(this.x, minVal, maxVal);
this.y = clamp(this.y, minVal, maxVal);
this.z = clamp(this.z, minVal, maxVal);
this.w = clamp(this.w, minVal, maxVal);
return 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(min, max) {
const length = this.length();
return this.divideScalar(length || 1).multiplyScalar(clamp(length, min, max));
}
/**
* The components of this vector are rounded down to the nearest integer value.
*
* @return {Vector4} A reference to this vector.
*/
floor() {
this.x = Math.floor(this.x);
this.y = Math.floor(this.y);
this.z = Math.floor(this.z);
this.w = Math.floor(this.w);
return this;
}
/**
* The components of this vector are rounded up to the nearest integer value.
*
* @return {Vector4} A reference to this vector.
*/
ceil() {
this.x = Math.ceil(this.x);
this.y = Math.ceil(this.y);
this.z = Math.ceil(this.z);
this.w = Math.ceil(this.w);
return this;
}
/**
* The components of this vector are rounded to the nearest integer value
*
* @return {Vector4} A reference to this vector.
*/
round() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
this.z = Math.round(this.z);
this.w = Math.round(this.w);
return 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() {
this.x = Math.trunc(this.x);
this.y = Math.trunc(this.y);
this.z = Math.trunc(this.z);
this.w = Math.trunc(this.w);
return this;
}
/**
* Inverts this vector - i.e. sets x = -x, y = -y, z = -z, w = -w.
*
* @return {Vector4} A reference to this vector.
*/
negate() {
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
this.w = -this.w;
return 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(v) {
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.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 slightl.........完整代码请登录后点击上方下载按钮下载查看















网友评论0