three实现三维末日城市流星雨驾车逃离游戏代码
代码语言:html
所属分类:其他
代码由minimax-m3.1-flash ai生成,可能有错误,仅供参考:点击查看提示词
代码描述:三维末日城市流星雨驾车逃离游戏
代码标签: three 三维 末日 城市 流星雨 驾车 逃离 游戏 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>AEGIS · 穹顶防御阵列 — 城市能量防护盾</title>
<style>
:root{
--ok:#54ffc8;
--warn:#ffcb4d;
--crit:#ff4d6a;
--cyan:#5fe8ff;
--line:rgba(95,232,255,.28);
--glass:rgba(6,14,24,.42);
--mono:"SF Mono",ui-monospace,Menlo,Consolas,"Roboto Mono","DejaVu Sans Mono",monospace;
--sans:"PingFang SC","Hiragino Sans GB","Microsoft YaHei",system-ui,-apple-system,"Segoe UI",sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:#02040a;overflow:hidden;font-family:var(--mono)}
canvas{display:block;width:100%;height:100%;cursor:crosshair}
body{color:#cfe9f5;-webkit-font-smoothing:antialiased}
/* ---------------------------------------------------------- HUD frame */
#hud{position:fixed;inset:0;pointer-events:none;z-index:10;
opacity:1;transition:opacity .45s ease}
body.hud-off #hud{opacity:0}
.corner{position:absolute;width:46px;height:46px;border:1px solid var(--line);opacity:.85}
.c-tl{top:16px;left:16px;border-right:0;border-bottom:0}
.c-tr{top:16px;right:16px;border-left:0;border-bottom:0}
.c-bl{bottom:16px;left:16px;border-right:0;border-top:0}
.c-br{bottom:16px;right:16px;border-left:0;border-top:0}
/* ------------------------------------------------------------- header */
.brand{position:absolute;top:26px;left:30px;display:flex;gap:14px;align-items:flex-start}
.brand .mark{width:34px;height:34px;border:1px solid var(--cyan);position:relative;
box-shadow:0 0 18px rgba(95,232,255,.35) inset,0 0 12px rgba(95,232,255,.18);
display:grid;place-items:center;color:var(--cyan);font-size:15px;letter-spacing:0}
.brand .mark::before{content:"";position:absolute;inset:5px;border:1px solid rgba(95,232,255,.35);
animation:spin 9s linear infinite;border-radius:50%}
@keyframes spin{to{transform:rotate(360deg)}}
.brand h1{margin:0;font-size:17px;letter-spacing:.42em;font-weight:600;color:#e8fbff;
text-shadow:0 0 18px rgba(95,232,255,.55)}
.brand p{margin:5px 0 0;font-size:10.5px;letter-spacing:.26em;color:rgba(160,210,230,.72)}
.brand .rule{width:190px;height:1px;margin-top:9px;
background:linear-gradient(90deg,var(--cyan),transparent)}
/* -------------------------------------------------------- right status */
.status{position:absolute;top:28px;right:30px;text-align:right}
.status .lbl{font-size:9.5px;letter-spacing:.3em;color:rgba(150,195,215,.6)}
.status .alert{display:inline-flex;align-items:center;gap:8px;margin-top:6px;
font-size:13px;letter-spacing:.22em}
.status .dot{width:7px;height:7px;border-radius:50%;background:var(--ok);
box-shadow:0 0 10px currentColor;color:var(--ok);animation:blink 1.4s infinite steps(1)}
.status .dot.warn{background:var(--warn);color:var(--warn)}
.status .dot.crit{background:var(--crit);color:var(--crit);animation-duration:.6s}
.status .meta{margin-top:10px;font-size:10px;letter-spacing:.18em;color:rgba(140,185,205,.55)}
/* -------------------------------------------------------- left panel */
.panel{position:absolute;left:30px;top:132px;width:286px;
background:linear-gradient(180deg,rgba(8,16,26,.52),rgba(6,12,20,.30));
border:1px solid rgba(95,232,255,.16);
border-left:2px solid rgba(95,232,255,.45);
backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
padding:16px 16px 14px}
.panel .hd{font-size:9.5px;letter-spacing:.32em;color:var(--cyan);opacity:.85;
border-bottom:1px solid rgba(95,232,255,.16);padding-bottom:9px;margin-bottom:12px;
display:flex;justify-content:space-between}
.row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin:11px 0 5px}
.row span{font-size:9.5px;letter-spacing:.14em;color:rgba(160,205,225,.72);line-height:1.5}
.row b{font-size:13px;font-weight:600;letter-spacing:.04em;color:#e6f8ff;white-space:nowrap;flex:none}
.bar{height:4px;background:rgba(255,255,255,.07);overflow:hidden;position:relative}
.bar i{display:block;height:100%;width:100%;background:var(--cyan);
box-shadow:0 0 10px currentColor;transition:width .25s linear}
.bar i::after{content:"";position:absolute;inset:0;
background:repeating-linear-gradient(90deg,transparent 0 9px,rgba(0,0,0,.45) 9px 11px)}
.mini{display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap;font-size:9px;letter-spacing:.12em;
color:rgba(140,185,205,.55);margin-top:12px;padding-top:10px;
border-top:1px solid rgba(95,232,255,.12)}
.val.ok{color:var(--ok)}.val.warn{color:var(--warn)}.val.crit{color:var(--crit)}
@keyframes blink{0%,60%{opacity:1}61%,100%{opacity:.25}}
/* ------------------------------------------------------- bottom right */
.keys{position:absolute;right:30px;bottom:26px;text-align:right;font-size:10px;
letter-spacing:.16em;color:rgba(150,195,215,.6);line-height:1.9}
.keys kbd{display:inline-block;min-width:20px;padding:1px 6px;margin-left:8px;
border:1px solid rgba(95,232,255,.28);color:var(--cyan);font-family:var(--mono);font-size:9.5px}
.btns{margin-top:10px;display:flex;gap:8px;justify-content:flex-end;pointer-events:auto}
.btn{background:rgba(8,18,28,.55);border:1px solid rgba(95,232,255,.3);color:var(--cyan);
font-family:var(--mono);font-size:9.5px;letter-spacing:.2em;padding:7px 12px;cursor:pointer;
transition:.18s;text-transform:uppercase}
.btn:hover{background:rgba(95,232,255,.16);box-shadow:0 0 16px rgba(95,232,255,.28)}
.btn.on{background:rgba(95,232,255,.22)}
/* --------------------------------------------------------------- log */
.logwrap{position:absolute;left:30px;bottom:26px;width:430px}
.logwrap .hd{font-size:9px;letter-spacing:.3em;color:rgba(95,232,255,.7);margin-bottom:7px}
#log{display:flex;flex-direction:column;gap:3px}
.log-row{font-size:10px;letter-spacing:.08em;color:rgba(170,215,235,.78);
opacity:0;transform:translateX(-8px);transition:opacity .3s,transform .3s;
display:flex;gap:10px;text-shadow:0 0 10px rgba(0,0,0,.9)}
.log-row.in{opacity:1;transform:none}
.log-row.warn{color:var(--warn)}
.log-row.crit{color:var(--crit)}
.log-row.ok{color:var(--ok)}
.log-ts{color:rgba(120,165,190,.55)}
/* ------------------------------------------------------------ reticle */
.reticle{position:absolute;left:50%;top:50%;width:120px;height:120px;
transform:translate(-50%,-50%);opacity:.28}
.reticle::before,.reticle::after{content:"";position:absolute;background:var(--cyan)}
.reticle::before{left:50%;top:0;width:1px;height:12px;transform:translateX(-50%);
box-shadow:0 108px 0 var(--cyan)}
.reticle::after{top:50%;left:0;height:1px;width:12px;transform:translateY(-50%);
box-shadow:108px 0 0 var(--cyan)}
/* ---------------------------------------------------------- overlays */
#scan{position:fixed;inset:0;pointer-events:none;z-index:11;
background:repeating-linear-gradient(0deg,rgba(0,0,0,.16) 0 1px,transparent 1px 3px);
mix-blend-mode:multiply;opacity:.55}
#vig{position:fixed;inset:0;pointer-events:none;z-index:12;
background:radial-gradient(ellipse at 50% 48%,transparent 40%,rgba(0,0,0,.55) 100%)}
#flash{position:fixed;inset:0;pointer-events:none;z-index:13;background:#dff4ff;opacity:0;
mix-blend-mode:screen;transition:opacity .06s linear}
/* -------------------------------------------------------------- intro */
#intro{position:fixed;inset:0;z-index:30;background:#02040a;display:grid;place-items:center;
transition:opacity 1.1s ease,letter-spacing 1.6s ease}
#intro.gone{opacity:0;pointer-events:none}
#intro .in{text-align:center}
#intro .k{font-size:10px;letter-spacing:.6em;color:var(--cyan);opacity:.8}
#intro h2{margin:16px 0 0;font-size:40px;letter-spacing:.34em;font-weight:300;color:#eafaff;
text-shadow:0 0 40px rgba(95,232,255,.45)}
#intro .s{margin-top:12px;font-size:11px;letter-spacing:.28em;color:rgba(150,195,215,.6)}
#intro .bar{margin:26px auto 0;width:260px;height:2px}
#intro .bar i{width:0;animation:load 2.4s ease forwards}
@keyframes load{to{width:100%}}
@media (max-width:1100px){
.panel{width:236px;top:118px;padding:12px 12px 10px}
.panel .hd{font-size:8.5px;letter-spacing:.22em}
.row span{font-size:8.5px;letter-spacing:.1em}
.row b{font-size:11px}
.mini{font-size:8px;letter-spacing:.08em}
.logwrap{width:330px}
.brand h1{font-size:13px;letter-spacing:.26em}
.brand p{font-size:9px;letter-spacing:.18em}
.keys{font-size:9px}
}
@media (max-width:760px){
.panel{width:200px}
.logwrap{width:250px}
.status .meta{font-size:8.5px}
}
</style>
</head>
<body>
<canvas id="scene"></canvas>
<div id="hud">
<div class="corner c-tl"></div><div class="corner c-tr"></div>
<div class="corner c-bl"></div><div class="corner c-br"></div>
<div class="brand">
<div class="mark">◈</div>
<div>
<h1>AEGIS DEFENSE GRID</h1>
<p>穹顶防御阵列 · SECTOR 07 / NEO-KOWLOON</p>
<div class="rule"></div>
</div>
</div>
<div class="status">
<div class="lbl">SHIELD STATUS</div>
<div class="alert"><span class="dot" id="alert-dot"></span><span class="val ok" id="v-alert">NOMINAL</span></div>
<div class="meta">LOCAL <span id="v-clock">--:--:--</span> · CAM <span id="v-mode">CINEMATIC</span></div>
</div>
<section class="panel">
<div class="hd"><span>REACTOR TELEMETRY</span><span>在线</span></div>
<div class="row"><span>SHIELD INTEGRITY 护盾完整度</span><b id="v-integrity">100.0%</b></div>
<div class="bar"><i id="bar-integrity" style="background:var(--ok)"></i></div>
<div class="row"><span>FIELD OUTPUT 场输出功率</span><b id="v-power">12.40 TW/s</b></div>
<div class="bar"><i id="bar-power" style="width:60%"></i></div>
<div class="mini">
<span>EMITTERS <b id="v-emitters">128 / 128</b></span>
<span>STRIKES <b id="v-hits">0</b></span>
<span>FPS <b id="v-fps">60</b></span>
</div>
</section>
<div class="reticle"></div>
<div class="logwrap">
<div class="hd">EVENT STREAM · 事件流</div>
<div id="log"></div>
</div>
<div class="keys">
<div>拖拽 DRAG 旋转视角 · 滚轮 WHEEL 推拉</div>
<div>点击护盾 CLICK SHIELD 触发冲击 <kbd>SPACE</kbd></div>
<div>镜头预设 <kbd>1</kbd><kbd>2</kbd><kbd>3</kbd><kbd>4</kbd> 隐藏 HUD <kbd>H</kbd> 重置 <kbd>R</kbd></div>
<div class="btns">
<button class="btn" id="btn-strike">⚡ 触发冲击</button>
<button class="btn" id="btn-view">◎ 切换镜头</button>
<button class="btn" id="btn-sound">♪ 音频 OFF</button>
</div>
</div>
</div>
<div id="scan"></div>
<div id="vig"></div>
<div id="flash"></div>
<div id="intro">
<div class="in">
<div class="k">CITY DEFENSE INITIATIVE</div>
<h2>AEGIS</h2>
<div class="s">穹 顶 防 御 阵 列 · 能 量 护 盾</div>
<div class="bar"><i></i></div>
</div>
</div>
<script>
/*! AEGIS DEFENSE GRID — bundled three.js r180 + scene runtime (self-contained, no network needed) */
(() => {
// node_modules/three/build/three.core.js
var REVISION = "180";
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 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 ZeroCurvatureEnding = 2400;
var ZeroSlopeEnding = 2401;
var WrapAroundEnding = 2402;
var BasicDepthPacking = 3200;
var RGBADepthPacking = 3201;
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 DynamicDrawUsage = 35048;
var GLSL3 = "300 es";
var WebGLCoordinateSystem = 2e3;
var WebGPUCoordinateSystem = 2001;
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:
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("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:
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("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) {
_Vector2.prototype.isVector2 = true;
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("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("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;
}
};
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 in the range `[0,1]`.
* @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];
const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3];
if (t === 0) {
dst[dstOffset + 0] = x0;
dst[dstOffset + 1] = y0;
dst[dstOffset + 2] = z0;
dst[dstOffset + 3] = w0;
return;
}
if (t === 1) {
dst[dstOffset + 0] = x1;
dst[dstOffset + 1] = y1;
dst[dstOffset + 2] = z1;
dst[dstOffset + 3] = w1;
return;
}
if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
let s = 1 - t;
const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos;
if (sqrSin > Number.EPSILON) {
const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir);
s = Math.sin(s * len) / sin;
t = Math.sin(t * len) / sin;
}
const tDir = t * dir;
x0 = x0 * s + x1 * tDir;
y0 = y0 * s + y1 * tDir;
z0 = z0 * s + z1 * tDir;
w0 = w0 * s + w1 * tDir;
if (s === 1 - 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:
console.warn("THREE.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 quaternions.
*
* @param {Quaternion} qb - The target quaternion.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {Quaternion} A reference to this quaternion.
*/
slerp(qb, t) {
if (t === 0) return this;
if (t === 1) return this.copy(qb);
const x = this._x, y = this._y, z = this._z, w = this._w;
let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
if (cosHalfTheta < 0) {
this._w = -qb._w;
this._x = -qb._x;
this._y = -qb._y;
this._z = -qb._z;
cosHalfTheta = -cosHalfTheta;
} else {
this.copy(qb);
}
if (cosHalfTheta >= 1) {
this._w = w;
this._x = x;
this._y = y;
this._z = z;
return this;
}
const sqrSinHalfTheta = 1 - cosHalfTheta * cosHalfTheta;
if (sqrSinHalfTheta <= Number.EPSILON) {
const s = 1 - t;
this._w = s * w + t * this._w;
this._x = s * x + t * this._x;
this._y = s * y + t * this._y;
this._z = s * z + t * this._z;
this.normalize();
return this;
}
const sinHalfTheta = Math.sqrt(sqrSinHalfTheta);
const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);
const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
this._w = w * ratioA + this._w * ratioB;
this._x = x * ratioA + this._x * ratioB;
this._y = y * ratioA + this._y * ratioB;
this._z = z * ratioA + this._z * ratioB;
this._onChangeCallback();
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) {
_Vector3.prototype.isVector3 = true;
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("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("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$4.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$4.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 the direction of this vector by a matrix (the upper left 3 x 3
* subset of the given 4x4 matrix and then normalizes the result.
*
* @param {Matrix4} m - The matrix.
* @return {Vector3} A reference to this vector.
*/
transformDirection(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;
}
// TODO lengthSquared?
/**
* Computes the square of the Euclidean length (straight-line length) from
* (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should
* compare the length squared instead as it is slightly more efficient to calculate.
*
* @return {number} The square length of this vector.
*/
lengthSq() {
return this.x * this.x + this.y * this.y + this.z * this.z;
}
/**
* Computes the Euclidean length (straight-line length) from (0, 0, 0) to (x, y, z).
*
* @return {number} The length of this vector.
*/
length() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
/**
* Computes the Manhattan length of this vector.
*
* @return {number} The length of this vector.
*/
manhattanLength() {
return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
}
/**
* Converts this vector to a unit vector - that is, sets it equal to a vector
* with the same direction as this one, but with a vector length of `1`.
*
* @return {Vector3} A reference to this vector.
*/
normalize() {
return this.divideScalar(this.length() || 1);
}
/**
* Sets this vector to a vector with the same direction as this one, but
* with the specified length.
*
* @param {number} length - The new length of this vector.
* @return {Vector3} A reference to this vector.
*/
setLength(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;
}
};
var _vector$c = /* @__PURE__ */ new Vector3();
var _quaternion$4 = /* @__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) {
_Matrix3.prototype.isMatrix3 = true;
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]{@link 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 tmp;
const m = this.elements;
tmp = m[1];
m[1] = m[3];
m[3] = tmp;
tmp = m[2];
m[2] = m[6];
m[6] = tmp;
tmp = m[5];
m[5] = m[7];
m[7] = tmp;
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.
*
* @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) {
this.premultiply(_m3.makeScale(sx, sy));
return this;
}
/**
* Rotates this matrix by the given angle.
*
* @param {number} theta - The rotation in radians.
* @return {Matrix3} A reference to this matrix.
*/
rotate(theta) {
this.premultiply(_m3.makeRotation(-theta));
return this;
}
/**
* Translates this matrix by the given scalar values.
*
* @param {number} tx - The amount to translate in the X axis.
* @param {number} ty - The amount to translate in the Y axis.
* @return {Matrix3} A reference to this matrix.
*/
translate(tx, ty) {
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);
}
};
var _m3 = /* @__PURE__ */ new Matrix3();
function arrayNeedsUint32(array) {
for (let i = array.length - 1; i >= 0; --i) {
if (array[i] >= 65535) return true;
}
return false;
}
function createElementNS(name) {
return document.createElementNS("http://www.w3.org/1999/xhtml", name);
}
function createCanvasElement() {
const canvas2 = createElementNS("canvas");
canvas2.style.display = "block";
return canvas2;
}
var _cache = {};
function warnOnce(message) {
if (message in _cache) return;
_cache[message] = true;
console.warn(message);
}
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 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("THREE.ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().");
return ColorManagement2.workingToColorSpace(color, targetColorSpace);
},
toWorkingColorSpace: function(color, sourceColorSpace) {
warnOnce("THREE.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 canvas2;
if (image instanceof HTMLCanvasElement) {
canvas2 = 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);
}
canvas2 = _canvas;
}
return canvas2.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 canvas2 = createElementNS("canvas");
canvas2.width = image.width;
canvas2.height = image.height;
const context = canvas2.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 canvas2;
} 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 {
console.warn("THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.");
return image;
}
}
};
var _sourceId = 0;
var Source = class {
/**
* Constructs a new video texture.
*
* @param {any} [data=null] - The data definition of a texture.
*/
constructor(data = null) {
this.isSource = 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 (data instanceof VideoFrame) {
target.set(data.displayHeight, data.displayWidth, 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 {
console.warn("THREE.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 Source(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;
}
/**
* 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 = null) {
this.source.data = value;
}
/**
* Updates the texture transformation matrix from the from the properties {@link Texture#offset},
* {@link Texture#repeat}, {@link Texture#rotation}, and {@link Texture#center}.
*/
updateMatrix() {
this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y);
}
/**
* Adds a range of data in the data texture to be updated on the GPU.
*
* @param {number} start - Position at which to start update.
* @param {number} count - The number of components to update.
*/
addUpdateRange(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.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) {
console.warn(`THREE.Texture.setValues(): parameter '${key}' has value of undefined.`);
continue;
}
const currentValue = this[key];
if (currentValue === void 0) {
console.warn(`THREE.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,
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) {
_Vector4.prototype.isVector4 = true;
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}.........完整代码请登录后点击上方下载按钮下载查看















网友评论0