You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
35142 lines
1.3 MiB
35142 lines
1.3 MiB
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
var __commonJS = (cb2, mod) => function __require() {
|
|
return mod || (0, cb2[Object.keys(cb2)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
};
|
|
var __export = (target, all) => {
|
|
__markAsModule(target);
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __reExport = (target, module2, desc) => {
|
|
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
for (let key of __getOwnPropNames(module2))
|
|
if (!__hasOwnProp.call(target, key) && key !== "default")
|
|
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
}
|
|
return target;
|
|
};
|
|
var __toModule = (module2) => {
|
|
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
};
|
|
|
|
// node_modules/lex/lexer.js
|
|
var require_lexer = __commonJS({
|
|
"node_modules/lex/lexer.js"(exports, module2) {
|
|
if (typeof module2 === "object" && typeof module2.exports === "object")
|
|
module2.exports = Lexer;
|
|
Lexer.defunct = function(chr) {
|
|
throw new Error("Unexpected character at index " + (this.index - 1) + ": " + chr);
|
|
};
|
|
function Lexer(defunct) {
|
|
if (typeof defunct !== "function")
|
|
defunct = Lexer.defunct;
|
|
var tokens = [];
|
|
var rules = [];
|
|
var remove = 0;
|
|
this.state = 0;
|
|
this.index = 0;
|
|
this.input = "";
|
|
this.addRule = function(pattern, action, start) {
|
|
var global2 = pattern.global;
|
|
if (!global2) {
|
|
var flags = "g";
|
|
if (pattern.multiline)
|
|
flags += "m";
|
|
if (pattern.ignoreCase)
|
|
flags += "i";
|
|
pattern = new RegExp(pattern.source, flags);
|
|
}
|
|
if (Object.prototype.toString.call(start) !== "[object Array]")
|
|
start = [0];
|
|
rules.push({
|
|
pattern,
|
|
global: global2,
|
|
action,
|
|
start
|
|
});
|
|
return this;
|
|
};
|
|
this.setInput = function(input) {
|
|
remove = 0;
|
|
this.state = 0;
|
|
this.index = 0;
|
|
tokens.length = 0;
|
|
this.input = input;
|
|
return this;
|
|
};
|
|
this.lex = function() {
|
|
if (tokens.length)
|
|
return tokens.shift();
|
|
this.reject = true;
|
|
while (this.index <= this.input.length) {
|
|
var matches = scan.call(this).splice(remove);
|
|
var index = this.index;
|
|
while (matches.length) {
|
|
if (this.reject) {
|
|
var match = matches.shift();
|
|
var result = match.result;
|
|
var length = match.length;
|
|
this.index += length;
|
|
this.reject = false;
|
|
remove++;
|
|
var token = match.action.apply(this, result);
|
|
if (this.reject)
|
|
this.index = result.index;
|
|
else if (typeof token !== "undefined") {
|
|
switch (Object.prototype.toString.call(token)) {
|
|
case "[object Array]":
|
|
tokens = token.slice(1);
|
|
token = token[0];
|
|
default:
|
|
if (length)
|
|
remove = 0;
|
|
return token;
|
|
}
|
|
}
|
|
} else
|
|
break;
|
|
}
|
|
var input = this.input;
|
|
if (index < input.length) {
|
|
if (this.reject) {
|
|
remove = 0;
|
|
var token = defunct.call(this, input.charAt(this.index++));
|
|
if (typeof token !== "undefined") {
|
|
if (Object.prototype.toString.call(token) === "[object Array]") {
|
|
tokens = token.slice(1);
|
|
return token[0];
|
|
} else
|
|
return token;
|
|
}
|
|
} else {
|
|
if (this.index !== index)
|
|
remove = 0;
|
|
this.reject = true;
|
|
}
|
|
} else if (matches.length)
|
|
this.reject = true;
|
|
else
|
|
break;
|
|
}
|
|
};
|
|
function scan() {
|
|
var matches = [];
|
|
var index = 0;
|
|
var state = this.state;
|
|
var lastIndex = this.index;
|
|
var input = this.input;
|
|
for (var i = 0, length = rules.length; i < length; i++) {
|
|
var rule = rules[i];
|
|
var start = rule.start;
|
|
var states = start.length;
|
|
if (!states || start.indexOf(state) >= 0 || state % 2 && states === 1 && !start[0]) {
|
|
var pattern = rule.pattern;
|
|
pattern.lastIndex = lastIndex;
|
|
var result = pattern.exec(input);
|
|
if (result && result.index === lastIndex) {
|
|
var j = matches.push({
|
|
result,
|
|
action: rule.action,
|
|
length: result[0].length
|
|
});
|
|
if (rule.global)
|
|
index = j;
|
|
while (--j > index) {
|
|
var k = j - 1;
|
|
if (matches[j].length > matches[k].length) {
|
|
var temple = matches[j];
|
|
matches[j] = matches[k];
|
|
matches[k] = temple;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return matches;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// node_modules/he/he.js
|
|
var require_he = __commonJS({
|
|
"node_modules/he/he.js"(exports, module2) {
|
|
(function(root) {
|
|
var freeExports = typeof exports == "object" && exports;
|
|
var freeModule = typeof module2 == "object" && module2 && module2.exports == freeExports && module2;
|
|
var freeGlobal = typeof global == "object" && global;
|
|
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
|
|
root = freeGlobal;
|
|
}
|
|
var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
var regexAsciiWhitelist = /[\x01-\x7F]/g;
|
|
var regexBmpWhitelist = /[\x01-\t\x0B\f\x0E-\x1F\x7F\x81\x8D\x8F\x90\x9D\xA0-\uFFFF]/g;
|
|
var regexEncodeNonAscii = /<\u20D2|=\u20E5|>\u20D2|\u205F\u200A|\u219D\u0338|\u2202\u0338|\u2220\u20D2|\u2229\uFE00|\u222A\uFE00|\u223C\u20D2|\u223D\u0331|\u223E\u0333|\u2242\u0338|\u224B\u0338|\u224D\u20D2|\u224E\u0338|\u224F\u0338|\u2250\u0338|\u2261\u20E5|\u2264\u20D2|\u2265\u20D2|\u2266\u0338|\u2267\u0338|\u2268\uFE00|\u2269\uFE00|\u226A\u0338|\u226A\u20D2|\u226B\u0338|\u226B\u20D2|\u227F\u0338|\u2282\u20D2|\u2283\u20D2|\u228A\uFE00|\u228B\uFE00|\u228F\u0338|\u2290\u0338|\u2293\uFE00|\u2294\uFE00|\u22B4\u20D2|\u22B5\u20D2|\u22D8\u0338|\u22D9\u0338|\u22DA\uFE00|\u22DB\uFE00|\u22F5\u0338|\u22F9\u0338|\u2933\u0338|\u29CF\u0338|\u29D0\u0338|\u2A6D\u0338|\u2A70\u0338|\u2A7D\u0338|\u2A7E\u0338|\u2AA1\u0338|\u2AA2\u0338|\u2AAC\uFE00|\u2AAD\uFE00|\u2AAF\u0338|\u2AB0\u0338|\u2AC5\u0338|\u2AC6\u0338|\u2ACB\uFE00|\u2ACC\uFE00|\u2AFD\u20E5|[\xA0-\u0113\u0116-\u0122\u0124-\u012B\u012E-\u014D\u0150-\u017E\u0192\u01B5\u01F5\u0237\u02C6\u02C7\u02D8-\u02DD\u0311\u0391-\u03A1\u03A3-\u03A9\u03B1-\u03C9\u03D1\u03D2\u03D5\u03D6\u03DC\u03DD\u03F0\u03F1\u03F5\u03F6\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E\u045F\u2002-\u2005\u2007-\u2010\u2013-\u2016\u2018-\u201A\u201C-\u201E\u2020-\u2022\u2025\u2026\u2030-\u2035\u2039\u203A\u203E\u2041\u2043\u2044\u204F\u2057\u205F-\u2063\u20AC\u20DB\u20DC\u2102\u2105\u210A-\u2113\u2115-\u211E\u2122\u2124\u2127-\u2129\u212C\u212D\u212F-\u2131\u2133-\u2138\u2145-\u2148\u2153-\u215E\u2190-\u219B\u219D-\u21A7\u21A9-\u21AE\u21B0-\u21B3\u21B5-\u21B7\u21BA-\u21DB\u21DD\u21E4\u21E5\u21F5\u21FD-\u2205\u2207-\u2209\u220B\u220C\u220F-\u2214\u2216-\u2218\u221A\u221D-\u2238\u223A-\u2257\u2259\u225A\u225C\u225F-\u2262\u2264-\u228B\u228D-\u229B\u229D-\u22A5\u22A7-\u22B0\u22B2-\u22BB\u22BD-\u22DB\u22DE-\u22E3\u22E6-\u22F7\u22F9-\u22FE\u2305\u2306\u2308-\u2310\u2312\u2313\u2315\u2316\u231C-\u231F\u2322\u2323\u232D\u232E\u2336\u233D\u233F\u237C\u23B0\u23B1\u23B4-\u23B6\u23DC-\u23DF\u23E2\u23E7\u2423\u24C8\u2500\u2502\u250C\u2510\u2514\u2518\u251C\u2524\u252C\u2534\u253C\u2550-\u256C\u2580\u2584\u2588\u2591-\u2593\u25A1\u25AA\u25AB\u25AD\u25AE\u25B1\u25B3-\u25B5\u25B8\u25B9\u25BD-\u25BF\u25C2\u25C3\u25CA\u25CB\u25EC\u25EF\u25F8-\u25FC\u2605\u2606\u260E\u2640\u2642\u2660\u2663\u2665\u2666\u266A\u266D-\u266F\u2713\u2717\u2720\u2736\u2758\u2772\u2773\u27C8\u27C9\u27E6-\u27ED\u27F5-\u27FA\u27FC\u27FF\u2902-\u2905\u290C-\u2913\u2916\u2919-\u2920\u2923-\u292A\u2933\u2935-\u2939\u293C\u293D\u2945\u2948-\u294B\u294E-\u2976\u2978\u2979\u297B-\u297F\u2985\u2986\u298B-\u2996\u299A\u299C\u299D\u29A4-\u29B7\u29B9\u29BB\u29BC\u29BE-\u29C5\u29C9\u29CD-\u29D0\u29DC-\u29DE\u29E3-\u29E5\u29EB\u29F4\u29F6\u2A00-\u2A02\u2A04\u2A06\u2A0C\u2A0D\u2A10-\u2A17\u2A22-\u2A27\u2A29\u2A2A\u2A2D-\u2A31\u2A33-\u2A3C\u2A3F\u2A40\u2A42-\u2A4D\u2A50\u2A53-\u2A58\u2A5A-\u2A5D\u2A5F\u2A66\u2A6A\u2A6D-\u2A75\u2A77-\u2A9A\u2A9D-\u2AA2\u2AA4-\u2AB0\u2AB3-\u2AC8\u2ACB\u2ACC\u2ACF-\u2ADB\u2AE4\u2AE6-\u2AE9\u2AEB-\u2AF3\u2AFD\uFB00-\uFB04]|\uD835[\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDD6B]/g;
|
|
var encodeMap = { "\xAD": "shy", "\u200C": "zwnj", "\u200D": "zwj", "\u200E": "lrm", "\u2063": "ic", "\u2062": "it", "\u2061": "af", "\u200F": "rlm", "\u200B": "ZeroWidthSpace", "\u2060": "NoBreak", "\u0311": "DownBreve", "\u20DB": "tdot", "\u20DC": "DotDot", " ": "Tab", "\n": "NewLine", "\u2008": "puncsp", "\u205F": "MediumSpace", "\u2009": "thinsp", "\u200A": "hairsp", "\u2004": "emsp13", "\u2002": "ensp", "\u2005": "emsp14", "\u2003": "emsp", "\u2007": "numsp", "\xA0": "nbsp", "\u205F\u200A": "ThickSpace", "\u203E": "oline", "_": "lowbar", "\u2010": "dash", "\u2013": "ndash", "\u2014": "mdash", "\u2015": "horbar", ",": "comma", ";": "semi", "\u204F": "bsemi", ":": "colon", "\u2A74": "Colone", "!": "excl", "\xA1": "iexcl", "?": "quest", "\xBF": "iquest", ".": "period", "\u2025": "nldr", "\u2026": "mldr", "\xB7": "middot", "'": "apos", "\u2018": "lsquo", "\u2019": "rsquo", "\u201A": "sbquo", "\u2039": "lsaquo", "\u203A": "rsaquo", '"': "quot", "\u201C": "ldquo", "\u201D": "rdquo", "\u201E": "bdquo", "\xAB": "laquo", "\xBB": "raquo", "(": "lpar", ")": "rpar", "[": "lsqb", "]": "rsqb", "{": "lcub", "}": "rcub", "\u2308": "lceil", "\u2309": "rceil", "\u230A": "lfloor", "\u230B": "rfloor", "\u2985": "lopar", "\u2986": "ropar", "\u298B": "lbrke", "\u298C": "rbrke", "\u298D": "lbrkslu", "\u298E": "rbrksld", "\u298F": "lbrksld", "\u2990": "rbrkslu", "\u2991": "langd", "\u2992": "rangd", "\u2993": "lparlt", "\u2994": "rpargt", "\u2995": "gtlPar", "\u2996": "ltrPar", "\u27E6": "lobrk", "\u27E7": "robrk", "\u27E8": "lang", "\u27E9": "rang", "\u27EA": "Lang", "\u27EB": "Rang", "\u27EC": "loang", "\u27ED": "roang", "\u2772": "lbbrk", "\u2773": "rbbrk", "\u2016": "Vert", "\xA7": "sect", "\xB6": "para", "@": "commat", "*": "ast", "/": "sol", "undefined": null, "&": "amp", "#": "num", "%": "percnt", "\u2030": "permil", "\u2031": "pertenk", "\u2020": "dagger", "\u2021": "Dagger", "\u2022": "bull", "\u2043": "hybull", "\u2032": "prime", "\u2033": "Prime", "\u2034": "tprime", "\u2057": "qprime", "\u2035": "bprime", "\u2041": "caret", "`": "grave", "\xB4": "acute", "\u02DC": "tilde", "^": "Hat", "\xAF": "macr", "\u02D8": "breve", "\u02D9": "dot", "\xA8": "die", "\u02DA": "ring", "\u02DD": "dblac", "\xB8": "cedil", "\u02DB": "ogon", "\u02C6": "circ", "\u02C7": "caron", "\xB0": "deg", "\xA9": "copy", "\xAE": "reg", "\u2117": "copysr", "\u2118": "wp", "\u211E": "rx", "\u2127": "mho", "\u2129": "iiota", "\u2190": "larr", "\u219A": "nlarr", "\u2192": "rarr", "\u219B": "nrarr", "\u2191": "uarr", "\u2193": "darr", "\u2194": "harr", "\u21AE": "nharr", "\u2195": "varr", "\u2196": "nwarr", "\u2197": "nearr", "\u2198": "searr", "\u2199": "swarr", "\u219D": "rarrw", "\u219D\u0338": "nrarrw", "\u219E": "Larr", "\u219F": "Uarr", "\u21A0": "Rarr", "\u21A1": "Darr", "\u21A2": "larrtl", "\u21A3": "rarrtl", "\u21A4": "mapstoleft", "\u21A5": "mapstoup", "\u21A6": "map", "\u21A7": "mapstodown", "\u21A9": "larrhk", "\u21AA": "rarrhk", "\u21AB": "larrlp", "\u21AC": "rarrlp", "\u21AD": "harrw", "\u21B0": "lsh", "\u21B1": "rsh", "\u21B2": "ldsh", "\u21B3": "rdsh", "\u21B5": "crarr", "\u21B6": "cularr", "\u21B7": "curarr", "\u21BA": "olarr", "\u21BB": "orarr", "\u21BC": "lharu", "\u21BD": "lhard", "\u21BE": "uharr", "\u21BF": "uharl", "\u21C0": "rharu", "\u21C1": "rhard", "\u21C2": "dharr", "\u21C3": "dharl", "\u21C4": "rlarr", "\u21C5": "udarr", "\u21C6": "lrarr", "\u21C7": "llarr", "\u21C8": "uuarr", "\u21C9": "rrarr", "\u21CA": "ddarr", "\u21CB": "lrhar", "\u21CC": "rlhar", "\u21D0": "lArr", "\u21CD": "nlArr", "\u21D1": "uArr", "\u21D2": "rArr", "\u21CF": "nrArr", "\u21D3": "dArr", "\u21D4": "iff", "\u21CE": "nhArr", "\u21D5": "vArr", "\u21D6": "nwArr", "\u21D7": "neArr", "\u21D8": "seArr", "\u21D9": "swArr", "\u21DA": "lAarr", "\u21DB": "rAarr", "\u21DD": "zigrarr", "\u21E4": "larrb", "\u21E5": "rarrb", "\u21F5": "duarr", "\u21FD": "loarr", "\u21FE": "roarr", "\u21FF": "hoarr", "\u2200": "forall", "\u2201": "comp", "\u2202": "part", "\u2202\u0338": "npart", "\u2203": "exist", "\u2204": "nexist", "\u2205": "empty", "\u2207": "Del", "\u2208": "in", "\u2209": "notin", "\u220B": "ni", "\u220C": "notni", "\u03F6": "bepsi", "\u220F": "prod", "\u2210": "coprod", "\u2211": "sum", "+": "plus", "\xB1": "pm", "\xF7": "div", "\xD7": "times", "<": "lt", "\u226E": "nlt", "<\u20D2": "nvlt", "=": "equals", "\u2260": "ne", "=\u20E5": "bne", "\u2A75": "Equal", ">": "gt", "\u226F": "ngt", ">\u20D2": "nvgt", "\xAC": "not", "|": "vert", "\xA6": "brvbar", "\u2212": "minus", "\u2213": "mp", "\u2214": "plusdo", "\u2044": "frasl", "\u2216": "setmn", "\u2217": "lowast", "\u2218": "compfn", "\u221A": "Sqrt", "\u221D": "prop", "\u221E": "infin", "\u221F": "angrt", "\u2220": "ang", "\u2220\u20D2": "nang", "\u2221": "angmsd", "\u2222": "angsph", "\u2223": "mid", "\u2224": "nmid", "\u2225": "par", "\u2226": "npar", "\u2227": "and", "\u2228": "or", "\u2229": "cap", "\u2229\uFE00": "caps", "\u222A": "cup", "\u222A\uFE00": "cups", "\u222B": "int", "\u222C": "Int", "\u222D": "tint", "\u2A0C": "qint", "\u222E": "oint", "\u222F": "Conint", "\u2230": "Cconint", "\u2231": "cwint", "\u2232": "cwconint", "\u2233": "awconint", "\u2234": "there4", "\u2235": "becaus", "\u2236": "ratio", "\u2237": "Colon", "\u2238": "minusd", "\u223A": "mDDot", "\u223B": "homtht", "\u223C": "sim", "\u2241": "nsim", "\u223C\u20D2": "nvsim", "\u223D": "bsim", "\u223D\u0331": "race", "\u223E": "ac", "\u223E\u0333": "acE", "\u223F": "acd", "\u2240": "wr", "\u2242": "esim", "\u2242\u0338": "nesim", "\u2243": "sime", "\u2244": "nsime", "\u2245": "cong", "\u2247": "ncong", "\u2246": "simne", "\u2248": "ap", "\u2249": "nap", "\u224A": "ape", "\u224B": "apid", "\u224B\u0338": "napid", "\u224C": "bcong", "\u224D": "CupCap", "\u226D": "NotCupCap", "\u224D\u20D2": "nvap", "\u224E": "bump", "\u224E\u0338": "nbump", "\u224F": "bumpe", "\u224F\u0338": "nbumpe", "\u2250": "doteq", "\u2250\u0338": "nedot", "\u2251": "eDot", "\u2252": "efDot", "\u2253": "erDot", "\u2254": "colone", "\u2255": "ecolon", "\u2256": "ecir", "\u2257": "cire", "\u2259": "wedgeq", "\u225A": "veeeq", "\u225C": "trie", "\u225F": "equest", "\u2261": "equiv", "\u2262": "nequiv", "\u2261\u20E5": "bnequiv", "\u2264": "le", "\u2270": "nle", "\u2264\u20D2": "nvle", "\u2265": "ge", "\u2271": "nge", "\u2265\u20D2": "nvge", "\u2266": "lE", "\u2266\u0338": "nlE", "\u2267": "gE", "\u2267\u0338": "ngE", "\u2268\uFE00": "lvnE", "\u2268": "lnE", "\u2269": "gnE", "\u2269\uFE00": "gvnE", "\u226A": "ll", "\u226A\u0338": "nLtv", "\u226A\u20D2": "nLt", "\u226B": "gg", "\u226B\u0338": "nGtv", "\u226B\u20D2": "nGt", "\u226C": "twixt", "\u2272": "lsim", "\u2274": "nlsim", "\u2273": "gsim", "\u2275": "ngsim", "\u2276": "lg", "\u2278": "ntlg", "\u2277": "gl", "\u2279": "ntgl", "\u227A": "pr", "\u2280": "npr", "\u227B": "sc", "\u2281": "nsc", "\u227C": "prcue", "\u22E0": "nprcue", "\u227D": "sccue", "\u22E1": "nsccue", "\u227E": "prsim", "\u227F": "scsim", "\u227F\u0338": "NotSucceedsTilde", "\u2282": "sub", "\u2284": "nsub", "\u2282\u20D2": "vnsub", "\u2283": "sup", "\u2285": "nsup", "\u2283\u20D2": "vnsup", "\u2286": "sube", "\u2288": "nsube", "\u2287": "supe", "\u2289": "nsupe", "\u228A\uFE00": "vsubne", "\u228A": "subne", "\u228B\uFE00": "vsupne", "\u228B": "supne", "\u228D": "cupdot", "\u228E": "uplus", "\u228F": "sqsub", "\u228F\u0338": "NotSquareSubset", "\u2290": "sqsup", "\u2290\u0338": "NotSquareSuperset", "\u2291": "sqsube", "\u22E2": "nsqsube", "\u2292": "sqsupe", "\u22E3": "nsqsupe", "\u2293": "sqcap", "\u2293\uFE00": "sqcaps", "\u2294": "sqcup", "\u2294\uFE00": "sqcups", "\u2295": "oplus", "\u2296": "ominus", "\u2297": "otimes", "\u2298": "osol", "\u2299": "odot", "\u229A": "ocir", "\u229B": "oast", "\u229D": "odash", "\u229E": "plusb", "\u229F": "minusb", "\u22A0": "timesb", "\u22A1": "sdotb", "\u22A2": "vdash", "\u22AC": "nvdash", "\u22A3": "dashv", "\u22A4": "top", "\u22A5": "bot", "\u22A7": "models", "\u22A8": "vDash", "\u22AD": "nvDash", "\u22A9": "Vdash", "\u22AE": "nVdash", "\u22AA": "Vvdash", "\u22AB": "VDash", "\u22AF": "nVDash", "\u22B0": "prurel", "\u22B2": "vltri", "\u22EA": "nltri", "\u22B3": "vrtri", "\u22EB": "nrtri", "\u22B4": "ltrie", "\u22EC": "nltrie", "\u22B4\u20D2": "nvltrie", "\u22B5": "rtrie", "\u22ED": "nrtrie", "\u22B5\u20D2": "nvrtrie", "\u22B6": "origof", "\u22B7": "imof", "\u22B8": "mumap", "\u22B9": "hercon", "\u22BA": "intcal", "\u22BB": "veebar", "\u22BD": "barvee", "\u22BE": "angrtvb", "\u22BF": "lrtri", "\u22C0": "Wedge", "\u22C1": "Vee", "\u22C2": "xcap", "\u22C3": "xcup", "\u22C4": "diam", "\u22C5": "sdot", "\u22C6": "Star", "\u22C7": "divonx", "\u22C8": "bowtie", "\u22C9": "ltimes", "\u22CA": "rtimes", "\u22CB": "lthree", "\u22CC": "rthree", "\u22CD": "bsime", "\u22CE": "cuvee", "\u22CF": "cuwed", "\u22D0": "Sub", "\u22D1": "Sup", "\u22D2": "Cap", "\u22D3": "Cup", "\u22D4": "fork", "\u22D5": "epar", "\u22D6": "ltdot", "\u22D7": "gtdot", "\u22D8": "Ll", "\u22D8\u0338": "nLl", "\u22D9": "Gg", "\u22D9\u0338": "nGg", "\u22DA\uFE00": "lesg", "\u22DA": "leg", "\u22DB": "gel", "\u22DB\uFE00": "gesl", "\u22DE": "cuepr", "\u22DF": "cuesc", "\u22E6": "lnsim", "\u22E7": "gnsim", "\u22E8": "prnsim", "\u22E9": "scnsim", "\u22EE": "vellip", "\u22EF": "ctdot", "\u22F0": "utdot", "\u22F1": "dtdot", "\u22F2": "disin", "\u22F3": "isinsv", "\u22F4": "isins", "\u22F5": "isindot", "\u22F5\u0338": "notindot", "\u22F6": "notinvc", "\u22F7": "notinvb", "\u22F9": "isinE", "\u22F9\u0338": "notinE", "\u22FA": "nisd", "\u22FB": "xnis", "\u22FC": "nis", "\u22FD": "notnivc", "\u22FE": "notnivb", "\u2305": "barwed", "\u2306": "Barwed", "\u230C": "drcrop", "\u230D": "dlcrop", "\u230E": "urcrop", "\u230F": "ulcrop", "\u2310": "bnot", "\u2312": "profline", "\u2313": "profsurf", "\u2315": "telrec", "\u2316": "target", "\u231C": "ulcorn", "\u231D": "urcorn", "\u231E": "dlcorn", "\u231F": "drcorn", "\u2322": "frown", "\u2323": "smile", "\u232D": "cylcty", "\u232E": "profalar", "\u2336": "topbot", "\u233D": "ovbar", "\u233F": "solbar", "\u237C": "angzarr", "\u23B0": "lmoust", "\u23B1": "rmoust", "\u23B4": "tbrk", "\u23B5": "bbrk", "\u23B6": "bbrktbrk", "\u23DC": "OverParenthesis", "\u23DD": "UnderParenthesis", "\u23DE": "OverBrace", "\u23DF": "UnderBrace", "\u23E2": "trpezium", "\u23E7": "elinters", "\u2423": "blank", "\u2500": "boxh", "\u2502": "boxv", "\u250C": "boxdr", "\u2510": "boxdl", "\u2514": "boxur", "\u2518": "boxul", "\u251C": "boxvr", "\u2524": "boxvl", "\u252C": "boxhd", "\u2534": "boxhu", "\u253C": "boxvh", "\u2550": "boxH", "\u2551": "boxV", "\u2552": "boxdR", "\u2553": "boxDr", "\u2554": "boxDR", "\u2555": "boxdL", "\u2556": "boxDl", "\u2557": "boxDL", "\u2558": "boxuR", "\u2559": "boxUr", "\u255A": "boxUR", "\u255B": "boxuL", "\u255C": "boxUl", "\u255D": "boxUL", "\u255E": "boxvR", "\u255F": "boxVr", "\u2560": "boxVR", "\u2561": "boxvL", "\u2562": "boxVl", "\u2563": "boxVL", "\u2564": "boxHd", "\u2565": "boxhD", "\u2566": "boxHD", "\u2567": "boxHu", "\u2568": "boxhU", "\u2569": "boxHU", "\u256A": "boxvH", "\u256B": "boxVh", "\u256C": "boxVH", "\u2580": "uhblk", "\u2584": "lhblk", "\u2588": "block", "\u2591": "blk14", "\u2592": "blk12", "\u2593": "blk34", "\u25A1": "squ", "\u25AA": "squf", "\u25AB": "EmptyVerySmallSquare", "\u25AD": "rect", "\u25AE": "marker", "\u25B1": "fltns", "\u25B3": "xutri", "\u25B4": "utrif", "\u25B5": "utri", "\u25B8": "rtrif", "\u25B9": "rtri", "\u25BD": "xdtri", "\u25BE": "dtrif", "\u25BF": "dtri", "\u25C2": "ltrif", "\u25C3": "ltri", "\u25CA": "loz", "\u25CB": "cir", "\u25EC": "tridot", "\u25EF": "xcirc", "\u25F8": "ultri", "\u25F9": "urtri", "\u25FA": "lltri", "\u25FB": "EmptySmallSquare", "\u25FC": "FilledSmallSquare", "\u2605": "starf", "\u2606": "star", "\u260E": "phone", "\u2640": "female", "\u2642": "male", "\u2660": "spades", "\u2663": "clubs", "\u2665": "hearts", "\u2666": "diams", "\u266A": "sung", "\u2713": "check", "\u2717": "cross", "\u2720": "malt", "\u2736": "sext", "\u2758": "VerticalSeparator", "\u27C8": "bsolhsub", "\u27C9": "suphsol", "\u27F5": "xlarr", "\u27F6": "xrarr", "\u27F7": "xharr", "\u27F8": "xlArr", "\u27F9": "xrArr", "\u27FA": "xhArr", "\u27FC": "xmap", "\u27FF": "dzigrarr", "\u2902": "nvlArr", "\u2903": "nvrArr", "\u2904": "nvHarr", "\u2905": "Map", "\u290C": "lbarr", "\u290D": "rbarr", "\u290E": "lBarr", "\u290F": "rBarr", "\u2910": "RBarr", "\u2911": "DDotrahd", "\u2912": "UpArrowBar", "\u2913": "DownArrowBar", "\u2916": "Rarrtl", "\u2919": "latail", "\u291A": "ratail", "\u291B": "lAtail", "\u291C": "rAtail", "\u291D": "larrfs", "\u291E": "rarrfs", "\u291F": "larrbfs", "\u2920": "rarrbfs", "\u2923": "nwarhk", "\u2924": "nearhk", "\u2925": "searhk", "\u2926": "swarhk", "\u2927": "nwnear", "\u2928": "toea", "\u2929": "tosa", "\u292A": "swnwar", "\u2933": "rarrc", "\u2933\u0338": "nrarrc", "\u2935": "cudarrr", "\u2936": "ldca", "\u2937": "rdca", "\u2938": "cudarrl", "\u2939": "larrpl", "\u293C": "curarrm", "\u293D": "cularrp", "\u2945": "rarrpl", "\u2948": "harrcir", "\u2949": "Uarrocir", "\u294A": "lurdshar", "\u294B": "ldrushar", "\u294E": "LeftRightVector", "\u294F": "RightUpDownVector", "\u2950": "DownLeftRightVector", "\u2951": "LeftUpDownVector", "\u2952": "LeftVectorBar", "\u2953": "RightVectorBar", "\u2954": "RightUpVectorBar", "\u2955": "RightDownVectorBar", "\u2956": "DownLeftVectorBar", "\u2957": "DownRightVectorBar", "\u2958": "LeftUpVectorBar", "\u2959": "LeftDownVectorBar", "\u295A": "LeftTeeVector", "\u295B": "RightTeeVector", "\u295C": "RightUpTeeVector", "\u295D": "RightDownTeeVector", "\u295E": "DownLeftTeeVector", "\u295F": "DownRightTeeVector", "\u2960": "LeftUpTeeVector", "\u2961": "LeftDownTeeVector", "\u2962": "lHar", "\u2963": "uHar", "\u2964": "rHar", "\u2965": "dHar", "\u2966": "luruhar", "\u2967": "ldrdhar", "\u2968": "ruluhar", "\u2969": "rdldhar", "\u296A": "lharul", "\u296B": "llhard", "\u296C": "rharul", "\u296D": "lrhard", "\u296E": "udhar", "\u296F": "duhar", "\u2970": "RoundImplies", "\u2971": "erarr", "\u2972": "simrarr", "\u2973": "larrsim", "\u2974": "rarrsim", "\u2975": "rarrap", "\u2976": "ltlarr", "\u2978": "gtrarr", "\u2979": "subrarr", "\u297B": "suplarr", "\u297C": "lfisht", "\u297D": "rfisht", "\u297E": "ufisht", "\u297F": "dfisht", "\u299A": "vzigzag", "\u299C": "vangrt", "\u299D": "angrtvbd", "\u29A4": "ange", "\u29A5": "range", "\u29A6": "dwangle", "\u29A7": "uwangle", "\u29A8": "angmsdaa", "\u29A9": "angmsdab", "\u29AA": "angmsdac", "\u29AB": "angmsdad", "\u29AC": "angmsdae", "\u29AD": "angmsdaf", "\u29AE": "angmsdag", "\u29AF": "angmsdah", "\u29B0": "bemptyv", "\u29B1": "demptyv", "\u29B2": "cemptyv", "\u29B3": "raemptyv", "\u29B4": "laemptyv", "\u29B5": "ohbar", "\u29B6": "omid", "\u29B7": "opar", "\u29B9": "operp", "\u29BB": "olcross", "\u29BC": "odsold", "\u29BE": "olcir", "\u29BF": "ofcir", "\u29C0": "olt", "\u29C1": "ogt", "\u29C2": "cirscir", "\u29C3": "cirE", "\u29C4": "solb", "\u29C5": "bsolb", "\u29C9": "boxbox", "\u29CD": "trisb", "\u29CE": "rtriltri", "\u29CF": "LeftTriangleBar", "\u29CF\u0338": "NotLeftTriangleBar", "\u29D0": "RightTriangleBar", "\u29D0\u0338": "NotRightTriangleBar", "\u29DC": "iinfin", "\u29DD": "infintie", "\u29DE": "nvinfin", "\u29E3": "eparsl", "\u29E4": "smeparsl", "\u29E5": "eqvparsl", "\u29EB": "lozf", "\u29F4": "RuleDelayed", "\u29F6": "dsol", "\u2A00": "xodot", "\u2A01": "xoplus", "\u2A02": "xotime", "\u2A04": "xuplus", "\u2A06": "xsqcup", "\u2A0D": "fpartint", "\u2A10": "cirfnint", "\u2A11": "awint", "\u2A12": "rppolint", "\u2A13": "scpolint", "\u2A14": "npolint", "\u2A15": "pointint", "\u2A16": "quatint", "\u2A17": "intlarhk", "\u2A22": "pluscir", "\u2A23": "plusacir", "\u2A24": "simplus", "\u2A25": "plusdu", "\u2A26": "plussim", "\u2A27": "plustwo", "\u2A29": "mcomma", "\u2A2A": "minusdu", "\u2A2D": "loplus", "\u2A2E": "roplus", "\u2A2F": "Cross", "\u2A30": "timesd", "\u2A31": "timesbar", "\u2A33": "smashp", "\u2A34": "lotimes", "\u2A35": "rotimes", "\u2A36": "otimesas", "\u2A37": "Otimes", "\u2A38": "odiv", "\u2A39": "triplus", "\u2A3A": "triminus", "\u2A3B": "tritime", "\u2A3C": "iprod", "\u2A3F": "amalg", "\u2A40": "capdot", "\u2A42": "ncup", "\u2A43": "ncap", "\u2A44": "capand", "\u2A45": "cupor", "\u2A46": "cupcap", "\u2A47": "capcup", "\u2A48": "cupbrcap", "\u2A49": "capbrcup", "\u2A4A": "cupcup", "\u2A4B": "capcap", "\u2A4C": "ccups", "\u2A4D": "ccaps", "\u2A50": "ccupssm", "\u2A53": "And", "\u2A54": "Or", "\u2A55": "andand", "\u2A56": "oror", "\u2A57": "orslope", "\u2A58": "andslope", "\u2A5A": "andv", "\u2A5B": "orv", "\u2A5C": "andd", "\u2A5D": "ord", "\u2A5F": "wedbar", "\u2A66": "sdote", "\u2A6A": "simdot", "\u2A6D": "congdot", "\u2A6D\u0338": "ncongdot", "\u2A6E": "easter", "\u2A6F": "apacir", "\u2A70": "apE", "\u2A70\u0338": "napE", "\u2A71": "eplus", "\u2A72": "pluse", "\u2A73": "Esim", "\u2A77": "eDDot", "\u2A78": "equivDD", "\u2A79": "ltcir", "\u2A7A": "gtcir", "\u2A7B": "ltquest", "\u2A7C": "gtquest", "\u2A7D": "les", "\u2A7D\u0338": "nles", "\u2A7E": "ges", "\u2A7E\u0338": "nges", "\u2A7F": "lesdot", "\u2A80": "gesdot", "\u2A81": "lesdoto", "\u2A82": "gesdoto", "\u2A83": "lesdotor", "\u2A84": "gesdotol", "\u2A85": "lap", "\u2A86": "gap", "\u2A87": "lne", "\u2A88": "gne", "\u2A89": "lnap", "\u2A8A": "gnap", "\u2A8B": "lEg", "\u2A8C": "gEl", "\u2A8D": "lsime", "\u2A8E": "gsime", "\u2A8F": "lsimg", "\u2A90": "gsiml", "\u2A91": "lgE", "\u2A92": "glE", "\u2A93": "lesges", "\u2A94": "gesles", "\u2A95": "els", "\u2A96": "egs", "\u2A97": "elsdot", "\u2A98": "egsdot", "\u2A99": "el", "\u2A9A": "eg", "\u2A9D": "siml", "\u2A9E": "simg", "\u2A9F": "simlE", "\u2AA0": "simgE", "\u2AA1": "LessLess", "\u2AA1\u0338": "NotNestedLessLess", "\u2AA2": "GreaterGreater", "\u2AA2\u0338": "NotNestedGreaterGreater", "\u2AA4": "glj", "\u2AA5": "gla", "\u2AA6": "ltcc", "\u2AA7": "gtcc", "\u2AA8": "lescc", "\u2AA9": "gescc", "\u2AAA": "smt", "\u2AAB": "lat", "\u2AAC": "smte", "\u2AAC\uFE00": "smtes", "\u2AAD": "late", "\u2AAD\uFE00": "lates", "\u2AAE": "bumpE", "\u2AAF": "pre", "\u2AAF\u0338": "npre", "\u2AB0": "sce", "\u2AB0\u0338": "nsce", "\u2AB3": "prE", "\u2AB4": "scE", "\u2AB5": "prnE", "\u2AB6": "scnE", "\u2AB7": "prap", "\u2AB8": "scap", "\u2AB9": "prnap", "\u2ABA": "scnap", "\u2ABB": "Pr", "\u2ABC": "Sc", "\u2ABD": "subdot", "\u2ABE": "supdot", "\u2ABF": "subplus", "\u2AC0": "supplus", "\u2AC1": "submult", "\u2AC2": "supmult", "\u2AC3": "subedot", "\u2AC4": "supedot", "\u2AC5": "subE", "\u2AC5\u0338": "nsubE", "\u2AC6": "supE", "\u2AC6\u0338": "nsupE", "\u2AC7": "subsim", "\u2AC8": "supsim", "\u2ACB\uFE00": "vsubnE", "\u2ACB": "subnE", "\u2ACC\uFE00": "vsupnE", "\u2ACC": "supnE", "\u2ACF": "csub", "\u2AD0": "csup", "\u2AD1": "csube", "\u2AD2": "csupe", "\u2AD3": "subsup", "\u2AD4": "supsub", "\u2AD5": "subsub", "\u2AD6": "supsup", "\u2AD7": "suphsub", "\u2AD8": "supdsub", "\u2AD9": "forkv", "\u2ADA": "topfork", "\u2ADB": "mlcp", "\u2AE4": "Dashv", "\u2AE6": "Vdashl", "\u2AE7": "Barv", "\u2AE8": "vBar", "\u2AE9": "vBarv", "\u2AEB": "Vbar", "\u2AEC": "Not", "\u2AED": "bNot", "\u2AEE": "rnmid", "\u2AEF": "cirmid", "\u2AF0": "midcir", "\u2AF1": "topcir", "\u2AF2": "nhpar", "\u2AF3": "parsim", "\u2AFD": "parsl", "\u2AFD\u20E5": "nparsl", "\u266D": "flat", "\u266E": "natur", "\u266F": "sharp", "\xA4": "curren", "\xA2": "cent", "$": "dollar", "\xA3": "pound", "\xA5": "yen", "\u20AC": "euro", "\xB9": "sup1", "\xBD": "half", "\u2153": "frac13", "\xBC": "frac14", "\u2155": "frac15", "\u2159": "frac16", "\u215B": "frac18", "\xB2": "sup2", "\u2154": "frac23", "\u2156": "frac25", "\xB3": "sup3", "\xBE": "frac34", "\u2157": "frac35", "\u215C": "frac38", "\u2158": "frac45", "\u215A": "frac56", "\u215D": "frac58", "\u215E": "frac78", "\u{1D4B6}": "ascr", "\u{1D552}": "aopf", "\u{1D51E}": "afr", "\u{1D538}": "Aopf", "\u{1D504}": "Afr", "\u{1D49C}": "Ascr", "\xAA": "ordf", "\xE1": "aacute", "\xC1": "Aacute", "\xE0": "agrave", "\xC0": "Agrave", "\u0103": "abreve", "\u0102": "Abreve", "\xE2": "acirc", "\xC2": "Acirc", "\xE5": "aring", "\xC5": "angst", "\xE4": "auml", "\xC4": "Auml", "\xE3": "atilde", "\xC3": "Atilde", "\u0105": "aogon", "\u0104": "Aogon", "\u0101": "amacr", "\u0100": "Amacr", "\xE6": "aelig", "\xC6": "AElig", "\u{1D4B7}": "bscr", "\u{1D553}": "bopf", "\u{1D51F}": "bfr", "\u{1D539}": "Bopf", "\u212C": "Bscr", "\u{1D505}": "Bfr", "\u{1D520}": "cfr", "\u{1D4B8}": "cscr", "\u{1D554}": "copf", "\u212D": "Cfr", "\u{1D49E}": "Cscr", "\u2102": "Copf", "\u0107": "cacute", "\u0106": "Cacute", "\u0109": "ccirc", "\u0108": "Ccirc", "\u010D": "ccaron", "\u010C": "Ccaron", "\u010B": "cdot", "\u010A": "Cdot", "\xE7": "ccedil", "\xC7": "Ccedil", "\u2105": "incare", "\u{1D521}": "dfr", "\u2146": "dd", "\u{1D555}": "dopf", "\u{1D4B9}": "dscr", "\u{1D49F}": "Dscr", "\u{1D507}": "Dfr", "\u2145": "DD", "\u{1D53B}": "Dopf", "\u010F": "dcaron", "\u010E": "Dcaron", "\u0111": "dstrok", "\u0110": "Dstrok", "\xF0": "eth", "\xD0": "ETH", "\u2147": "ee", "\u212F": "escr", "\u{1D522}": "efr", "\u{1D556}": "eopf", "\u2130": "Escr", "\u{1D508}": "Efr", "\u{1D53C}": "Eopf", "\xE9": "eacute", "\xC9": "Eacute", "\xE8": "egrave", "\xC8": "Egrave", "\xEA": "ecirc", "\xCA": "Ecirc", "\u011B": "ecaron", "\u011A": "Ecaron", "\xEB": "euml", "\xCB": "Euml", "\u0117": "edot", "\u0116": "Edot", "\u0119": "eogon", "\u0118": "Eogon", "\u0113": "emacr", "\u0112": "Emacr", "\u{1D523}": "ffr", "\u{1D557}": "fopf", "\u{1D4BB}": "fscr", "\u{1D509}": "Ffr", "\u{1D53D}": "Fopf", "\u2131": "Fscr", "\uFB00": "fflig", "\uFB03": "ffilig", "\uFB04": "ffllig", "\uFB01": "filig", "fj": "fjlig", "\uFB02": "fllig", "\u0192": "fnof", "\u210A": "gscr", "\u{1D558}": "gopf", "\u{1D524}": "gfr", "\u{1D4A2}": "Gscr", "\u{1D53E}": "Gopf", "\u{1D50A}": "Gfr", "\u01F5": "gacute", "\u011F": "gbreve", "\u011E": "Gbreve", "\u011D": "gcirc", "\u011C": "Gcirc", "\u0121": "gdot", "\u0120": "Gdot", "\u0122": "Gcedil", "\u{1D525}": "hfr", "\u210E": "planckh", "\u{1D4BD}": "hscr", "\u{1D559}": "hopf", "\u210B": "Hscr", "\u210C": "Hfr", "\u210D": "Hopf", "\u0125": "hcirc", "\u0124": "Hcirc", "\u210F": "hbar", "\u0127": "hstrok", "\u0126": "Hstrok", "\u{1D55A}": "iopf", "\u{1D526}": "ifr", "\u{1D4BE}": "iscr", "\u2148": "ii", "\u{1D540}": "Iopf", "\u2110": "Iscr", "\u2111": "Im", "\xED": "iacute", "\xCD": "Iacute", "\xEC": "igrave", "\xCC": "Igrave", "\xEE": "icirc", "\xCE": "Icirc", "\xEF": "iuml", "\xCF": "Iuml", "\u0129": "itilde", "\u0128": "Itilde", "\u0130": "Idot", "\u012F": "iogon", "\u012E": "Iogon", "\u012B": "imacr", "\u012A": "Imacr", "\u0133": "ijlig", "\u0132": "IJlig", "\u0131": "imath", "\u{1D4BF}": "jscr", "\u{1D55B}": "jopf", "\u{1D527}": "jfr", "\u{1D4A5}": "Jscr", "\u{1D50D}": "Jfr", "\u{1D541}": "Jopf", "\u0135": "jcirc", "\u0134": "Jcirc", "\u0237": "jmath", "\u{1D55C}": "kopf", "\u{1D4C0}": "kscr", "\u{1D528}": "kfr", "\u{1D4A6}": "Kscr", "\u{1D542}": "Kopf", "\u{1D50E}": "Kfr", "\u0137": "kcedil", "\u0136": "Kcedil", "\u{1D529}": "lfr", "\u{1D4C1}": "lscr", "\u2113": "ell", "\u{1D55D}": "lopf", "\u2112": "Lscr", "\u{1D50F}": "Lfr", "\u{1D543}": "Lopf", "\u013A": "lacute", "\u0139": "Lacute", "\u013E": "lcaron", "\u013D": "Lcaron", "\u013C": "lcedil", "\u013B": "Lcedil", "\u0142": "lstrok", "\u0141": "Lstrok", "\u0140": "lmidot", "\u013F": "Lmidot", "\u{1D52A}": "mfr", "\u{1D55E}": "mopf", "\u{1D4C2}": "mscr", "\u{1D510}": "Mfr", "\u{1D544}": "Mopf", "\u2133": "Mscr", "\u{1D52B}": "nfr", "\u{1D55F}": "nopf", "\u{1D4C3}": "nscr", "\u2115": "Nopf", "\u{1D4A9}": "Nscr", "\u{1D511}": "Nfr", "\u0144": "nacute", "\u0143": "Nacute", "\u0148": "ncaron", "\u0147": "Ncaron", "\xF1": "ntilde", "\xD1": "Ntilde", "\u0146": "ncedil", "\u0145": "Ncedil", "\u2116": "numero", "\u014B": "eng", "\u014A": "ENG", "\u{1D560}": "oopf", "\u{1D52C}": "ofr", "\u2134": "oscr", "\u{1D4AA}": "Oscr", "\u{1D512}": "Ofr", "\u{1D546}": "Oopf", "\xBA": "ordm", "\xF3": "oacute", "\xD3": "Oacute", "\xF2": "ograve", "\xD2": "Ograve", "\xF4": "ocirc", "\xD4": "Ocirc", "\xF6": "ouml", "\xD6": "Ouml", "\u0151": "odblac", "\u0150": "Odblac", "\xF5": "otilde", "\xD5": "Otilde", "\xF8": "oslash", "\xD8": "Oslash", "\u014D": "omacr", "\u014C": "Omacr", "\u0153": "oelig", "\u0152": "OElig", "\u{1D52D}": "pfr", "\u{1D4C5}": "pscr", "\u{1D561}": "popf", "\u2119": "Popf", "\u{1D513}": "Pfr", "\u{1D4AB}": "Pscr", "\u{1D562}": "qopf", "\u{1D52E}": "qfr", "\u{1D4C6}": "qscr", "\u{1D4AC}": "Qscr", "\u{1D514}": "Qfr", "\u211A": "Qopf", "\u0138": "kgreen", "\u{1D52F}": "rfr", "\u{1D563}": "ropf", "\u{1D4C7}": "rscr", "\u211B": "Rscr", "\u211C": "Re", "\u211D": "Ropf", "\u0155": "racute", "\u0154": "Racute", "\u0159": "rcaron", "\u0158": "Rcaron", "\u0157": "rcedil", "\u0156": "Rcedil", "\u{1D564}": "sopf", "\u{1D4C8}": "sscr", "\u{1D530}": "sfr", "\u{1D54A}": "Sopf", "\u{1D516}": "Sfr", "\u{1D4AE}": "Sscr", "\u24C8": "oS", "\u015B": "sacute", "\u015A": "Sacute", "\u015D": "scirc", "\u015C": "Scirc", "\u0161": "scaron", "\u0160": "Scaron", "\u015F": "scedil", "\u015E": "Scedil", "\xDF": "szlig", "\u{1D531}": "tfr", "\u{1D4C9}": "tscr", "\u{1D565}": "topf", "\u{1D4AF}": "Tscr", "\u{1D517}": "Tfr", "\u{1D54B}": "Topf", "\u0165": "tcaron", "\u0164": "Tcaron", "\u0163": "tcedil", "\u0162": "Tcedil", "\u2122": "trade", "\u0167": "tstrok", "\u0166": "Tstrok", "\u{1D4CA}": "uscr", "\u{1D566}": "uopf", "\u{1D532}": "ufr", "\u{1D54C}": "Uopf", "\u{1D518}": "Ufr", "\u{1D4B0}": "Uscr", "\xFA": "uacute", "\xDA": "Uacute", "\xF9": "ugrave", "\xD9": "Ugrave", "\u016D": "ubreve", "\u016C": "Ubreve", "\xFB": "ucirc", "\xDB": "Ucirc", "\u016F": "uring", "\u016E": "Uring", "\xFC": "uuml", "\xDC": "Uuml", "\u0171": "udblac", "\u0170": "Udblac", "\u0169": "utilde", "\u0168": "Utilde", "\u0173": "uogon", "\u0172": "Uogon", "\u016B": "umacr", "\u016A": "Umacr", "\u{1D533}": "vfr", "\u{1D567}": "vopf", "\u{1D4CB}": "vscr", "\u{1D519}": "Vfr", "\u{1D54D}": "Vopf", "\u{1D4B1}": "Vscr", "\u{1D568}": "wopf", "\u{1D4CC}": "wscr", "\u{1D534}": "wfr", "\u{1D4B2}": "Wscr", "\u{1D54E}": "Wopf", "\u{1D51A}": "Wfr", "\u0175": "wcirc", "\u0174": "Wcirc", "\u{1D535}": "xfr", "\u{1D4CD}": "xscr", "\u{1D569}": "xopf", "\u{1D54F}": "Xopf", "\u{1D51B}": "Xfr", "\u{1D4B3}": "Xscr", "\u{1D536}": "yfr", "\u{1D4CE}": "yscr", "\u{1D56A}": "yopf", "\u{1D4B4}": "Yscr", "\u{1D51C}": "Yfr", "\u{1D550}": "Yopf", "\xFD": "yacute", "\xDD": "Yacute", "\u0177": "ycirc", "\u0176": "Ycirc", "\xFF": "yuml", "\u0178": "Yuml", "\u{1D4CF}": "zscr", "\u{1D537}": "zfr", "\u{1D56B}": "zopf", "\u2128": "Zfr", "\u2124": "Zopf", "\u{1D4B5}": "Zscr", "\u017A": "zacute", "\u0179": "Zacute", "\u017E": "zcaron", "\u017D": "Zcaron", "\u017C": "zdot", "\u017B": "Zdot", "\u01B5": "imped", "\xFE": "thorn", "\xDE": "THORN", "\u0149": "napos", "\u03B1": "alpha", "\u0391": "Alpha", "\u03B2": "beta", "\u0392": "Beta", "\u03B3": "gamma", "\u0393": "Gamma", "\u03B4": "delta", "\u0394": "Delta", "\u03B5": "epsi", "\u03F5": "epsiv", "\u0395": "Epsilon", "\u03DD": "gammad", "\u03DC": "Gammad", "\u03B6": "zeta", "\u0396": "Zeta", "\u03B7": "eta", "\u0397": "Eta", "\u03B8": "theta", "\u03D1": "thetav", "\u0398": "Theta", "\u03B9": "iota", "\u0399": "Iota", "\u03BA": "kappa", "\u03F0": "kappav", "\u039A": "Kappa", "\u03BB": "lambda", "\u039B": "Lambda", "\u03BC": "mu", "\xB5": "micro", "\u039C": "Mu", "\u03BD": "nu", "\u039D": "Nu", "\u03BE": "xi", "\u039E": "Xi", "\u03BF": "omicron", "\u039F": "Omicron", "\u03C0": "pi", "\u03D6": "piv", "\u03A0": "Pi", "\u03C1": "rho", "\u03F1": "rhov", "\u03A1": "Rho", "\u03C3": "sigma", "\u03A3": "Sigma", "\u03C2": "sigmaf", "\u03C4": "tau", "\u03A4": "Tau", "\u03C5": "upsi", "\u03A5": "Upsilon", "\u03D2": "Upsi", "\u03C6": "phi", "\u03D5": "phiv", "\u03A6": "Phi", "\u03C7": "chi", "\u03A7": "Chi", "\u03C8": "psi", "\u03A8": "Psi", "\u03C9": "omega", "\u03A9": "ohm", "\u0430": "acy", "\u0410": "Acy", "\u0431": "bcy", "\u0411": "Bcy", "\u0432": "vcy", "\u0412": "Vcy", "\u0433": "gcy", "\u0413": "Gcy", "\u0453": "gjcy", "\u0403": "GJcy", "\u0434": "dcy", "\u0414": "Dcy", "\u0452": "djcy", "\u0402": "DJcy", "\u0435": "iecy", "\u0415": "IEcy", "\u0451": "iocy", "\u0401": "IOcy", "\u0454": "jukcy", "\u0404": "Jukcy", "\u0436": "zhcy", "\u0416": "ZHcy", "\u0437": "zcy", "\u0417": "Zcy", "\u0455": "dscy", "\u0405": "DScy", "\u0438": "icy", "\u0418": "Icy", "\u0456": "iukcy", "\u0406": "Iukcy", "\u0457": "yicy", "\u0407": "YIcy", "\u0439": "jcy", "\u0419": "Jcy", "\u0458": "jsercy", "\u0408": "Jsercy", "\u043A": "kcy", "\u041A": "Kcy", "\u045C": "kjcy", "\u040C": "KJcy", "\u043B": "lcy", "\u041B": "Lcy", "\u0459": "ljcy", "\u0409": "LJcy", "\u043C": "mcy", "\u041C": "Mcy", "\u043D": "ncy", "\u041D": "Ncy", "\u045A": "njcy", "\u040A": "NJcy", "\u043E": "ocy", "\u041E": "Ocy", "\u043F": "pcy", "\u041F": "Pcy", "\u0440": "rcy", "\u0420": "Rcy", "\u0441": "scy", "\u0421": "Scy", "\u0442": "tcy", "\u0422": "Tcy", "\u045B": "tshcy", "\u040B": "TSHcy", "\u0443": "ucy", "\u0423": "Ucy", "\u045E": "ubrcy", "\u040E": "Ubrcy", "\u0444": "fcy", "\u0424": "Fcy", "\u0445": "khcy", "\u0425": "KHcy", "\u0446": "tscy", "\u0426": "TScy", "\u0447": "chcy", "\u0427": "CHcy", "\u045F": "dzcy", "\u040F": "DZcy", "\u0448": "shcy", "\u0428": "SHcy", "\u0449": "shchcy", "\u0429": "SHCHcy", "\u044A": "hardcy", "\u042A": "HARDcy", "\u044B": "ycy", "\u042B": "Ycy", "\u044C": "softcy", "\u042C": "SOFTcy", "\u044D": "ecy", "\u042D": "Ecy", "\u044E": "yucy", "\u042E": "YUcy", "\u044F": "yacy", "\u042F": "YAcy", "\u2135": "aleph", "\u2136": "beth", "\u2137": "gimel", "\u2138": "daleth" };
|
|
var regexEscape = /["&'<>`]/g;
|
|
var escapeMap = {
|
|
'"': """,
|
|
"&": "&",
|
|
"'": "'",
|
|
"<": "<",
|
|
">": ">",
|
|
"`": "`"
|
|
};
|
|
var regexInvalidEntity = /&#(?:[xX][^a-fA-F0-9]|[^0-9xX])/;
|
|
var regexInvalidRawCodePoint = /[\0-\x08\x0B\x0E-\x1F\x7F-\x9F\uFDD0-\uFDEF\uFFFE\uFFFF]|[\uD83F\uD87F\uD8BF\uD8FF\uD93F\uD97F\uD9BF\uD9FF\uDA3F\uDA7F\uDABF\uDAFF\uDB3F\uDB7F\uDBBF\uDBFF][\uDFFE\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
|
|
var regexDecode = /&(CounterClockwiseContourIntegral|DoubleLongLeftRightArrow|ClockwiseContourIntegral|NotNestedGreaterGreater|NotSquareSupersetEqual|DiacriticalDoubleAcute|NotRightTriangleEqual|NotSucceedsSlantEqual|NotPrecedesSlantEqual|CloseCurlyDoubleQuote|NegativeVeryThinSpace|DoubleContourIntegral|FilledVerySmallSquare|CapitalDifferentialD|OpenCurlyDoubleQuote|EmptyVerySmallSquare|NestedGreaterGreater|DoubleLongRightArrow|NotLeftTriangleEqual|NotGreaterSlantEqual|ReverseUpEquilibrium|DoubleLeftRightArrow|NotSquareSubsetEqual|NotDoubleVerticalBar|RightArrowLeftArrow|NotGreaterFullEqual|NotRightTriangleBar|SquareSupersetEqual|DownLeftRightVector|DoubleLongLeftArrow|leftrightsquigarrow|LeftArrowRightArrow|NegativeMediumSpace|blacktriangleright|RightDownVectorBar|PrecedesSlantEqual|RightDoubleBracket|SucceedsSlantEqual|NotLeftTriangleBar|RightTriangleEqual|SquareIntersection|RightDownTeeVector|ReverseEquilibrium|NegativeThickSpace|longleftrightarrow|Longleftrightarrow|LongLeftRightArrow|DownRightTeeVector|DownRightVectorBar|GreaterSlantEqual|SquareSubsetEqual|LeftDownVectorBar|LeftDoubleBracket|VerticalSeparator|rightleftharpoons|NotGreaterGreater|NotSquareSuperset|blacktriangleleft|blacktriangledown|NegativeThinSpace|LeftDownTeeVector|NotLessSlantEqual|leftrightharpoons|DoubleUpDownArrow|DoubleVerticalBar|LeftTriangleEqual|FilledSmallSquare|twoheadrightarrow|NotNestedLessLess|DownLeftTeeVector|DownLeftVectorBar|RightAngleBracket|NotTildeFullEqual|NotReverseElement|RightUpDownVector|DiacriticalTilde|NotSucceedsTilde|circlearrowright|NotPrecedesEqual|rightharpoondown|DoubleRightArrow|NotSucceedsEqual|NonBreakingSpace|NotRightTriangle|LessEqualGreater|RightUpTeeVector|LeftAngleBracket|GreaterFullEqual|DownArrowUpArrow|RightUpVectorBar|twoheadleftarrow|GreaterEqualLess|downharpoonright|RightTriangleBar|ntrianglerighteq|NotSupersetEqual|LeftUpDownVector|DiacriticalAcute|rightrightarrows|vartriangleright|UpArrowDownArrow|DiacriticalGrave|UnderParenthesis|EmptySmallSquare|LeftUpVectorBar|leftrightarrows|DownRightVector|downharpoonleft|trianglerighteq|ShortRightArrow|OverParenthesis|DoubleLeftArrow|DoubleDownArrow|NotSquareSubset|bigtriangledown|ntrianglelefteq|UpperRightArrow|curvearrowright|vartriangleleft|NotLeftTriangle|nleftrightarrow|LowerRightArrow|NotHumpDownHump|NotGreaterTilde|rightthreetimes|LeftUpTeeVector|NotGreaterEqual|straightepsilon|LeftTriangleBar|rightsquigarrow|ContourIntegral|rightleftarrows|CloseCurlyQuote|RightDownVector|LeftRightVector|nLeftrightarrow|leftharpoondown|circlearrowleft|SquareSuperset|OpenCurlyQuote|hookrightarrow|HorizontalLine|DiacriticalDot|NotLessGreater|ntriangleright|DoubleRightTee|InvisibleComma|InvisibleTimes|LowerLeftArrow|DownLeftVector|NotSubsetEqual|curvearrowleft|trianglelefteq|NotVerticalBar|TildeFullEqual|downdownarrows|NotGreaterLess|RightTeeVector|ZeroWidthSpace|looparrowright|LongRightArrow|doublebarwedge|ShortLeftArrow|ShortDownArrow|RightVectorBar|GreaterGreater|ReverseElement|rightharpoonup|LessSlantEqual|leftthreetimes|upharpoonright|rightarrowtail|LeftDownVector|Longrightarrow|NestedLessLess|UpperLeftArrow|nshortparallel|leftleftarrows|leftrightarrow|Leftrightarrow|LeftRightArrow|longrightarrow|upharpoonleft|RightArrowBar|ApplyFunction|LeftTeeVector|leftarrowtail|NotEqualTilde|varsubsetneqq|varsupsetneqq|RightTeeArrow|SucceedsEqual|SucceedsTilde|LeftVectorBar|SupersetEqual|hookleftarrow|DifferentialD|VerticalTilde|VeryThinSpace|blacktriangle|bigtriangleup|LessFullEqual|divideontimes|leftharpoonup|UpEquilibrium|ntriangleleft|RightTriangle|measuredangle|shortparallel|longleftarrow|Longleftarrow|LongLeftArrow|DoubleLeftTee|Poincareplane|PrecedesEqual|triangleright|DoubleUpArrow|RightUpVector|fallingdotseq|looparrowleft|PrecedesTilde|NotTildeEqual|NotTildeTilde|smallsetminus|Proportional|triangleleft|triangledown|UnderBracket|NotHumpEqual|exponentiale|ExponentialE|NotLessTilde|HilbertSpace|RightCeiling|blacklozenge|varsupsetneq|HumpDownHump|GreaterEqual|VerticalLine|LeftTeeArrow|NotLessEqual|DownTeeArrow|LeftTriangle|varsubsetneq|Intersection|NotCongruent|DownArrowBar|LeftUpVector|LeftArrowBar|risingdotseq|GreaterTilde|RoundImplies|SquareSubset|ShortUpArrow|NotSuperset|quaternions|precnapprox|backepsilon|preccurlyeq|OverBracket|blacksquare|MediumSpace|VerticalBar|circledcirc|circleddash|CircleMinus|CircleTimes|LessGreater|curlyeqprec|curlyeqsucc|diamondsuit|UpDownArrow|Updownarrow|RuleDelayed|Rrightarrow|updownarrow|RightVector|nRightarrow|nrightarrow|eqslantless|LeftCeiling|Equilibrium|SmallCircle|expectation|NotSucceeds|thickapprox|GreaterLess|SquareUnion|NotPrecedes|NotLessLess|straightphi|succnapprox|succcurlyeq|SubsetEqual|sqsupseteq|Proportion|Laplacetrf|ImaginaryI|supsetneqq|NotGreater|gtreqqless|NotElement|ThickSpace|TildeEqual|TildeTilde|Fouriertrf|rmoustache|EqualTilde|eqslantgtr|UnderBrace|LeftVector|UpArrowBar|nLeftarrow|nsubseteqq|subsetneqq|nsupseteqq|nleftarrow|succapprox|lessapprox|UpTeeArrow|upuparrows|curlywedge|lesseqqgtr|varepsilon|varnothing|RightFloor|complement|CirclePlus|sqsubseteq|Lleftarrow|circledast|RightArrow|Rightarrow|rightarrow|lmoustache|Bernoullis|precapprox|mapstoleft|mapstodown|longmapsto|dotsquare|downarrow|DoubleDot|nsubseteq|supsetneq|leftarrow|nsupseteq|subsetneq|ThinSpace|ngeqslant|subseteqq|HumpEqual|NotSubset|triangleq|NotCupCap|lesseqgtr|heartsuit|TripleDot|Leftarrow|Coproduct|Congruent|varpropto|complexes|gvertneqq|LeftArrow|LessTilde|supseteqq|MinusPlus|CircleDot|nleqslant|NotExists|gtreqless|nparallel|UnionPlus|LeftFloor|checkmark|CenterDot|centerdot|Mellintrf|gtrapprox|bigotimes|OverBrace|spadesuit|therefore|pitchfork|rationals|PlusMinus|Backslash|Therefore|DownBreve|backsimeq|backprime|DownArrow|nshortmid|Downarrow|lvertneqq|eqvparsl|imagline|imagpart|infintie|integers|Integral|intercal|LessLess|Uarrocir|intlarhk|sqsupset|angmsdaf|sqsubset|llcorner|vartheta|cupbrcap|lnapprox|Superset|SuchThat|succnsim|succneqq|angmsdag|biguplus|curlyvee|trpezium|Succeeds|NotTilde|bigwedge|angmsdah|angrtvbd|triminus|cwconint|fpartint|lrcorner|smeparsl|subseteq|urcorner|lurdshar|laemptyv|DDotrahd|approxeq|ldrushar|awconint|mapstoup|backcong|shortmid|triangle|geqslant|gesdotol|timesbar|circledR|circledS|setminus|multimap|naturals|scpolint|ncongdot|RightTee|boxminus|gnapprox|boxtimes|andslope|thicksim|angmsdaa|varsigma|cirfnint|rtriltri|angmsdab|rppolint|angmsdac|barwedge|drbkarow|clubsuit|thetasym|bsolhsub|capbrcup|dzigrarr|doteqdot|DotEqual|dotminus|UnderBar|NotEqual|realpart|otimesas|ulcorner|hksearow|hkswarow|parallel|PartialD|elinters|emptyset|plusacir|bbrktbrk|angmsdad|pointint|bigoplus|angmsdae|Precedes|bigsqcup|varkappa|notindot|supseteq|precneqq|precnsim|profalar|profline|profsurf|leqslant|lesdotor|raemptyv|subplus|notnivb|notnivc|subrarr|zigrarr|vzigzag|submult|subedot|Element|between|cirscir|larrbfs|larrsim|lotimes|lbrksld|lbrkslu|lozenge|ldrdhar|dbkarow|bigcirc|epsilon|simrarr|simplus|ltquest|Epsilon|luruhar|gtquest|maltese|npolint|eqcolon|npreceq|bigodot|ddagger|gtrless|bnequiv|harrcir|ddotseq|equivDD|backsim|demptyv|nsqsube|nsqsupe|Upsilon|nsubset|upsilon|minusdu|nsucceq|swarrow|nsupset|coloneq|searrow|boxplus|napprox|natural|asympeq|alefsym|congdot|nearrow|bigstar|diamond|supplus|tritime|LeftTee|nvinfin|triplus|NewLine|nvltrie|nvrtrie|nwarrow|nexists|Diamond|ruluhar|Implies|supmult|angzarr|suplarr|suphsub|questeq|because|digamma|Because|olcross|bemptyv|omicron|Omicron|rotimes|NoBreak|intprod|angrtvb|orderof|uwangle|suphsol|lesdoto|orslope|DownTee|realine|cudarrl|rdldhar|OverBar|supedot|lessdot|supdsub|topfork|succsim|rbrkslu|rbrksld|pertenk|cudarrr|isindot|planckh|lessgtr|pluscir|gesdoto|plussim|plustwo|lesssim|cularrp|rarrsim|Cayleys|notinva|notinvb|notinvc|UpArrow|Uparrow|uparrow|NotLess|dwangle|precsim|Product|curarrm|Cconint|dotplus|rarrbfs|ccupssm|Cedilla|cemptyv|notniva|quatint|frac35|frac38|frac45|frac56|frac58|frac78|tridot|xoplus|gacute|gammad|Gammad|lfisht|lfloor|bigcup|sqsupe|gbreve|Gbreve|lharul|sqsube|sqcups|Gcedil|apacir|llhard|lmidot|Lmidot|lmoust|andand|sqcaps|approx|Abreve|spades|circeq|tprime|divide|topcir|Assign|topbot|gesdot|divonx|xuplus|timesd|gesles|atilde|solbar|SOFTcy|loplus|timesb|lowast|lowbar|dlcorn|dlcrop|softcy|dollar|lparlt|thksim|lrhard|Atilde|lsaquo|smashp|bigvee|thinsp|wreath|bkarow|lsquor|lstrok|Lstrok|lthree|ltimes|ltlarr|DotDot|simdot|ltrPar|weierp|xsqcup|angmsd|sigmav|sigmaf|zeetrf|Zcaron|zcaron|mapsto|vsupne|thetav|cirmid|marker|mcomma|Zacute|vsubnE|there4|gtlPar|vsubne|bottom|gtrarr|SHCHcy|shchcy|midast|midcir|middot|minusb|minusd|gtrdot|bowtie|sfrown|mnplus|models|colone|seswar|Colone|mstpos|searhk|gtrsim|nacute|Nacute|boxbox|telrec|hairsp|Tcedil|nbumpe|scnsim|ncaron|Ncaron|ncedil|Ncedil|hamilt|Scedil|nearhk|hardcy|HARDcy|tcedil|Tcaron|commat|nequiv|nesear|tcaron|target|hearts|nexist|varrho|scedil|Scaron|scaron|hellip|Sacute|sacute|hercon|swnwar|compfn|rtimes|rthree|rsquor|rsaquo|zacute|wedgeq|homtht|barvee|barwed|Barwed|rpargt|horbar|conint|swarhk|roplus|nltrie|hslash|hstrok|Hstrok|rmoust|Conint|bprime|hybull|hyphen|iacute|Iacute|supsup|supsub|supsim|varphi|coprod|brvbar|agrave|Supset|supset|igrave|Igrave|notinE|Agrave|iiiint|iinfin|copysr|wedbar|Verbar|vangrt|becaus|incare|verbar|inodot|bullet|drcorn|intcal|drcrop|cularr|vellip|Utilde|bumpeq|cupcap|dstrok|Dstrok|CupCap|cupcup|cupdot|eacute|Eacute|supdot|iquest|easter|ecaron|Ecaron|ecolon|isinsv|utilde|itilde|Itilde|curarr|succeq|Bumpeq|cacute|ulcrop|nparsl|Cacute|nprcue|egrave|Egrave|nrarrc|nrarrw|subsup|subsub|nrtrie|jsercy|nsccue|Jsercy|kappav|kcedil|Kcedil|subsim|ulcorn|nsimeq|egsdot|veebar|kgreen|capand|elsdot|Subset|subset|curren|aacute|lacute|Lacute|emptyv|ntilde|Ntilde|lagran|lambda|Lambda|capcap|Ugrave|langle|subdot|emsp13|numero|emsp14|nvdash|nvDash|nVdash|nVDash|ugrave|ufisht|nvHarr|larrfs|nvlArr|larrhk|larrlp|larrpl|nvrArr|Udblac|nwarhk|larrtl|nwnear|oacute|Oacute|latail|lAtail|sstarf|lbrace|odblac|Odblac|lbrack|udblac|odsold|eparsl|lcaron|Lcaron|ograve|Ograve|lcedil|Lcedil|Aacute|ssmile|ssetmn|squarf|ldquor|capcup|ominus|cylcty|rharul|eqcirc|dagger|rfloor|rfisht|Dagger|daleth|equals|origof|capdot|equest|dcaron|Dcaron|rdquor|oslash|Oslash|otilde|Otilde|otimes|Otimes|urcrop|Ubreve|ubreve|Yacute|Uacute|uacute|Rcedil|rcedil|urcorn|parsim|Rcaron|Vdashl|rcaron|Tstrok|percnt|period|permil|Exists|yacute|rbrack|rbrace|phmmat|ccaron|Ccaron|planck|ccedil|plankv|tstrok|female|plusdo|plusdu|ffilig|plusmn|ffllig|Ccedil|rAtail|dfisht|bernou|ratail|Rarrtl|rarrtl|angsph|rarrpl|rarrlp|rarrhk|xwedge|xotime|forall|ForAll|Vvdash|vsupnE|preceq|bigcap|frac12|frac13|frac14|primes|rarrfs|prnsim|frac15|Square|frac16|square|lesdot|frac18|frac23|propto|prurel|rarrap|rangle|puncsp|frac25|Racute|qprime|racute|lesges|frac34|abreve|AElig|eqsim|utdot|setmn|urtri|Equal|Uring|seArr|uring|searr|dashv|Dashv|mumap|nabla|iogon|Iogon|sdote|sdotb|scsim|napid|napos|equiv|natur|Acirc|dblac|erarr|nbump|iprod|erDot|ucirc|awint|esdot|angrt|ncong|isinE|scnap|Scirc|scirc|ndash|isins|Ubrcy|nearr|neArr|isinv|nedot|ubrcy|acute|Ycirc|iukcy|Iukcy|xutri|nesim|caret|jcirc|Jcirc|caron|twixt|ddarr|sccue|exist|jmath|sbquo|ngeqq|angst|ccaps|lceil|ngsim|UpTee|delta|Delta|rtrif|nharr|nhArr|nhpar|rtrie|jukcy|Jukcy|kappa|rsquo|Kappa|nlarr|nlArr|TSHcy|rrarr|aogon|Aogon|fflig|xrarr|tshcy|ccirc|nleqq|filig|upsih|nless|dharl|nlsim|fjlig|ropar|nltri|dharr|robrk|roarr|fllig|fltns|roang|rnmid|subnE|subne|lAarr|trisb|Ccirc|acirc|ccups|blank|VDash|forkv|Vdash|langd|cedil|blk12|blk14|laquo|strns|diams|notin|vDash|larrb|blk34|block|disin|uplus|vdash|vBarv|aelig|starf|Wedge|check|xrArr|lates|lbarr|lBarr|notni|lbbrk|bcong|frasl|lbrke|frown|vrtri|vprop|vnsup|gamma|Gamma|wedge|xodot|bdquo|srarr|doteq|ldquo|boxdl|boxdL|gcirc|Gcirc|boxDl|boxDL|boxdr|boxdR|boxDr|TRADE|trade|rlhar|boxDR|vnsub|npart|vltri|rlarr|boxhd|boxhD|nprec|gescc|nrarr|nrArr|boxHd|boxHD|boxhu|boxhU|nrtri|boxHu|clubs|boxHU|times|colon|Colon|gimel|xlArr|Tilde|nsime|tilde|nsmid|nspar|THORN|thorn|xlarr|nsube|nsubE|thkap|xhArr|comma|nsucc|boxul|boxuL|nsupe|nsupE|gneqq|gnsim|boxUl|boxUL|grave|boxur|boxuR|boxUr|boxUR|lescc|angle|bepsi|boxvh|varpi|boxvH|numsp|Theta|gsime|gsiml|theta|boxVh|boxVH|boxvl|gtcir|gtdot|boxvL|boxVl|boxVL|crarr|cross|Cross|nvsim|boxvr|nwarr|nwArr|sqsup|dtdot|Uogon|lhard|lharu|dtrif|ocirc|Ocirc|lhblk|duarr|odash|sqsub|Hacek|sqcup|llarr|duhar|oelig|OElig|ofcir|boxvR|uogon|lltri|boxVr|csube|uuarr|ohbar|csupe|ctdot|olarr|olcir|harrw|oline|sqcap|omacr|Omacr|omega|Omega|boxVR|aleph|lneqq|lnsim|loang|loarr|rharu|lobrk|hcirc|operp|oplus|rhard|Hcirc|orarr|Union|order|ecirc|Ecirc|cuepr|szlig|cuesc|breve|reals|eDDot|Breve|hoarr|lopar|utrif|rdquo|Umacr|umacr|efDot|swArr|ultri|alpha|rceil|ovbar|swarr|Wcirc|wcirc|smtes|smile|bsemi|lrarr|aring|parsl|lrhar|bsime|uhblk|lrtri|cupor|Aring|uharr|uharl|slarr|rbrke|bsolb|lsime|rbbrk|RBarr|lsimg|phone|rBarr|rbarr|icirc|lsquo|Icirc|emacr|Emacr|ratio|simne|plusb|simlE|simgE|simeq|pluse|ltcir|ltdot|empty|xharr|xdtri|iexcl|Alpha|ltrie|rarrw|pound|ltrif|xcirc|bumpe|prcue|bumpE|asymp|amacr|cuvee|Sigma|sigma|iiint|udhar|iiota|ijlig|IJlig|supnE|imacr|Imacr|prime|Prime|image|prnap|eogon|Eogon|rarrc|mdash|mDDot|cuwed|imath|supne|imped|Amacr|udarr|prsim|micro|rarrb|cwint|raquo|infin|eplus|range|rangd|Ucirc|radic|minus|amalg|veeeq|rAarr|epsiv|ycirc|quest|sharp|quot|zwnj|Qscr|race|qscr|Qopf|qopf|qint|rang|Rang|Zscr|zscr|Zopf|zopf|rarr|rArr|Rarr|Pscr|pscr|prop|prod|prnE|prec|ZHcy|zhcy|prap|Zeta|zeta|Popf|popf|Zdot|plus|zdot|Yuml|yuml|phiv|YUcy|yucy|Yscr|yscr|perp|Yopf|yopf|part|para|YIcy|Ouml|rcub|yicy|YAcy|rdca|ouml|osol|Oscr|rdsh|yacy|real|oscr|xvee|andd|rect|andv|Xscr|oror|ordm|ordf|xscr|ange|aopf|Aopf|rHar|Xopf|opar|Oopf|xopf|xnis|rhov|oopf|omid|xmap|oint|apid|apos|ogon|ascr|Ascr|odot|odiv|xcup|xcap|ocir|oast|nvlt|nvle|nvgt|nvge|nvap|Wscr|wscr|auml|ntlg|ntgl|nsup|nsub|nsim|Nscr|nscr|nsce|Wopf|ring|npre|wopf|npar|Auml|Barv|bbrk|Nopf|nopf|nmid|nLtv|beta|ropf|Ropf|Beta|beth|nles|rpar|nleq|bnot|bNot|nldr|NJcy|rscr|Rscr|Vscr|vscr|rsqb|njcy|bopf|nisd|Bopf|rtri|Vopf|nGtv|ngtr|vopf|boxh|boxH|boxv|nges|ngeq|boxV|bscr|scap|Bscr|bsim|Vert|vert|bsol|bull|bump|caps|cdot|ncup|scnE|ncap|nbsp|napE|Cdot|cent|sdot|Vbar|nang|vBar|chcy|Mscr|mscr|sect|semi|CHcy|Mopf|mopf|sext|circ|cire|mldr|mlcp|cirE|comp|shcy|SHcy|vArr|varr|cong|copf|Copf|copy|COPY|malt|male|macr|lvnE|cscr|ltri|sime|ltcc|simg|Cscr|siml|csub|Uuml|lsqb|lsim|uuml|csup|Lscr|lscr|utri|smid|lpar|cups|smte|lozf|darr|Lopf|Uscr|solb|lopf|sopf|Sopf|lneq|uscr|spar|dArr|lnap|Darr|dash|Sqrt|LJcy|ljcy|lHar|dHar|Upsi|upsi|diam|lesg|djcy|DJcy|leqq|dopf|Dopf|dscr|Dscr|dscy|ldsh|ldca|squf|DScy|sscr|Sscr|dsol|lcub|late|star|Star|Uopf|Larr|lArr|larr|uopf|dtri|dzcy|sube|subE|Lang|lang|Kscr|kscr|Kopf|kopf|KJcy|kjcy|KHcy|khcy|DZcy|ecir|edot|eDot|Jscr|jscr|succ|Jopf|jopf|Edot|uHar|emsp|ensp|Iuml|iuml|eopf|isin|Iscr|iscr|Eopf|epar|sung|epsi|escr|sup1|sup2|sup3|Iota|iota|supe|supE|Iopf|iopf|IOcy|iocy|Escr|esim|Esim|imof|Uarr|QUOT|uArr|uarr|euml|IEcy|iecy|Idot|Euml|euro|excl|Hscr|hscr|Hopf|hopf|TScy|tscy|Tscr|hbar|tscr|flat|tbrk|fnof|hArr|harr|half|fopf|Fopf|tdot|gvnE|fork|trie|gtcc|fscr|Fscr|gdot|gsim|Gscr|gscr|Gopf|gopf|gneq|Gdot|tosa|gnap|Topf|topf|geqq|toea|GJcy|gjcy|tint|gesl|mid|Sfr|ggg|top|ges|gla|glE|glj|geq|gne|gEl|gel|gnE|Gcy|gcy|gap|Tfr|tfr|Tcy|tcy|Hat|Tau|Ffr|tau|Tab|hfr|Hfr|ffr|Fcy|fcy|icy|Icy|iff|ETH|eth|ifr|Ifr|Eta|eta|int|Int|Sup|sup|ucy|Ucy|Sum|sum|jcy|ENG|ufr|Ufr|eng|Jcy|jfr|els|ell|egs|Efr|efr|Jfr|uml|kcy|Kcy|Ecy|ecy|kfr|Kfr|lap|Sub|sub|lat|lcy|Lcy|leg|Dot|dot|lEg|leq|les|squ|div|die|lfr|Lfr|lgE|Dfr|dfr|Del|deg|Dcy|dcy|lne|lnE|sol|loz|smt|Cup|lrm|cup|lsh|Lsh|sim|shy|map|Map|mcy|Mcy|mfr|Mfr|mho|gfr|Gfr|sfr|cir|Chi|chi|nap|Cfr|vcy|Vcy|cfr|Scy|scy|ncy|Ncy|vee|Vee|Cap|cap|nfr|scE|sce|Nfr|nge|ngE|nGg|vfr|Vfr|ngt|bot|nGt|nis|niv|Rsh|rsh|nle|nlE|bne|Bfr|bfr|nLl|nlt|nLt|Bcy|bcy|not|Not|rlm|wfr|Wfr|npr|nsc|num|ocy|ast|Ocy|ofr|xfr|Xfr|Ofr|ogt|ohm|apE|olt|Rho|ape|rho|Rfr|rfr|ord|REG|ang|reg|orv|And|and|AMP|Rcy|amp|Afr|ycy|Ycy|yen|yfr|Yfr|rcy|par|pcy|Pcy|pfr|Pfr|phi|Phi|afr|Acy|acy|zcy|Zcy|piv|acE|acd|zfr|Zfr|pre|prE|psi|Psi|qfr|Qfr|zwj|Or|ge|Gg|gt|gg|el|oS|lt|Lt|LT|Re|lg|gl|eg|ne|Im|it|le|DD|wp|wr|nu|Nu|dd|lE|Sc|sc|pi|Pi|ee|af|ll|Ll|rx|gE|xi|pm|Xi|ic|pr|Pr|in|ni|mp|mu|ac|Mu|or|ap|Gt|GT|ii);|&(Aacute|Agrave|Atilde|Ccedil|Eacute|Egrave|Iacute|Igrave|Ntilde|Oacute|Ograve|Oslash|Otilde|Uacute|Ugrave|Yacute|aacute|agrave|atilde|brvbar|ccedil|curren|divide|eacute|egrave|frac12|frac14|frac34|iacute|igrave|iquest|middot|ntilde|oacute|ograve|oslash|otilde|plusmn|uacute|ugrave|yacute|AElig|Acirc|Aring|Ecirc|Icirc|Ocirc|THORN|Ucirc|acirc|acute|aelig|aring|cedil|ecirc|icirc|iexcl|laquo|micro|ocirc|pound|raquo|szlig|thorn|times|ucirc|Auml|COPY|Euml|Iuml|Ouml|QUOT|Uuml|auml|cent|copy|euml|iuml|macr|nbsp|ordf|ordm|ouml|para|quot|sect|sup1|sup2|sup3|uuml|yuml|AMP|ETH|REG|amp|deg|eth|not|reg|shy|uml|yen|GT|LT|gt|lt)(?!;)([=a-zA-Z0-9]?)|&#([0-9]+)(;?)|&#[xX]([a-fA-F0-9]+)(;?)|&([0-9a-zA-Z]+)/g;
|
|
var decodeMap = { "aacute": "\xE1", "Aacute": "\xC1", "abreve": "\u0103", "Abreve": "\u0102", "ac": "\u223E", "acd": "\u223F", "acE": "\u223E\u0333", "acirc": "\xE2", "Acirc": "\xC2", "acute": "\xB4", "acy": "\u0430", "Acy": "\u0410", "aelig": "\xE6", "AElig": "\xC6", "af": "\u2061", "afr": "\u{1D51E}", "Afr": "\u{1D504}", "agrave": "\xE0", "Agrave": "\xC0", "alefsym": "\u2135", "aleph": "\u2135", "alpha": "\u03B1", "Alpha": "\u0391", "amacr": "\u0101", "Amacr": "\u0100", "amalg": "\u2A3F", "amp": "&", "AMP": "&", "and": "\u2227", "And": "\u2A53", "andand": "\u2A55", "andd": "\u2A5C", "andslope": "\u2A58", "andv": "\u2A5A", "ang": "\u2220", "ange": "\u29A4", "angle": "\u2220", "angmsd": "\u2221", "angmsdaa": "\u29A8", "angmsdab": "\u29A9", "angmsdac": "\u29AA", "angmsdad": "\u29AB", "angmsdae": "\u29AC", "angmsdaf": "\u29AD", "angmsdag": "\u29AE", "angmsdah": "\u29AF", "angrt": "\u221F", "angrtvb": "\u22BE", "angrtvbd": "\u299D", "angsph": "\u2222", "angst": "\xC5", "angzarr": "\u237C", "aogon": "\u0105", "Aogon": "\u0104", "aopf": "\u{1D552}", "Aopf": "\u{1D538}", "ap": "\u2248", "apacir": "\u2A6F", "ape": "\u224A", "apE": "\u2A70", "apid": "\u224B", "apos": "'", "ApplyFunction": "\u2061", "approx": "\u2248", "approxeq": "\u224A", "aring": "\xE5", "Aring": "\xC5", "ascr": "\u{1D4B6}", "Ascr": "\u{1D49C}", "Assign": "\u2254", "ast": "*", "asymp": "\u2248", "asympeq": "\u224D", "atilde": "\xE3", "Atilde": "\xC3", "auml": "\xE4", "Auml": "\xC4", "awconint": "\u2233", "awint": "\u2A11", "backcong": "\u224C", "backepsilon": "\u03F6", "backprime": "\u2035", "backsim": "\u223D", "backsimeq": "\u22CD", "Backslash": "\u2216", "Barv": "\u2AE7", "barvee": "\u22BD", "barwed": "\u2305", "Barwed": "\u2306", "barwedge": "\u2305", "bbrk": "\u23B5", "bbrktbrk": "\u23B6", "bcong": "\u224C", "bcy": "\u0431", "Bcy": "\u0411", "bdquo": "\u201E", "becaus": "\u2235", "because": "\u2235", "Because": "\u2235", "bemptyv": "\u29B0", "bepsi": "\u03F6", "bernou": "\u212C", "Bernoullis": "\u212C", "beta": "\u03B2", "Beta": "\u0392", "beth": "\u2136", "between": "\u226C", "bfr": "\u{1D51F}", "Bfr": "\u{1D505}", "bigcap": "\u22C2", "bigcirc": "\u25EF", "bigcup": "\u22C3", "bigodot": "\u2A00", "bigoplus": "\u2A01", "bigotimes": "\u2A02", "bigsqcup": "\u2A06", "bigstar": "\u2605", "bigtriangledown": "\u25BD", "bigtriangleup": "\u25B3", "biguplus": "\u2A04", "bigvee": "\u22C1", "bigwedge": "\u22C0", "bkarow": "\u290D", "blacklozenge": "\u29EB", "blacksquare": "\u25AA", "blacktriangle": "\u25B4", "blacktriangledown": "\u25BE", "blacktriangleleft": "\u25C2", "blacktriangleright": "\u25B8", "blank": "\u2423", "blk12": "\u2592", "blk14": "\u2591", "blk34": "\u2593", "block": "\u2588", "bne": "=\u20E5", "bnequiv": "\u2261\u20E5", "bnot": "\u2310", "bNot": "\u2AED", "bopf": "\u{1D553}", "Bopf": "\u{1D539}", "bot": "\u22A5", "bottom": "\u22A5", "bowtie": "\u22C8", "boxbox": "\u29C9", "boxdl": "\u2510", "boxdL": "\u2555", "boxDl": "\u2556", "boxDL": "\u2557", "boxdr": "\u250C", "boxdR": "\u2552", "boxDr": "\u2553", "boxDR": "\u2554", "boxh": "\u2500", "boxH": "\u2550", "boxhd": "\u252C", "boxhD": "\u2565", "boxHd": "\u2564", "boxHD": "\u2566", "boxhu": "\u2534", "boxhU": "\u2568", "boxHu": "\u2567", "boxHU": "\u2569", "boxminus": "\u229F", "boxplus": "\u229E", "boxtimes": "\u22A0", "boxul": "\u2518", "boxuL": "\u255B", "boxUl": "\u255C", "boxUL": "\u255D", "boxur": "\u2514", "boxuR": "\u2558", "boxUr": "\u2559", "boxUR": "\u255A", "boxv": "\u2502", "boxV": "\u2551", "boxvh": "\u253C", "boxvH": "\u256A", "boxVh": "\u256B", "boxVH": "\u256C", "boxvl": "\u2524", "boxvL": "\u2561", "boxVl": "\u2562", "boxVL": "\u2563", "boxvr": "\u251C", "boxvR": "\u255E", "boxVr": "\u255F", "boxVR": "\u2560", "bprime": "\u2035", "breve": "\u02D8", "Breve": "\u02D8", "brvbar": "\xA6", "bscr": "\u{1D4B7}", "Bscr": "\u212C", "bsemi": "\u204F", "bsim": "\u223D", "bsime": "\u22CD", "bsol": "\\", "bsolb": "\u29C5", "bsolhsub": "\u27C8", "bull": "\u2022", "bullet": "\u2022", "bump": "\u224E", "bumpe": "\u224F", "bumpE": "\u2AAE", "bumpeq": "\u224F", "Bumpeq": "\u224E", "cacute": "\u0107", "Cacute": "\u0106", "cap": "\u2229", "Cap": "\u22D2", "capand": "\u2A44", "capbrcup": "\u2A49", "capcap": "\u2A4B", "capcup": "\u2A47", "capdot": "\u2A40", "CapitalDifferentialD": "\u2145", "caps": "\u2229\uFE00", "caret": "\u2041", "caron": "\u02C7", "Cayleys": "\u212D", "ccaps": "\u2A4D", "ccaron": "\u010D", "Ccaron": "\u010C", "ccedil": "\xE7", "Ccedil": "\xC7", "ccirc": "\u0109", "Ccirc": "\u0108", "Cconint": "\u2230", "ccups": "\u2A4C", "ccupssm": "\u2A50", "cdot": "\u010B", "Cdot": "\u010A", "cedil": "\xB8", "Cedilla": "\xB8", "cemptyv": "\u29B2", "cent": "\xA2", "centerdot": "\xB7", "CenterDot": "\xB7", "cfr": "\u{1D520}", "Cfr": "\u212D", "chcy": "\u0447", "CHcy": "\u0427", "check": "\u2713", "checkmark": "\u2713", "chi": "\u03C7", "Chi": "\u03A7", "cir": "\u25CB", "circ": "\u02C6", "circeq": "\u2257", "circlearrowleft": "\u21BA", "circlearrowright": "\u21BB", "circledast": "\u229B", "circledcirc": "\u229A", "circleddash": "\u229D", "CircleDot": "\u2299", "circledR": "\xAE", "circledS": "\u24C8", "CircleMinus": "\u2296", "CirclePlus": "\u2295", "CircleTimes": "\u2297", "cire": "\u2257", "cirE": "\u29C3", "cirfnint": "\u2A10", "cirmid": "\u2AEF", "cirscir": "\u29C2", "ClockwiseContourIntegral": "\u2232", "CloseCurlyDoubleQuote": "\u201D", "CloseCurlyQuote": "\u2019", "clubs": "\u2663", "clubsuit": "\u2663", "colon": ":", "Colon": "\u2237", "colone": "\u2254", "Colone": "\u2A74", "coloneq": "\u2254", "comma": ",", "commat": "@", "comp": "\u2201", "compfn": "\u2218", "complement": "\u2201", "complexes": "\u2102", "cong": "\u2245", "congdot": "\u2A6D", "Congruent": "\u2261", "conint": "\u222E", "Conint": "\u222F", "ContourIntegral": "\u222E", "copf": "\u{1D554}", "Copf": "\u2102", "coprod": "\u2210", "Coproduct": "\u2210", "copy": "\xA9", "COPY": "\xA9", "copysr": "\u2117", "CounterClockwiseContourIntegral": "\u2233", "crarr": "\u21B5", "cross": "\u2717", "Cross": "\u2A2F", "cscr": "\u{1D4B8}", "Cscr": "\u{1D49E}", "csub": "\u2ACF", "csube": "\u2AD1", "csup": "\u2AD0", "csupe": "\u2AD2", "ctdot": "\u22EF", "cudarrl": "\u2938", "cudarrr": "\u2935", "cuepr": "\u22DE", "cuesc": "\u22DF", "cularr": "\u21B6", "cularrp": "\u293D", "cup": "\u222A", "Cup": "\u22D3", "cupbrcap": "\u2A48", "cupcap": "\u2A46", "CupCap": "\u224D", "cupcup": "\u2A4A", "cupdot": "\u228D", "cupor": "\u2A45", "cups": "\u222A\uFE00", "curarr": "\u21B7", "curarrm": "\u293C", "curlyeqprec": "\u22DE", "curlyeqsucc": "\u22DF", "curlyvee": "\u22CE", "curlywedge": "\u22CF", "curren": "\xA4", "curvearrowleft": "\u21B6", "curvearrowright": "\u21B7", "cuvee": "\u22CE", "cuwed": "\u22CF", "cwconint": "\u2232", "cwint": "\u2231", "cylcty": "\u232D", "dagger": "\u2020", "Dagger": "\u2021", "daleth": "\u2138", "darr": "\u2193", "dArr": "\u21D3", "Darr": "\u21A1", "dash": "\u2010", "dashv": "\u22A3", "Dashv": "\u2AE4", "dbkarow": "\u290F", "dblac": "\u02DD", "dcaron": "\u010F", "Dcaron": "\u010E", "dcy": "\u0434", "Dcy": "\u0414", "dd": "\u2146", "DD": "\u2145", "ddagger": "\u2021", "ddarr": "\u21CA", "DDotrahd": "\u2911", "ddotseq": "\u2A77", "deg": "\xB0", "Del": "\u2207", "delta": "\u03B4", "Delta": "\u0394", "demptyv": "\u29B1", "dfisht": "\u297F", "dfr": "\u{1D521}", "Dfr": "\u{1D507}", "dHar": "\u2965", "dharl": "\u21C3", "dharr": "\u21C2", "DiacriticalAcute": "\xB4", "DiacriticalDot": "\u02D9", "DiacriticalDoubleAcute": "\u02DD", "DiacriticalGrave": "`", "DiacriticalTilde": "\u02DC", "diam": "\u22C4", "diamond": "\u22C4", "Diamond": "\u22C4", "diamondsuit": "\u2666", "diams": "\u2666", "die": "\xA8", "DifferentialD": "\u2146", "digamma": "\u03DD", "disin": "\u22F2", "div": "\xF7", "divide": "\xF7", "divideontimes": "\u22C7", "divonx": "\u22C7", "djcy": "\u0452", "DJcy": "\u0402", "dlcorn": "\u231E", "dlcrop": "\u230D", "dollar": "$", "dopf": "\u{1D555}", "Dopf": "\u{1D53B}", "dot": "\u02D9", "Dot": "\xA8", "DotDot": "\u20DC", "doteq": "\u2250", "doteqdot": "\u2251", "DotEqual": "\u2250", "dotminus": "\u2238", "dotplus": "\u2214", "dotsquare": "\u22A1", "doublebarwedge": "\u2306", "DoubleContourIntegral": "\u222F", "DoubleDot": "\xA8", "DoubleDownArrow": "\u21D3", "DoubleLeftArrow": "\u21D0", "DoubleLeftRightArrow": "\u21D4", "DoubleLeftTee": "\u2AE4", "DoubleLongLeftArrow": "\u27F8", "DoubleLongLeftRightArrow": "\u27FA", "DoubleLongRightArrow": "\u27F9", "DoubleRightArrow": "\u21D2", "DoubleRightTee": "\u22A8", "DoubleUpArrow": "\u21D1", "DoubleUpDownArrow": "\u21D5", "DoubleVerticalBar": "\u2225", "downarrow": "\u2193", "Downarrow": "\u21D3", "DownArrow": "\u2193", "DownArrowBar": "\u2913", "DownArrowUpArrow": "\u21F5", "DownBreve": "\u0311", "downdownarrows": "\u21CA", "downharpoonleft": "\u21C3", "downharpoonright": "\u21C2", "DownLeftRightVector": "\u2950", "DownLeftTeeVector": "\u295E", "DownLeftVector": "\u21BD", "DownLeftVectorBar": "\u2956", "DownRightTeeVector": "\u295F", "DownRightVector": "\u21C1", "DownRightVectorBar": "\u2957", "DownTee": "\u22A4", "DownTeeArrow": "\u21A7", "drbkarow": "\u2910", "drcorn": "\u231F", "drcrop": "\u230C", "dscr": "\u{1D4B9}", "Dscr": "\u{1D49F}", "dscy": "\u0455", "DScy": "\u0405", "dsol": "\u29F6", "dstrok": "\u0111", "Dstrok": "\u0110", "dtdot": "\u22F1", "dtri": "\u25BF", "dtrif": "\u25BE", "duarr": "\u21F5", "duhar": "\u296F", "dwangle": "\u29A6", "dzcy": "\u045F", "DZcy": "\u040F", "dzigrarr": "\u27FF", "eacute": "\xE9", "Eacute": "\xC9", "easter": "\u2A6E", "ecaron": "\u011B", "Ecaron": "\u011A", "ecir": "\u2256", "ecirc": "\xEA", "Ecirc": "\xCA", "ecolon": "\u2255", "ecy": "\u044D", "Ecy": "\u042D", "eDDot": "\u2A77", "edot": "\u0117", "eDot": "\u2251", "Edot": "\u0116", "ee": "\u2147", "efDot": "\u2252", "efr": "\u{1D522}", "Efr": "\u{1D508}", "eg": "\u2A9A", "egrave": "\xE8", "Egrave": "\xC8", "egs": "\u2A96", "egsdot": "\u2A98", "el": "\u2A99", "Element": "\u2208", "elinters": "\u23E7", "ell": "\u2113", "els": "\u2A95", "elsdot": "\u2A97", "emacr": "\u0113", "Emacr": "\u0112", "empty": "\u2205", "emptyset": "\u2205", "EmptySmallSquare": "\u25FB", "emptyv": "\u2205", "EmptyVerySmallSquare": "\u25AB", "emsp": "\u2003", "emsp13": "\u2004", "emsp14": "\u2005", "eng": "\u014B", "ENG": "\u014A", "ensp": "\u2002", "eogon": "\u0119", "Eogon": "\u0118", "eopf": "\u{1D556}", "Eopf": "\u{1D53C}", "epar": "\u22D5", "eparsl": "\u29E3", "eplus": "\u2A71", "epsi": "\u03B5", "epsilon": "\u03B5", "Epsilon": "\u0395", "epsiv": "\u03F5", "eqcirc": "\u2256", "eqcolon": "\u2255", "eqsim": "\u2242", "eqslantgtr": "\u2A96", "eqslantless": "\u2A95", "Equal": "\u2A75", "equals": "=", "EqualTilde": "\u2242", "equest": "\u225F", "Equilibrium": "\u21CC", "equiv": "\u2261", "equivDD": "\u2A78", "eqvparsl": "\u29E5", "erarr": "\u2971", "erDot": "\u2253", "escr": "\u212F", "Escr": "\u2130", "esdot": "\u2250", "esim": "\u2242", "Esim": "\u2A73", "eta": "\u03B7", "Eta": "\u0397", "eth": "\xF0", "ETH": "\xD0", "euml": "\xEB", "Euml": "\xCB", "euro": "\u20AC", "excl": "!", "exist": "\u2203", "Exists": "\u2203", "expectation": "\u2130", "exponentiale": "\u2147", "ExponentialE": "\u2147", "fallingdotseq": "\u2252", "fcy": "\u0444", "Fcy": "\u0424", "female": "\u2640", "ffilig": "\uFB03", "fflig": "\uFB00", "ffllig": "\uFB04", "ffr": "\u{1D523}", "Ffr": "\u{1D509}", "filig": "\uFB01", "FilledSmallSquare": "\u25FC", "FilledVerySmallSquare": "\u25AA", "fjlig": "fj", "flat": "\u266D", "fllig": "\uFB02", "fltns": "\u25B1", "fnof": "\u0192", "fopf": "\u{1D557}", "Fopf": "\u{1D53D}", "forall": "\u2200", "ForAll": "\u2200", "fork": "\u22D4", "forkv": "\u2AD9", "Fouriertrf": "\u2131", "fpartint": "\u2A0D", "frac12": "\xBD", "frac13": "\u2153", "frac14": "\xBC", "frac15": "\u2155", "frac16": "\u2159", "frac18": "\u215B", "frac23": "\u2154", "frac25": "\u2156", "frac34": "\xBE", "frac35": "\u2157", "frac38": "\u215C", "frac45": "\u2158", "frac56": "\u215A", "frac58": "\u215D", "frac78": "\u215E", "frasl": "\u2044", "frown": "\u2322", "fscr": "\u{1D4BB}", "Fscr": "\u2131", "gacute": "\u01F5", "gamma": "\u03B3", "Gamma": "\u0393", "gammad": "\u03DD", "Gammad": "\u03DC", "gap": "\u2A86", "gbreve": "\u011F", "Gbreve": "\u011E", "Gcedil": "\u0122", "gcirc": "\u011D", "Gcirc": "\u011C", "gcy": "\u0433", "Gcy": "\u0413", "gdot": "\u0121", "Gdot": "\u0120", "ge": "\u2265", "gE": "\u2267", "gel": "\u22DB", "gEl": "\u2A8C", "geq": "\u2265", "geqq": "\u2267", "geqslant": "\u2A7E", "ges": "\u2A7E", "gescc": "\u2AA9", "gesdot": "\u2A80", "gesdoto": "\u2A82", "gesdotol": "\u2A84", "gesl": "\u22DB\uFE00", "gesles": "\u2A94", "gfr": "\u{1D524}", "Gfr": "\u{1D50A}", "gg": "\u226B", "Gg": "\u22D9", "ggg": "\u22D9", "gimel": "\u2137", "gjcy": "\u0453", "GJcy": "\u0403", "gl": "\u2277", "gla": "\u2AA5", "glE": "\u2A92", "glj": "\u2AA4", "gnap": "\u2A8A", "gnapprox": "\u2A8A", "gne": "\u2A88", "gnE": "\u2269", "gneq": "\u2A88", "gneqq": "\u2269", "gnsim": "\u22E7", "gopf": "\u{1D558}", "Gopf": "\u{1D53E}", "grave": "`", "GreaterEqual": "\u2265", "GreaterEqualLess": "\u22DB", "GreaterFullEqual": "\u2267", "GreaterGreater": "\u2AA2", "GreaterLess": "\u2277", "GreaterSlantEqual": "\u2A7E", "GreaterTilde": "\u2273", "gscr": "\u210A", "Gscr": "\u{1D4A2}", "gsim": "\u2273", "gsime": "\u2A8E", "gsiml": "\u2A90", "gt": ">", "Gt": "\u226B", "GT": ">", "gtcc": "\u2AA7", "gtcir": "\u2A7A", "gtdot": "\u22D7", "gtlPar": "\u2995", "gtquest": "\u2A7C", "gtrapprox": "\u2A86", "gtrarr": "\u2978", "gtrdot": "\u22D7", "gtreqless": "\u22DB", "gtreqqless": "\u2A8C", "gtrless": "\u2277", "gtrsim": "\u2273", "gvertneqq": "\u2269\uFE00", "gvnE": "\u2269\uFE00", "Hacek": "\u02C7", "hairsp": "\u200A", "half": "\xBD", "hamilt": "\u210B", "hardcy": "\u044A", "HARDcy": "\u042A", "harr": "\u2194", "hArr": "\u21D4", "harrcir": "\u2948", "harrw": "\u21AD", "Hat": "^", "hbar": "\u210F", "hcirc": "\u0125", "Hcirc": "\u0124", "hearts": "\u2665", "heartsuit": "\u2665", "hellip": "\u2026", "hercon": "\u22B9", "hfr": "\u{1D525}", "Hfr": "\u210C", "HilbertSpace": "\u210B", "hksearow": "\u2925", "hkswarow": "\u2926", "hoarr": "\u21FF", "homtht": "\u223B", "hookleftarrow": "\u21A9", "hookrightarrow": "\u21AA", "hopf": "\u{1D559}", "Hopf": "\u210D", "horbar": "\u2015", "HorizontalLine": "\u2500", "hscr": "\u{1D4BD}", "Hscr": "\u210B", "hslash": "\u210F", "hstrok": "\u0127", "Hstrok": "\u0126", "HumpDownHump": "\u224E", "HumpEqual": "\u224F", "hybull": "\u2043", "hyphen": "\u2010", "iacute": "\xED", "Iacute": "\xCD", "ic": "\u2063", "icirc": "\xEE", "Icirc": "\xCE", "icy": "\u0438", "Icy": "\u0418", "Idot": "\u0130", "iecy": "\u0435", "IEcy": "\u0415", "iexcl": "\xA1", "iff": "\u21D4", "ifr": "\u{1D526}", "Ifr": "\u2111", "igrave": "\xEC", "Igrave": "\xCC", "ii": "\u2148", "iiiint": "\u2A0C", "iiint": "\u222D", "iinfin": "\u29DC", "iiota": "\u2129", "ijlig": "\u0133", "IJlig": "\u0132", "Im": "\u2111", "imacr": "\u012B", "Imacr": "\u012A", "image": "\u2111", "ImaginaryI": "\u2148", "imagline": "\u2110", "imagpart": "\u2111", "imath": "\u0131", "imof": "\u22B7", "imped": "\u01B5", "Implies": "\u21D2", "in": "\u2208", "incare": "\u2105", "infin": "\u221E", "infintie": "\u29DD", "inodot": "\u0131", "int": "\u222B", "Int": "\u222C", "intcal": "\u22BA", "integers": "\u2124", "Integral": "\u222B", "intercal": "\u22BA", "Intersection": "\u22C2", "intlarhk": "\u2A17", "intprod": "\u2A3C", "InvisibleComma": "\u2063", "InvisibleTimes": "\u2062", "iocy": "\u0451", "IOcy": "\u0401", "iogon": "\u012F", "Iogon": "\u012E", "iopf": "\u{1D55A}", "Iopf": "\u{1D540}", "iota": "\u03B9", "Iota": "\u0399", "iprod": "\u2A3C", "iquest": "\xBF", "iscr": "\u{1D4BE}", "Iscr": "\u2110", "isin": "\u2208", "isindot": "\u22F5", "isinE": "\u22F9", "isins": "\u22F4", "isinsv": "\u22F3", "isinv": "\u2208", "it": "\u2062", "itilde": "\u0129", "Itilde": "\u0128", "iukcy": "\u0456", "Iukcy": "\u0406", "iuml": "\xEF", "Iuml": "\xCF", "jcirc": "\u0135", "Jcirc": "\u0134", "jcy": "\u0439", "Jcy": "\u0419", "jfr": "\u{1D527}", "Jfr": "\u{1D50D}", "jmath": "\u0237", "jopf": "\u{1D55B}", "Jopf": "\u{1D541}", "jscr": "\u{1D4BF}", "Jscr": "\u{1D4A5}", "jsercy": "\u0458", "Jsercy": "\u0408", "jukcy": "\u0454", "Jukcy": "\u0404", "kappa": "\u03BA", "Kappa": "\u039A", "kappav": "\u03F0", "kcedil": "\u0137", "Kcedil": "\u0136", "kcy": "\u043A", "Kcy": "\u041A", "kfr": "\u{1D528}", "Kfr": "\u{1D50E}", "kgreen": "\u0138", "khcy": "\u0445", "KHcy": "\u0425", "kjcy": "\u045C", "KJcy": "\u040C", "kopf": "\u{1D55C}", "Kopf": "\u{1D542}", "kscr": "\u{1D4C0}", "Kscr": "\u{1D4A6}", "lAarr": "\u21DA", "lacute": "\u013A", "Lacute": "\u0139", "laemptyv": "\u29B4", "lagran": "\u2112", "lambda": "\u03BB", "Lambda": "\u039B", "lang": "\u27E8", "Lang": "\u27EA", "langd": "\u2991", "langle": "\u27E8", "lap": "\u2A85", "Laplacetrf": "\u2112", "laquo": "\xAB", "larr": "\u2190", "lArr": "\u21D0", "Larr": "\u219E", "larrb": "\u21E4", "larrbfs": "\u291F", "larrfs": "\u291D", "larrhk": "\u21A9", "larrlp": "\u21AB", "larrpl": "\u2939", "larrsim": "\u2973", "larrtl": "\u21A2", "lat": "\u2AAB", "latail": "\u2919", "lAtail": "\u291B", "late": "\u2AAD", "lates": "\u2AAD\uFE00", "lbarr": "\u290C", "lBarr": "\u290E", "lbbrk": "\u2772", "lbrace": "{", "lbrack": "[", "lbrke": "\u298B", "lbrksld": "\u298F", "lbrkslu": "\u298D", "lcaron": "\u013E", "Lcaron": "\u013D", "lcedil": "\u013C", "Lcedil": "\u013B", "lceil": "\u2308", "lcub": "{", "lcy": "\u043B", "Lcy": "\u041B", "ldca": "\u2936", "ldquo": "\u201C", "ldquor": "\u201E", "ldrdhar": "\u2967", "ldrushar": "\u294B", "ldsh": "\u21B2", "le": "\u2264", "lE": "\u2266", "LeftAngleBracket": "\u27E8", "leftarrow": "\u2190", "Leftarrow": "\u21D0", "LeftArrow": "\u2190", "LeftArrowBar": "\u21E4", "LeftArrowRightArrow": "\u21C6", "leftarrowtail": "\u21A2", "LeftCeiling": "\u2308", "LeftDoubleBracket": "\u27E6", "LeftDownTeeVector": "\u2961", "LeftDownVector": "\u21C3", "LeftDownVectorBar": "\u2959", "LeftFloor": "\u230A", "leftharpoondown": "\u21BD", "leftharpoonup": "\u21BC", "leftleftarrows": "\u21C7", "leftrightarrow": "\u2194", "Leftrightarrow": "\u21D4", "LeftRightArrow": "\u2194", "leftrightarrows": "\u21C6", "leftrightharpoons": "\u21CB", "leftrightsquigarrow": "\u21AD", "LeftRightVector": "\u294E", "LeftTee": "\u22A3", "LeftTeeArrow": "\u21A4", "LeftTeeVector": "\u295A", "leftthreetimes": "\u22CB", "LeftTriangle": "\u22B2", "LeftTriangleBar": "\u29CF", "LeftTriangleEqual": "\u22B4", "LeftUpDownVector": "\u2951", "LeftUpTeeVector": "\u2960", "LeftUpVector": "\u21BF", "LeftUpVectorBar": "\u2958", "LeftVector": "\u21BC", "LeftVectorBar": "\u2952", "leg": "\u22DA", "lEg": "\u2A8B", "leq": "\u2264", "leqq": "\u2266", "leqslant": "\u2A7D", "les": "\u2A7D", "lescc": "\u2AA8", "lesdot": "\u2A7F", "lesdoto": "\u2A81", "lesdotor": "\u2A83", "lesg": "\u22DA\uFE00", "lesges": "\u2A93", "lessapprox": "\u2A85", "lessdot": "\u22D6", "lesseqgtr": "\u22DA", "lesseqqgtr": "\u2A8B", "LessEqualGreater": "\u22DA", "LessFullEqual": "\u2266", "LessGreater": "\u2276", "lessgtr": "\u2276", "LessLess": "\u2AA1", "lesssim": "\u2272", "LessSlantEqual": "\u2A7D", "LessTilde": "\u2272", "lfisht": "\u297C", "lfloor": "\u230A", "lfr": "\u{1D529}", "Lfr": "\u{1D50F}", "lg": "\u2276", "lgE": "\u2A91", "lHar": "\u2962", "lhard": "\u21BD", "lharu": "\u21BC", "lharul": "\u296A", "lhblk": "\u2584", "ljcy": "\u0459", "LJcy": "\u0409", "ll": "\u226A", "Ll": "\u22D8", "llarr": "\u21C7", "llcorner": "\u231E", "Lleftarrow": "\u21DA", "llhard": "\u296B", "lltri": "\u25FA", "lmidot": "\u0140", "Lmidot": "\u013F", "lmoust": "\u23B0", "lmoustache": "\u23B0", "lnap": "\u2A89", "lnapprox": "\u2A89", "lne": "\u2A87", "lnE": "\u2268", "lneq": "\u2A87", "lneqq": "\u2268", "lnsim": "\u22E6", "loang": "\u27EC", "loarr": "\u21FD", "lobrk": "\u27E6", "longleftarrow": "\u27F5", "Longleftarrow": "\u27F8", "LongLeftArrow": "\u27F5", "longleftrightarrow": "\u27F7", "Longleftrightarrow": "\u27FA", "LongLeftRightArrow": "\u27F7", "longmapsto": "\u27FC", "longrightarrow": "\u27F6", "Longrightarrow": "\u27F9", "LongRightArrow": "\u27F6", "looparrowleft": "\u21AB", "looparrowright": "\u21AC", "lopar": "\u2985", "lopf": "\u{1D55D}", "Lopf": "\u{1D543}", "loplus": "\u2A2D", "lotimes": "\u2A34", "lowast": "\u2217", "lowbar": "_", "LowerLeftArrow": "\u2199", "LowerRightArrow": "\u2198", "loz": "\u25CA", "lozenge": "\u25CA", "lozf": "\u29EB", "lpar": "(", "lparlt": "\u2993", "lrarr": "\u21C6", "lrcorner": "\u231F", "lrhar": "\u21CB", "lrhard": "\u296D", "lrm": "\u200E", "lrtri": "\u22BF", "lsaquo": "\u2039", "lscr": "\u{1D4C1}", "Lscr": "\u2112", "lsh": "\u21B0", "Lsh": "\u21B0", "lsim": "\u2272", "lsime": "\u2A8D", "lsimg": "\u2A8F", "lsqb": "[", "lsquo": "\u2018", "lsquor": "\u201A", "lstrok": "\u0142", "Lstrok": "\u0141", "lt": "<", "Lt": "\u226A", "LT": "<", "ltcc": "\u2AA6", "ltcir": "\u2A79", "ltdot": "\u22D6", "lthree": "\u22CB", "ltimes": "\u22C9", "ltlarr": "\u2976", "ltquest": "\u2A7B", "ltri": "\u25C3", "ltrie": "\u22B4", "ltrif": "\u25C2", "ltrPar": "\u2996", "lurdshar": "\u294A", "luruhar": "\u2966", "lvertneqq": "\u2268\uFE00", "lvnE": "\u2268\uFE00", "macr": "\xAF", "male": "\u2642", "malt": "\u2720", "maltese": "\u2720", "map": "\u21A6", "Map": "\u2905", "mapsto": "\u21A6", "mapstodown": "\u21A7", "mapstoleft": "\u21A4", "mapstoup": "\u21A5", "marker": "\u25AE", "mcomma": "\u2A29", "mcy": "\u043C", "Mcy": "\u041C", "mdash": "\u2014", "mDDot": "\u223A", "measuredangle": "\u2221", "MediumSpace": "\u205F", "Mellintrf": "\u2133", "mfr": "\u{1D52A}", "Mfr": "\u{1D510}", "mho": "\u2127", "micro": "\xB5", "mid": "\u2223", "midast": "*", "midcir": "\u2AF0", "middot": "\xB7", "minus": "\u2212", "minusb": "\u229F", "minusd": "\u2238", "minusdu": "\u2A2A", "MinusPlus": "\u2213", "mlcp": "\u2ADB", "mldr": "\u2026", "mnplus": "\u2213", "models": "\u22A7", "mopf": "\u{1D55E}", "Mopf": "\u{1D544}", "mp": "\u2213", "mscr": "\u{1D4C2}", "Mscr": "\u2133", "mstpos": "\u223E", "mu": "\u03BC", "Mu": "\u039C", "multimap": "\u22B8", "mumap": "\u22B8", "nabla": "\u2207", "nacute": "\u0144", "Nacute": "\u0143", "nang": "\u2220\u20D2", "nap": "\u2249", "napE": "\u2A70\u0338", "napid": "\u224B\u0338", "napos": "\u0149", "napprox": "\u2249", "natur": "\u266E", "natural": "\u266E", "naturals": "\u2115", "nbsp": "\xA0", "nbump": "\u224E\u0338", "nbumpe": "\u224F\u0338", "ncap": "\u2A43", "ncaron": "\u0148", "Ncaron": "\u0147", "ncedil": "\u0146", "Ncedil": "\u0145", "ncong": "\u2247", "ncongdot": "\u2A6D\u0338", "ncup": "\u2A42", "ncy": "\u043D", "Ncy": "\u041D", "ndash": "\u2013", "ne": "\u2260", "nearhk": "\u2924", "nearr": "\u2197", "neArr": "\u21D7", "nearrow": "\u2197", "nedot": "\u2250\u0338", "NegativeMediumSpace": "\u200B", "NegativeThickSpace": "\u200B", "NegativeThinSpace": "\u200B", "NegativeVeryThinSpace": "\u200B", "nequiv": "\u2262", "nesear": "\u2928", "nesim": "\u2242\u0338", "NestedGreaterGreater": "\u226B", "NestedLessLess": "\u226A", "NewLine": "\n", "nexist": "\u2204", "nexists": "\u2204", "nfr": "\u{1D52B}", "Nfr": "\u{1D511}", "nge": "\u2271", "ngE": "\u2267\u0338", "ngeq": "\u2271", "ngeqq": "\u2267\u0338", "ngeqslant": "\u2A7E\u0338", "nges": "\u2A7E\u0338", "nGg": "\u22D9\u0338", "ngsim": "\u2275", "ngt": "\u226F", "nGt": "\u226B\u20D2", "ngtr": "\u226F", "nGtv": "\u226B\u0338", "nharr": "\u21AE", "nhArr": "\u21CE", "nhpar": "\u2AF2", "ni": "\u220B", "nis": "\u22FC", "nisd": "\u22FA", "niv": "\u220B", "njcy": "\u045A", "NJcy": "\u040A", "nlarr": "\u219A", "nlArr": "\u21CD", "nldr": "\u2025", "nle": "\u2270", "nlE": "\u2266\u0338", "nleftarrow": "\u219A", "nLeftarrow": "\u21CD", "nleftrightarrow": "\u21AE", "nLeftrightarrow": "\u21CE", "nleq": "\u2270", "nleqq": "\u2266\u0338", "nleqslant": "\u2A7D\u0338", "nles": "\u2A7D\u0338", "nless": "\u226E", "nLl": "\u22D8\u0338", "nlsim": "\u2274", "nlt": "\u226E", "nLt": "\u226A\u20D2", "nltri": "\u22EA", "nltrie": "\u22EC", "nLtv": "\u226A\u0338", "nmid": "\u2224", "NoBreak": "\u2060", "NonBreakingSpace": "\xA0", "nopf": "\u{1D55F}", "Nopf": "\u2115", "not": "\xAC", "Not": "\u2AEC", "NotCongruent": "\u2262", "NotCupCap": "\u226D", "NotDoubleVerticalBar": "\u2226", "NotElement": "\u2209", "NotEqual": "\u2260", "NotEqualTilde": "\u2242\u0338", "NotExists": "\u2204", "NotGreater": "\u226F", "NotGreaterEqual": "\u2271", "NotGreaterFullEqual": "\u2267\u0338", "NotGreaterGreater": "\u226B\u0338", "NotGreaterLess": "\u2279", "NotGreaterSlantEqual": "\u2A7E\u0338", "NotGreaterTilde": "\u2275", "NotHumpDownHump": "\u224E\u0338", "NotHumpEqual": "\u224F\u0338", "notin": "\u2209", "notindot": "\u22F5\u0338", "notinE": "\u22F9\u0338", "notinva": "\u2209", "notinvb": "\u22F7", "notinvc": "\u22F6", "NotLeftTriangle": "\u22EA", "NotLeftTriangleBar": "\u29CF\u0338", "NotLeftTriangleEqual": "\u22EC", "NotLess": "\u226E", "NotLessEqual": "\u2270", "NotLessGreater": "\u2278", "NotLessLess": "\u226A\u0338", "NotLessSlantEqual": "\u2A7D\u0338", "NotLessTilde": "\u2274", "NotNestedGreaterGreater": "\u2AA2\u0338", "NotNestedLessLess": "\u2AA1\u0338", "notni": "\u220C", "notniva": "\u220C", "notnivb": "\u22FE", "notnivc": "\u22FD", "NotPrecedes": "\u2280", "NotPrecedesEqual": "\u2AAF\u0338", "NotPrecedesSlantEqual": "\u22E0", "NotReverseElement": "\u220C", "NotRightTriangle": "\u22EB", "NotRightTriangleBar": "\u29D0\u0338", "NotRightTriangleEqual": "\u22ED", "NotSquareSubset": "\u228F\u0338", "NotSquareSubsetEqual": "\u22E2", "NotSquareSuperset": "\u2290\u0338", "NotSquareSupersetEqual": "\u22E3", "NotSubset": "\u2282\u20D2", "NotSubsetEqual": "\u2288", "NotSucceeds": "\u2281", "NotSucceedsEqual": "\u2AB0\u0338", "NotSucceedsSlantEqual": "\u22E1", "NotSucceedsTilde": "\u227F\u0338", "NotSuperset": "\u2283\u20D2", "NotSupersetEqual": "\u2289", "NotTilde": "\u2241", "NotTildeEqual": "\u2244", "NotTildeFullEqual": "\u2247", "NotTildeTilde": "\u2249", "NotVerticalBar": "\u2224", "npar": "\u2226", "nparallel": "\u2226", "nparsl": "\u2AFD\u20E5", "npart": "\u2202\u0338", "npolint": "\u2A14", "npr": "\u2280", "nprcue": "\u22E0", "npre": "\u2AAF\u0338", "nprec": "\u2280", "npreceq": "\u2AAF\u0338", "nrarr": "\u219B", "nrArr": "\u21CF", "nrarrc": "\u2933\u0338", "nrarrw": "\u219D\u0338", "nrightarrow": "\u219B", "nRightarrow": "\u21CF", "nrtri": "\u22EB", "nrtrie": "\u22ED", "nsc": "\u2281", "nsccue": "\u22E1", "nsce": "\u2AB0\u0338", "nscr": "\u{1D4C3}", "Nscr": "\u{1D4A9}", "nshortmid": "\u2224", "nshortparallel": "\u2226", "nsim": "\u2241", "nsime": "\u2244", "nsimeq": "\u2244", "nsmid": "\u2224", "nspar": "\u2226", "nsqsube": "\u22E2", "nsqsupe": "\u22E3", "nsub": "\u2284", "nsube": "\u2288", "nsubE": "\u2AC5\u0338", "nsubset": "\u2282\u20D2", "nsubseteq": "\u2288", "nsubseteqq": "\u2AC5\u0338", "nsucc": "\u2281", "nsucceq": "\u2AB0\u0338", "nsup": "\u2285", "nsupe": "\u2289", "nsupE": "\u2AC6\u0338", "nsupset": "\u2283\u20D2", "nsupseteq": "\u2289", "nsupseteqq": "\u2AC6\u0338", "ntgl": "\u2279", "ntilde": "\xF1", "Ntilde": "\xD1", "ntlg": "\u2278", "ntriangleleft": "\u22EA", "ntrianglelefteq": "\u22EC", "ntriangleright": "\u22EB", "ntrianglerighteq": "\u22ED", "nu": "\u03BD", "Nu": "\u039D", "num": "#", "numero": "\u2116", "numsp": "\u2007", "nvap": "\u224D\u20D2", "nvdash": "\u22AC", "nvDash": "\u22AD", "nVdash": "\u22AE", "nVDash": "\u22AF", "nvge": "\u2265\u20D2", "nvgt": ">\u20D2", "nvHarr": "\u2904", "nvinfin": "\u29DE", "nvlArr": "\u2902", "nvle": "\u2264\u20D2", "nvlt": "<\u20D2", "nvltrie": "\u22B4\u20D2", "nvrArr": "\u2903", "nvrtrie": "\u22B5\u20D2", "nvsim": "\u223C\u20D2", "nwarhk": "\u2923", "nwarr": "\u2196", "nwArr": "\u21D6", "nwarrow": "\u2196", "nwnear": "\u2927", "oacute": "\xF3", "Oacute": "\xD3", "oast": "\u229B", "ocir": "\u229A", "ocirc": "\xF4", "Ocirc": "\xD4", "ocy": "\u043E", "Ocy": "\u041E", "odash": "\u229D", "odblac": "\u0151", "Odblac": "\u0150", "odiv": "\u2A38", "odot": "\u2299", "odsold": "\u29BC", "oelig": "\u0153", "OElig": "\u0152", "ofcir": "\u29BF", "ofr": "\u{1D52C}", "Ofr": "\u{1D512}", "ogon": "\u02DB", "ograve": "\xF2", "Ograve": "\xD2", "ogt": "\u29C1", "ohbar": "\u29B5", "ohm": "\u03A9", "oint": "\u222E", "olarr": "\u21BA", "olcir": "\u29BE", "olcross": "\u29BB", "oline": "\u203E", "olt": "\u29C0", "omacr": "\u014D", "Omacr": "\u014C", "omega": "\u03C9", "Omega": "\u03A9", "omicron": "\u03BF", "Omicron": "\u039F", "omid": "\u29B6", "ominus": "\u2296", "oopf": "\u{1D560}", "Oopf": "\u{1D546}", "opar": "\u29B7", "OpenCurlyDoubleQuote": "\u201C", "OpenCurlyQuote": "\u2018", "operp": "\u29B9", "oplus": "\u2295", "or": "\u2228", "Or": "\u2A54", "orarr": "\u21BB", "ord": "\u2A5D", "order": "\u2134", "orderof": "\u2134", "ordf": "\xAA", "ordm": "\xBA", "origof": "\u22B6", "oror": "\u2A56", "orslope": "\u2A57", "orv": "\u2A5B", "oS": "\u24C8", "oscr": "\u2134", "Oscr": "\u{1D4AA}", "oslash": "\xF8", "Oslash": "\xD8", "osol": "\u2298", "otilde": "\xF5", "Otilde": "\xD5", "otimes": "\u2297", "Otimes": "\u2A37", "otimesas": "\u2A36", "ouml": "\xF6", "Ouml": "\xD6", "ovbar": "\u233D", "OverBar": "\u203E", "OverBrace": "\u23DE", "OverBracket": "\u23B4", "OverParenthesis": "\u23DC", "par": "\u2225", "para": "\xB6", "parallel": "\u2225", "parsim": "\u2AF3", "parsl": "\u2AFD", "part": "\u2202", "PartialD": "\u2202", "pcy": "\u043F", "Pcy": "\u041F", "percnt": "%", "period": ".", "permil": "\u2030", "perp": "\u22A5", "pertenk": "\u2031", "pfr": "\u{1D52D}", "Pfr": "\u{1D513}", "phi": "\u03C6", "Phi": "\u03A6", "phiv": "\u03D5", "phmmat": "\u2133", "phone": "\u260E", "pi": "\u03C0", "Pi": "\u03A0", "pitchfork": "\u22D4", "piv": "\u03D6", "planck": "\u210F", "planckh": "\u210E", "plankv": "\u210F", "plus": "+", "plusacir": "\u2A23", "plusb": "\u229E", "pluscir": "\u2A22", "plusdo": "\u2214", "plusdu": "\u2A25", "pluse": "\u2A72", "PlusMinus": "\xB1", "plusmn": "\xB1", "plussim": "\u2A26", "plustwo": "\u2A27", "pm": "\xB1", "Poincareplane": "\u210C", "pointint": "\u2A15", "popf": "\u{1D561}", "Popf": "\u2119", "pound": "\xA3", "pr": "\u227A", "Pr": "\u2ABB", "prap": "\u2AB7", "prcue": "\u227C", "pre": "\u2AAF", "prE": "\u2AB3", "prec": "\u227A", "precapprox": "\u2AB7", "preccurlyeq": "\u227C", "Precedes": "\u227A", "PrecedesEqual": "\u2AAF", "PrecedesSlantEqual": "\u227C", "PrecedesTilde": "\u227E", "preceq": "\u2AAF", "precnapprox": "\u2AB9", "precneqq": "\u2AB5", "precnsim": "\u22E8", "precsim": "\u227E", "prime": "\u2032", "Prime": "\u2033", "primes": "\u2119", "prnap": "\u2AB9", "prnE": "\u2AB5", "prnsim": "\u22E8", "prod": "\u220F", "Product": "\u220F", "profalar": "\u232E", "profline": "\u2312", "profsurf": "\u2313", "prop": "\u221D", "Proportion": "\u2237", "Proportional": "\u221D", "propto": "\u221D", "prsim": "\u227E", "prurel": "\u22B0", "pscr": "\u{1D4C5}", "Pscr": "\u{1D4AB}", "psi": "\u03C8", "Psi": "\u03A8", "puncsp": "\u2008", "qfr": "\u{1D52E}", "Qfr": "\u{1D514}", "qint": "\u2A0C", "qopf": "\u{1D562}", "Qopf": "\u211A", "qprime": "\u2057", "qscr": "\u{1D4C6}", "Qscr": "\u{1D4AC}", "quaternions": "\u210D", "quatint": "\u2A16", "quest": "?", "questeq": "\u225F", "quot": '"', "QUOT": '"', "rAarr": "\u21DB", "race": "\u223D\u0331", "racute": "\u0155", "Racute": "\u0154", "radic": "\u221A", "raemptyv": "\u29B3", "rang": "\u27E9", "Rang": "\u27EB", "rangd": "\u2992", "range": "\u29A5", "rangle": "\u27E9", "raquo": "\xBB", "rarr": "\u2192", "rArr": "\u21D2", "Rarr": "\u21A0", "rarrap": "\u2975", "rarrb": "\u21E5", "rarrbfs": "\u2920", "rarrc": "\u2933", "rarrfs": "\u291E", "rarrhk": "\u21AA", "rarrlp": "\u21AC", "rarrpl": "\u2945", "rarrsim": "\u2974", "rarrtl": "\u21A3", "Rarrtl": "\u2916", "rarrw": "\u219D", "ratail": "\u291A", "rAtail": "\u291C", "ratio": "\u2236", "rationals": "\u211A", "rbarr": "\u290D", "rBarr": "\u290F", "RBarr": "\u2910", "rbbrk": "\u2773", "rbrace": "}", "rbrack": "]", "rbrke": "\u298C", "rbrksld": "\u298E", "rbrkslu": "\u2990", "rcaron": "\u0159", "Rcaron": "\u0158", "rcedil": "\u0157", "Rcedil": "\u0156", "rceil": "\u2309", "rcub": "}", "rcy": "\u0440", "Rcy": "\u0420", "rdca": "\u2937", "rdldhar": "\u2969", "rdquo": "\u201D", "rdquor": "\u201D", "rdsh": "\u21B3", "Re": "\u211C", "real": "\u211C", "realine": "\u211B", "realpart": "\u211C", "reals": "\u211D", "rect": "\u25AD", "reg": "\xAE", "REG": "\xAE", "ReverseElement": "\u220B", "ReverseEquilibrium": "\u21CB", "ReverseUpEquilibrium": "\u296F", "rfisht": "\u297D", "rfloor": "\u230B", "rfr": "\u{1D52F}", "Rfr": "\u211C", "rHar": "\u2964", "rhard": "\u21C1", "rharu": "\u21C0", "rharul": "\u296C", "rho": "\u03C1", "Rho": "\u03A1", "rhov": "\u03F1", "RightAngleBracket": "\u27E9", "rightarrow": "\u2192", "Rightarrow": "\u21D2", "RightArrow": "\u2192", "RightArrowBar": "\u21E5", "RightArrowLeftArrow": "\u21C4", "rightarrowtail": "\u21A3", "RightCeiling": "\u2309", "RightDoubleBracket": "\u27E7", "RightDownTeeVector": "\u295D", "RightDownVector": "\u21C2", "RightDownVectorBar": "\u2955", "RightFloor": "\u230B", "rightharpoondown": "\u21C1", "rightharpoonup": "\u21C0", "rightleftarrows": "\u21C4", "rightleftharpoons": "\u21CC", "rightrightarrows": "\u21C9", "rightsquigarrow": "\u219D", "RightTee": "\u22A2", "RightTeeArrow": "\u21A6", "RightTeeVector": "\u295B", "rightthreetimes": "\u22CC", "RightTriangle": "\u22B3", "RightTriangleBar": "\u29D0", "RightTriangleEqual": "\u22B5", "RightUpDownVector": "\u294F", "RightUpTeeVector": "\u295C", "RightUpVector": "\u21BE", "RightUpVectorBar": "\u2954", "RightVector": "\u21C0", "RightVectorBar": "\u2953", "ring": "\u02DA", "risingdotseq": "\u2253", "rlarr": "\u21C4", "rlhar": "\u21CC", "rlm": "\u200F", "rmoust": "\u23B1", "rmoustache": "\u23B1", "rnmid": "\u2AEE", "roang": "\u27ED", "roarr": "\u21FE", "robrk": "\u27E7", "ropar": "\u2986", "ropf": "\u{1D563}", "Ropf": "\u211D", "roplus": "\u2A2E", "rotimes": "\u2A35", "RoundImplies": "\u2970", "rpar": ")", "rpargt": "\u2994", "rppolint": "\u2A12", "rrarr": "\u21C9", "Rrightarrow": "\u21DB", "rsaquo": "\u203A", "rscr": "\u{1D4C7}", "Rscr": "\u211B", "rsh": "\u21B1", "Rsh": "\u21B1", "rsqb": "]", "rsquo": "\u2019", "rsquor": "\u2019", "rthree": "\u22CC", "rtimes": "\u22CA", "rtri": "\u25B9", "rtrie": "\u22B5", "rtrif": "\u25B8", "rtriltri": "\u29CE", "RuleDelayed": "\u29F4", "ruluhar": "\u2968", "rx": "\u211E", "sacute": "\u015B", "Sacute": "\u015A", "sbquo": "\u201A", "sc": "\u227B", "Sc": "\u2ABC", "scap": "\u2AB8", "scaron": "\u0161", "Scaron": "\u0160", "sccue": "\u227D", "sce": "\u2AB0", "scE": "\u2AB4", "scedil": "\u015F", "Scedil": "\u015E", "scirc": "\u015D", "Scirc": "\u015C", "scnap": "\u2ABA", "scnE": "\u2AB6", "scnsim": "\u22E9", "scpolint": "\u2A13", "scsim": "\u227F", "scy": "\u0441", "Scy": "\u0421", "sdot": "\u22C5", "sdotb": "\u22A1", "sdote": "\u2A66", "searhk": "\u2925", "searr": "\u2198", "seArr": "\u21D8", "searrow": "\u2198", "sect": "\xA7", "semi": ";", "seswar": "\u2929", "setminus": "\u2216", "setmn": "\u2216", "sext": "\u2736", "sfr": "\u{1D530}", "Sfr": "\u{1D516}", "sfrown": "\u2322", "sharp": "\u266F", "shchcy": "\u0449", "SHCHcy": "\u0429", "shcy": "\u0448", "SHcy": "\u0428", "ShortDownArrow": "\u2193", "ShortLeftArrow": "\u2190", "shortmid": "\u2223", "shortparallel": "\u2225", "ShortRightArrow": "\u2192", "ShortUpArrow": "\u2191", "shy": "\xAD", "sigma": "\u03C3", "Sigma": "\u03A3", "sigmaf": "\u03C2", "sigmav": "\u03C2", "sim": "\u223C", "simdot": "\u2A6A", "sime": "\u2243", "simeq": "\u2243", "simg": "\u2A9E", "simgE": "\u2AA0", "siml": "\u2A9D", "simlE": "\u2A9F", "simne": "\u2246", "simplus": "\u2A24", "simrarr": "\u2972", "slarr": "\u2190", "SmallCircle": "\u2218", "smallsetminus": "\u2216", "smashp": "\u2A33", "smeparsl": "\u29E4", "smid": "\u2223", "smile": "\u2323", "smt": "\u2AAA", "smte": "\u2AAC", "smtes": "\u2AAC\uFE00", "softcy": "\u044C", "SOFTcy": "\u042C", "sol": "/", "solb": "\u29C4", "solbar": "\u233F", "sopf": "\u{1D564}", "Sopf": "\u{1D54A}", "spades": "\u2660", "spadesuit": "\u2660", "spar": "\u2225", "sqcap": "\u2293", "sqcaps": "\u2293\uFE00", "sqcup": "\u2294", "sqcups": "\u2294\uFE00", "Sqrt": "\u221A", "sqsub": "\u228F", "sqsube": "\u2291", "sqsubset": "\u228F", "sqsubseteq": "\u2291", "sqsup": "\u2290", "sqsupe": "\u2292", "sqsupset": "\u2290", "sqsupseteq": "\u2292", "squ": "\u25A1", "square": "\u25A1", "Square": "\u25A1", "SquareIntersection": "\u2293", "SquareSubset": "\u228F", "SquareSubsetEqual": "\u2291", "SquareSuperset": "\u2290", "SquareSupersetEqual": "\u2292", "SquareUnion": "\u2294", "squarf": "\u25AA", "squf": "\u25AA", "srarr": "\u2192", "sscr": "\u{1D4C8}", "Sscr": "\u{1D4AE}", "ssetmn": "\u2216", "ssmile": "\u2323", "sstarf": "\u22C6", "star": "\u2606", "Star": "\u22C6", "starf": "\u2605", "straightepsilon": "\u03F5", "straightphi": "\u03D5", "strns": "\xAF", "sub": "\u2282", "Sub": "\u22D0", "subdot": "\u2ABD", "sube": "\u2286", "subE": "\u2AC5", "subedot": "\u2AC3", "submult": "\u2AC1", "subne": "\u228A", "subnE": "\u2ACB", "subplus": "\u2ABF", "subrarr": "\u2979", "subset": "\u2282", "Subset": "\u22D0", "subseteq": "\u2286", "subseteqq": "\u2AC5", "SubsetEqual": "\u2286", "subsetneq": "\u228A", "subsetneqq": "\u2ACB", "subsim": "\u2AC7", "subsub": "\u2AD5", "subsup": "\u2AD3", "succ": "\u227B", "succapprox": "\u2AB8", "succcurlyeq": "\u227D", "Succeeds": "\u227B", "SucceedsEqual": "\u2AB0", "SucceedsSlantEqual": "\u227D", "SucceedsTilde": "\u227F", "succeq": "\u2AB0", "succnapprox": "\u2ABA", "succneqq": "\u2AB6", "succnsim": "\u22E9", "succsim": "\u227F", "SuchThat": "\u220B", "sum": "\u2211", "Sum": "\u2211", "sung": "\u266A", "sup": "\u2283", "Sup": "\u22D1", "sup1": "\xB9", "sup2": "\xB2", "sup3": "\xB3", "supdot": "\u2ABE", "supdsub": "\u2AD8", "supe": "\u2287", "supE": "\u2AC6", "supedot": "\u2AC4", "Superset": "\u2283", "SupersetEqual": "\u2287", "suphsol": "\u27C9", "suphsub": "\u2AD7", "suplarr": "\u297B", "supmult": "\u2AC2", "supne": "\u228B", "supnE": "\u2ACC", "supplus": "\u2AC0", "supset": "\u2283", "Supset": "\u22D1", "supseteq": "\u2287", "supseteqq": "\u2AC6", "supsetneq": "\u228B", "supsetneqq": "\u2ACC", "supsim": "\u2AC8", "supsub": "\u2AD4", "supsup": "\u2AD6", "swarhk": "\u2926", "swarr": "\u2199", "swArr": "\u21D9", "swarrow": "\u2199", "swnwar": "\u292A", "szlig": "\xDF", "Tab": " ", "target": "\u2316", "tau": "\u03C4", "Tau": "\u03A4", "tbrk": "\u23B4", "tcaron": "\u0165", "Tcaron": "\u0164", "tcedil": "\u0163", "Tcedil": "\u0162", "tcy": "\u0442", "Tcy": "\u0422", "tdot": "\u20DB", "telrec": "\u2315", "tfr": "\u{1D531}", "Tfr": "\u{1D517}", "there4": "\u2234", "therefore": "\u2234", "Therefore": "\u2234", "theta": "\u03B8", "Theta": "\u0398", "thetasym": "\u03D1", "thetav": "\u03D1", "thickapprox": "\u2248", "thicksim": "\u223C", "ThickSpace": "\u205F\u200A", "thinsp": "\u2009", "ThinSpace": "\u2009", "thkap": "\u2248", "thksim": "\u223C", "thorn": "\xFE", "THORN": "\xDE", "tilde": "\u02DC", "Tilde": "\u223C", "TildeEqual": "\u2243", "TildeFullEqual": "\u2245", "TildeTilde": "\u2248", "times": "\xD7", "timesb": "\u22A0", "timesbar": "\u2A31", "timesd": "\u2A30", "tint": "\u222D", "toea": "\u2928", "top": "\u22A4", "topbot": "\u2336", "topcir": "\u2AF1", "topf": "\u{1D565}", "Topf": "\u{1D54B}", "topfork": "\u2ADA", "tosa": "\u2929", "tprime": "\u2034", "trade": "\u2122", "TRADE": "\u2122", "triangle": "\u25B5", "triangledown": "\u25BF", "triangleleft": "\u25C3", "trianglelefteq": "\u22B4", "triangleq": "\u225C", "triangleright": "\u25B9", "trianglerighteq": "\u22B5", "tridot": "\u25EC", "trie": "\u225C", "triminus": "\u2A3A", "TripleDot": "\u20DB", "triplus": "\u2A39", "trisb": "\u29CD", "tritime": "\u2A3B", "trpezium": "\u23E2", "tscr": "\u{1D4C9}", "Tscr": "\u{1D4AF}", "tscy": "\u0446", "TScy": "\u0426", "tshcy": "\u045B", "TSHcy": "\u040B", "tstrok": "\u0167", "Tstrok": "\u0166", "twixt": "\u226C", "twoheadleftarrow": "\u219E", "twoheadrightarrow": "\u21A0", "uacute": "\xFA", "Uacute": "\xDA", "uarr": "\u2191", "uArr": "\u21D1", "Uarr": "\u219F", "Uarrocir": "\u2949", "ubrcy": "\u045E", "Ubrcy": "\u040E", "ubreve": "\u016D", "Ubreve": "\u016C", "ucirc": "\xFB", "Ucirc": "\xDB", "ucy": "\u0443", "Ucy": "\u0423", "udarr": "\u21C5", "udblac": "\u0171", "Udblac": "\u0170", "udhar": "\u296E", "ufisht": "\u297E", "ufr": "\u{1D532}", "Ufr": "\u{1D518}", "ugrave": "\xF9", "Ugrave": "\xD9", "uHar": "\u2963", "uharl": "\u21BF", "uharr": "\u21BE", "uhblk": "\u2580", "ulcorn": "\u231C", "ulcorner": "\u231C", "ulcrop": "\u230F", "ultri": "\u25F8", "umacr": "\u016B", "Umacr": "\u016A", "uml": "\xA8", "UnderBar": "_", "UnderBrace": "\u23DF", "UnderBracket": "\u23B5", "UnderParenthesis": "\u23DD", "Union": "\u22C3", "UnionPlus": "\u228E", "uogon": "\u0173", "Uogon": "\u0172", "uopf": "\u{1D566}", "Uopf": "\u{1D54C}", "uparrow": "\u2191", "Uparrow": "\u21D1", "UpArrow": "\u2191", "UpArrowBar": "\u2912", "UpArrowDownArrow": "\u21C5", "updownarrow": "\u2195", "Updownarrow": "\u21D5", "UpDownArrow": "\u2195", "UpEquilibrium": "\u296E", "upharpoonleft": "\u21BF", "upharpoonright": "\u21BE", "uplus": "\u228E", "UpperLeftArrow": "\u2196", "UpperRightArrow": "\u2197", "upsi": "\u03C5", "Upsi": "\u03D2", "upsih": "\u03D2", "upsilon": "\u03C5", "Upsilon": "\u03A5", "UpTee": "\u22A5", "UpTeeArrow": "\u21A5", "upuparrows": "\u21C8", "urcorn": "\u231D", "urcorner": "\u231D", "urcrop": "\u230E", "uring": "\u016F", "Uring": "\u016E", "urtri": "\u25F9", "uscr": "\u{1D4CA}", "Uscr": "\u{1D4B0}", "utdot": "\u22F0", "utilde": "\u0169", "Utilde": "\u0168", "utri": "\u25B5", "utrif": "\u25B4", "uuarr": "\u21C8", "uuml": "\xFC", "Uuml": "\xDC", "uwangle": "\u29A7", "vangrt": "\u299C", "varepsilon": "\u03F5", "varkappa": "\u03F0", "varnothing": "\u2205", "varphi": "\u03D5", "varpi": "\u03D6", "varpropto": "\u221D", "varr": "\u2195", "vArr": "\u21D5", "varrho": "\u03F1", "varsigma": "\u03C2", "varsubsetneq": "\u228A\uFE00", "varsubsetneqq": "\u2ACB\uFE00", "varsupsetneq": "\u228B\uFE00", "varsupsetneqq": "\u2ACC\uFE00", "vartheta": "\u03D1", "vartriangleleft": "\u22B2", "vartriangleright": "\u22B3", "vBar": "\u2AE8", "Vbar": "\u2AEB", "vBarv": "\u2AE9", "vcy": "\u0432", "Vcy": "\u0412", "vdash": "\u22A2", "vDash": "\u22A8", "Vdash": "\u22A9", "VDash": "\u22AB", "Vdashl": "\u2AE6", "vee": "\u2228", "Vee": "\u22C1", "veebar": "\u22BB", "veeeq": "\u225A", "vellip": "\u22EE", "verbar": "|", "Verbar": "\u2016", "vert": "|", "Vert": "\u2016", "VerticalBar": "\u2223", "VerticalLine": "|", "VerticalSeparator": "\u2758", "VerticalTilde": "\u2240", "VeryThinSpace": "\u200A", "vfr": "\u{1D533}", "Vfr": "\u{1D519}", "vltri": "\u22B2", "vnsub": "\u2282\u20D2", "vnsup": "\u2283\u20D2", "vopf": "\u{1D567}", "Vopf": "\u{1D54D}", "vprop": "\u221D", "vrtri": "\u22B3", "vscr": "\u{1D4CB}", "Vscr": "\u{1D4B1}", "vsubne": "\u228A\uFE00", "vsubnE": "\u2ACB\uFE00", "vsupne": "\u228B\uFE00", "vsupnE": "\u2ACC\uFE00", "Vvdash": "\u22AA", "vzigzag": "\u299A", "wcirc": "\u0175", "Wcirc": "\u0174", "wedbar": "\u2A5F", "wedge": "\u2227", "Wedge": "\u22C0", "wedgeq": "\u2259", "weierp": "\u2118", "wfr": "\u{1D534}", "Wfr": "\u{1D51A}", "wopf": "\u{1D568}", "Wopf": "\u{1D54E}", "wp": "\u2118", "wr": "\u2240", "wreath": "\u2240", "wscr": "\u{1D4CC}", "Wscr": "\u{1D4B2}", "xcap": "\u22C2", "xcirc": "\u25EF", "xcup": "\u22C3", "xdtri": "\u25BD", "xfr": "\u{1D535}", "Xfr": "\u{1D51B}", "xharr": "\u27F7", "xhArr": "\u27FA", "xi": "\u03BE", "Xi": "\u039E", "xlarr": "\u27F5", "xlArr": "\u27F8", "xmap": "\u27FC", "xnis": "\u22FB", "xodot": "\u2A00", "xopf": "\u{1D569}", "Xopf": "\u{1D54F}", "xoplus": "\u2A01", "xotime": "\u2A02", "xrarr": "\u27F6", "xrArr": "\u27F9", "xscr": "\u{1D4CD}", "Xscr": "\u{1D4B3}", "xsqcup": "\u2A06", "xuplus": "\u2A04", "xutri": "\u25B3", "xvee": "\u22C1", "xwedge": "\u22C0", "yacute": "\xFD", "Yacute": "\xDD", "yacy": "\u044F", "YAcy": "\u042F", "ycirc": "\u0177", "Ycirc": "\u0176", "ycy": "\u044B", "Ycy": "\u042B", "yen": "\xA5", "yfr": "\u{1D536}", "Yfr": "\u{1D51C}", "yicy": "\u0457", "YIcy": "\u0407", "yopf": "\u{1D56A}", "Yopf": "\u{1D550}", "yscr": "\u{1D4CE}", "Yscr": "\u{1D4B4}", "yucy": "\u044E", "YUcy": "\u042E", "yuml": "\xFF", "Yuml": "\u0178", "zacute": "\u017A", "Zacute": "\u0179", "zcaron": "\u017E", "Zcaron": "\u017D", "zcy": "\u0437", "Zcy": "\u0417", "zdot": "\u017C", "Zdot": "\u017B", "zeetrf": "\u2128", "ZeroWidthSpace": "\u200B", "zeta": "\u03B6", "Zeta": "\u0396", "zfr": "\u{1D537}", "Zfr": "\u2128", "zhcy": "\u0436", "ZHcy": "\u0416", "zigrarr": "\u21DD", "zopf": "\u{1D56B}", "Zopf": "\u2124", "zscr": "\u{1D4CF}", "Zscr": "\u{1D4B5}", "zwj": "\u200D", "zwnj": "\u200C" };
|
|
var decodeMapLegacy = { "aacute": "\xE1", "Aacute": "\xC1", "acirc": "\xE2", "Acirc": "\xC2", "acute": "\xB4", "aelig": "\xE6", "AElig": "\xC6", "agrave": "\xE0", "Agrave": "\xC0", "amp": "&", "AMP": "&", "aring": "\xE5", "Aring": "\xC5", "atilde": "\xE3", "Atilde": "\xC3", "auml": "\xE4", "Auml": "\xC4", "brvbar": "\xA6", "ccedil": "\xE7", "Ccedil": "\xC7", "cedil": "\xB8", "cent": "\xA2", "copy": "\xA9", "COPY": "\xA9", "curren": "\xA4", "deg": "\xB0", "divide": "\xF7", "eacute": "\xE9", "Eacute": "\xC9", "ecirc": "\xEA", "Ecirc": "\xCA", "egrave": "\xE8", "Egrave": "\xC8", "eth": "\xF0", "ETH": "\xD0", "euml": "\xEB", "Euml": "\xCB", "frac12": "\xBD", "frac14": "\xBC", "frac34": "\xBE", "gt": ">", "GT": ">", "iacute": "\xED", "Iacute": "\xCD", "icirc": "\xEE", "Icirc": "\xCE", "iexcl": "\xA1", "igrave": "\xEC", "Igrave": "\xCC", "iquest": "\xBF", "iuml": "\xEF", "Iuml": "\xCF", "laquo": "\xAB", "lt": "<", "LT": "<", "macr": "\xAF", "micro": "\xB5", "middot": "\xB7", "nbsp": "\xA0", "not": "\xAC", "ntilde": "\xF1", "Ntilde": "\xD1", "oacute": "\xF3", "Oacute": "\xD3", "ocirc": "\xF4", "Ocirc": "\xD4", "ograve": "\xF2", "Ograve": "\xD2", "ordf": "\xAA", "ordm": "\xBA", "oslash": "\xF8", "Oslash": "\xD8", "otilde": "\xF5", "Otilde": "\xD5", "ouml": "\xF6", "Ouml": "\xD6", "para": "\xB6", "plusmn": "\xB1", "pound": "\xA3", "quot": '"', "QUOT": '"', "raquo": "\xBB", "reg": "\xAE", "REG": "\xAE", "sect": "\xA7", "shy": "\xAD", "sup1": "\xB9", "sup2": "\xB2", "sup3": "\xB3", "szlig": "\xDF", "thorn": "\xFE", "THORN": "\xDE", "times": "\xD7", "uacute": "\xFA", "Uacute": "\xDA", "ucirc": "\xFB", "Ucirc": "\xDB", "ugrave": "\xF9", "Ugrave": "\xD9", "uml": "\xA8", "uuml": "\xFC", "Uuml": "\xDC", "yacute": "\xFD", "Yacute": "\xDD", "yen": "\xA5", "yuml": "\xFF" };
|
|
var decodeMapNumeric = { "0": "\uFFFD", "128": "\u20AC", "130": "\u201A", "131": "\u0192", "132": "\u201E", "133": "\u2026", "134": "\u2020", "135": "\u2021", "136": "\u02C6", "137": "\u2030", "138": "\u0160", "139": "\u2039", "140": "\u0152", "142": "\u017D", "145": "\u2018", "146": "\u2019", "147": "\u201C", "148": "\u201D", "149": "\u2022", "150": "\u2013", "151": "\u2014", "152": "\u02DC", "153": "\u2122", "154": "\u0161", "155": "\u203A", "156": "\u0153", "158": "\u017E", "159": "\u0178" };
|
|
var invalidReferenceCodePoints = [1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 64976, 64977, 64978, 64979, 64980, 64981, 64982, 64983, 64984, 64985, 64986, 64987, 64988, 64989, 64990, 64991, 64992, 64993, 64994, 64995, 64996, 64997, 64998, 64999, 65e3, 65001, 65002, 65003, 65004, 65005, 65006, 65007, 65534, 65535, 131070, 131071, 196606, 196607, 262142, 262143, 327678, 327679, 393214, 393215, 458750, 458751, 524286, 524287, 589822, 589823, 655358, 655359, 720894, 720895, 786430, 786431, 851966, 851967, 917502, 917503, 983038, 983039, 1048574, 1048575, 1114110, 1114111];
|
|
var stringFromCharCode = String.fromCharCode;
|
|
var object = {};
|
|
var hasOwnProperty = object.hasOwnProperty;
|
|
var has = function(object2, propertyName) {
|
|
return hasOwnProperty.call(object2, propertyName);
|
|
};
|
|
var contains = function(array, value) {
|
|
var index = -1;
|
|
var length = array.length;
|
|
while (++index < length) {
|
|
if (array[index] == value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
var merge = function(options, defaults) {
|
|
if (!options) {
|
|
return defaults;
|
|
}
|
|
var result = {};
|
|
var key2;
|
|
for (key2 in defaults) {
|
|
result[key2] = has(options, key2) ? options[key2] : defaults[key2];
|
|
}
|
|
return result;
|
|
};
|
|
var codePointToSymbol = function(codePoint, strict) {
|
|
var output = "";
|
|
if (codePoint >= 55296 && codePoint <= 57343 || codePoint > 1114111) {
|
|
if (strict) {
|
|
parseError("character reference outside the permissible Unicode range");
|
|
}
|
|
return "\uFFFD";
|
|
}
|
|
if (has(decodeMapNumeric, codePoint)) {
|
|
if (strict) {
|
|
parseError("disallowed character reference");
|
|
}
|
|
return decodeMapNumeric[codePoint];
|
|
}
|
|
if (strict && contains(invalidReferenceCodePoints, codePoint)) {
|
|
parseError("disallowed character reference");
|
|
}
|
|
if (codePoint > 65535) {
|
|
codePoint -= 65536;
|
|
output += stringFromCharCode(codePoint >>> 10 & 1023 | 55296);
|
|
codePoint = 56320 | codePoint & 1023;
|
|
}
|
|
output += stringFromCharCode(codePoint);
|
|
return output;
|
|
};
|
|
var hexEscape = function(codePoint) {
|
|
return "&#x" + codePoint.toString(16).toUpperCase() + ";";
|
|
};
|
|
var decEscape = function(codePoint) {
|
|
return "&#" + codePoint + ";";
|
|
};
|
|
var parseError = function(message) {
|
|
throw Error("Parse error: " + message);
|
|
};
|
|
var encode = function(string, options) {
|
|
options = merge(options, encode.options);
|
|
var strict = options.strict;
|
|
if (strict && regexInvalidRawCodePoint.test(string)) {
|
|
parseError("forbidden code point");
|
|
}
|
|
var encodeEverything = options.encodeEverything;
|
|
var useNamedReferences = options.useNamedReferences;
|
|
var allowUnsafeSymbols = options.allowUnsafeSymbols;
|
|
var escapeCodePoint = options.decimal ? decEscape : hexEscape;
|
|
var escapeBmpSymbol = function(symbol) {
|
|
return escapeCodePoint(symbol.charCodeAt(0));
|
|
};
|
|
if (encodeEverything) {
|
|
string = string.replace(regexAsciiWhitelist, function(symbol) {
|
|
if (useNamedReferences && has(encodeMap, symbol)) {
|
|
return "&" + encodeMap[symbol] + ";";
|
|
}
|
|
return escapeBmpSymbol(symbol);
|
|
});
|
|
if (useNamedReferences) {
|
|
string = string.replace(/>\u20D2/g, ">⃒").replace(/<\u20D2/g, "<⃒").replace(/fj/g, "fj");
|
|
}
|
|
if (useNamedReferences) {
|
|
string = string.replace(regexEncodeNonAscii, function(string2) {
|
|
return "&" + encodeMap[string2] + ";";
|
|
});
|
|
}
|
|
} else if (useNamedReferences) {
|
|
if (!allowUnsafeSymbols) {
|
|
string = string.replace(regexEscape, function(string2) {
|
|
return "&" + encodeMap[string2] + ";";
|
|
});
|
|
}
|
|
string = string.replace(/>\u20D2/g, ">⃒").replace(/<\u20D2/g, "<⃒");
|
|
string = string.replace(regexEncodeNonAscii, function(string2) {
|
|
return "&" + encodeMap[string2] + ";";
|
|
});
|
|
} else if (!allowUnsafeSymbols) {
|
|
string = string.replace(regexEscape, escapeBmpSymbol);
|
|
}
|
|
return string.replace(regexAstralSymbols, function($0) {
|
|
var high = $0.charCodeAt(0);
|
|
var low = $0.charCodeAt(1);
|
|
var codePoint = (high - 55296) * 1024 + low - 56320 + 65536;
|
|
return escapeCodePoint(codePoint);
|
|
}).replace(regexBmpWhitelist, escapeBmpSymbol);
|
|
};
|
|
encode.options = {
|
|
"allowUnsafeSymbols": false,
|
|
"encodeEverything": false,
|
|
"strict": false,
|
|
"useNamedReferences": false,
|
|
"decimal": false
|
|
};
|
|
var decode2 = function(html, options) {
|
|
options = merge(options, decode2.options);
|
|
var strict = options.strict;
|
|
if (strict && regexInvalidEntity.test(html)) {
|
|
parseError("malformed character reference");
|
|
}
|
|
return html.replace(regexDecode, function($0, $1, $2, $3, $4, $5, $6, $7, $8) {
|
|
var codePoint;
|
|
var semicolon;
|
|
var decDigits;
|
|
var hexDigits;
|
|
var reference;
|
|
var next;
|
|
if ($1) {
|
|
reference = $1;
|
|
return decodeMap[reference];
|
|
}
|
|
if ($2) {
|
|
reference = $2;
|
|
next = $3;
|
|
if (next && options.isAttributeValue) {
|
|
if (strict && next == "=") {
|
|
parseError("`&` did not start a character reference");
|
|
}
|
|
return $0;
|
|
} else {
|
|
if (strict) {
|
|
parseError("named character reference was not terminated by a semicolon");
|
|
}
|
|
return decodeMapLegacy[reference] + (next || "");
|
|
}
|
|
}
|
|
if ($4) {
|
|
decDigits = $4;
|
|
semicolon = $5;
|
|
if (strict && !semicolon) {
|
|
parseError("character reference was not terminated by a semicolon");
|
|
}
|
|
codePoint = parseInt(decDigits, 10);
|
|
return codePointToSymbol(codePoint, strict);
|
|
}
|
|
if ($6) {
|
|
hexDigits = $6;
|
|
semicolon = $7;
|
|
if (strict && !semicolon) {
|
|
parseError("character reference was not terminated by a semicolon");
|
|
}
|
|
codePoint = parseInt(hexDigits, 16);
|
|
return codePointToSymbol(codePoint, strict);
|
|
}
|
|
if (strict) {
|
|
parseError("named character reference was not terminated by a semicolon");
|
|
}
|
|
return $0;
|
|
});
|
|
};
|
|
decode2.options = {
|
|
"isAttributeValue": false,
|
|
"strict": false
|
|
};
|
|
var escape2 = function(string) {
|
|
return string.replace(regexEscape, function($0) {
|
|
return escapeMap[$0];
|
|
});
|
|
};
|
|
var he = {
|
|
"version": "1.2.0",
|
|
"encode": encode,
|
|
"decode": decode2,
|
|
"escape": escape2,
|
|
"unescape": decode2
|
|
};
|
|
if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
|
|
define(function() {
|
|
return he;
|
|
});
|
|
} else if (freeExports && !freeExports.nodeType) {
|
|
if (freeModule) {
|
|
freeModule.exports = he;
|
|
} else {
|
|
for (var key in he) {
|
|
has(he, key) && (freeExports[key] = he[key]);
|
|
}
|
|
}
|
|
} else {
|
|
root.he = he;
|
|
}
|
|
})(exports);
|
|
}
|
|
});
|
|
|
|
// src/main.ts
|
|
__export(exports, {
|
|
default: () => DiceRollerPlugin
|
|
});
|
|
var import_obsidian8 = __toModule(require("obsidian"));
|
|
var import_lex = __toModule(require_lexer());
|
|
|
|
// node_modules/@fortawesome/free-solid-svg-icons/index.es.js
|
|
var faDice = {
|
|
prefix: "fas",
|
|
iconName: "dice",
|
|
icon: [640, 512, [], "f522", "M592 192H473.26c12.69 29.59 7.12 65.2-17 89.32L320 417.58V464c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48V240c0-26.51-21.49-48-48-48zM480 376c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24zm-46.37-186.7L258.7 14.37c-19.16-19.16-50.23-19.16-69.39 0L14.37 189.3c-19.16 19.16-19.16 50.23 0 69.39L189.3 433.63c19.16 19.16 50.23 19.16 69.39 0L433.63 258.7c19.16-19.17 19.16-50.24 0-69.4zM96 248c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24zm128 128c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24zm0-128c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24zm0-128c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24zm128 128c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z"]
|
|
};
|
|
|
|
// node_modules/@fortawesome/free-regular-svg-icons/index.es.js
|
|
var faCopy = {
|
|
prefix: "far",
|
|
iconName: "copy",
|
|
icon: [448, 512, [], "f0c5", "M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"]
|
|
};
|
|
|
|
// node_modules/@fortawesome/fontawesome-svg-core/index.es.js
|
|
function _typeof(obj) {
|
|
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
_typeof = function(obj2) {
|
|
return typeof obj2;
|
|
};
|
|
} else {
|
|
_typeof = function(obj2) {
|
|
return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
|
|
};
|
|
}
|
|
return _typeof(obj);
|
|
}
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor)
|
|
descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
if (protoProps)
|
|
_defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps)
|
|
_defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _defineProperty(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
return obj;
|
|
}
|
|
function _objectSpread(target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
var ownKeys = Object.keys(source);
|
|
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
}));
|
|
}
|
|
ownKeys.forEach(function(key) {
|
|
_defineProperty(target, key, source[key]);
|
|
});
|
|
}
|
|
return target;
|
|
}
|
|
function _slicedToArray(arr, i) {
|
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
|
|
}
|
|
function _arrayWithHoles(arr) {
|
|
if (Array.isArray(arr))
|
|
return arr;
|
|
}
|
|
function _iterableToArrayLimit(arr, i) {
|
|
var _arr = [];
|
|
var _n = true;
|
|
var _d = false;
|
|
var _e = void 0;
|
|
try {
|
|
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
|
_arr.push(_s.value);
|
|
if (i && _arr.length === i)
|
|
break;
|
|
}
|
|
} catch (err) {
|
|
_d = true;
|
|
_e = err;
|
|
} finally {
|
|
try {
|
|
if (!_n && _i["return"] != null)
|
|
_i["return"]();
|
|
} finally {
|
|
if (_d)
|
|
throw _e;
|
|
}
|
|
}
|
|
return _arr;
|
|
}
|
|
function _nonIterableRest() {
|
|
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
|
}
|
|
var noop = function noop2() {
|
|
};
|
|
var _WINDOW = {};
|
|
var _DOCUMENT = {};
|
|
var _MUTATION_OBSERVER = null;
|
|
var _PERFORMANCE = {
|
|
mark: noop,
|
|
measure: noop
|
|
};
|
|
try {
|
|
if (typeof window !== "undefined")
|
|
_WINDOW = window;
|
|
if (typeof document !== "undefined")
|
|
_DOCUMENT = document;
|
|
if (typeof MutationObserver !== "undefined")
|
|
_MUTATION_OBSERVER = MutationObserver;
|
|
if (typeof performance !== "undefined")
|
|
_PERFORMANCE = performance;
|
|
} catch (e) {
|
|
}
|
|
var _ref = _WINDOW.navigator || {};
|
|
var _ref$userAgent = _ref.userAgent;
|
|
var userAgent = _ref$userAgent === void 0 ? "" : _ref$userAgent;
|
|
var WINDOW = _WINDOW;
|
|
var DOCUMENT = _DOCUMENT;
|
|
var PERFORMANCE = _PERFORMANCE;
|
|
var IS_BROWSER = !!WINDOW.document;
|
|
var IS_DOM = !!DOCUMENT.documentElement && !!DOCUMENT.head && typeof DOCUMENT.addEventListener === "function" && typeof DOCUMENT.createElement === "function";
|
|
var IS_IE = ~userAgent.indexOf("MSIE") || ~userAgent.indexOf("Trident/");
|
|
var NAMESPACE_IDENTIFIER = "___FONT_AWESOME___";
|
|
var DEFAULT_FAMILY_PREFIX = "fa";
|
|
var DEFAULT_REPLACEMENT_CLASS = "svg-inline--fa";
|
|
var DATA_FA_I2SVG = "data-fa-i2svg";
|
|
var PRODUCTION = function() {
|
|
try {
|
|
return false;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}();
|
|
var oneToTen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
var oneToTwenty = oneToTen.concat([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
|
|
var DUOTONE_CLASSES = {
|
|
GROUP: "group",
|
|
SWAP_OPACITY: "swap-opacity",
|
|
PRIMARY: "primary",
|
|
SECONDARY: "secondary"
|
|
};
|
|
var RESERVED_CLASSES = ["xs", "sm", "lg", "fw", "ul", "li", "border", "pull-left", "pull-right", "spin", "pulse", "rotate-90", "rotate-180", "rotate-270", "flip-horizontal", "flip-vertical", "flip-both", "stack", "stack-1x", "stack-2x", "inverse", "layers", "layers-text", "layers-counter", DUOTONE_CLASSES.GROUP, DUOTONE_CLASSES.SWAP_OPACITY, DUOTONE_CLASSES.PRIMARY, DUOTONE_CLASSES.SECONDARY].concat(oneToTen.map(function(n) {
|
|
return "".concat(n, "x");
|
|
})).concat(oneToTwenty.map(function(n) {
|
|
return "w-".concat(n);
|
|
}));
|
|
var initial = WINDOW.FontAwesomeConfig || {};
|
|
function getAttrConfig(attr) {
|
|
var element = DOCUMENT.querySelector("script[" + attr + "]");
|
|
if (element) {
|
|
return element.getAttribute(attr);
|
|
}
|
|
}
|
|
function coerce(val) {
|
|
if (val === "")
|
|
return true;
|
|
if (val === "false")
|
|
return false;
|
|
if (val === "true")
|
|
return true;
|
|
return val;
|
|
}
|
|
if (DOCUMENT && typeof DOCUMENT.querySelector === "function") {
|
|
attrs = [["data-family-prefix", "familyPrefix"], ["data-replacement-class", "replacementClass"], ["data-auto-replace-svg", "autoReplaceSvg"], ["data-auto-add-css", "autoAddCss"], ["data-auto-a11y", "autoA11y"], ["data-search-pseudo-elements", "searchPseudoElements"], ["data-observe-mutations", "observeMutations"], ["data-mutate-approach", "mutateApproach"], ["data-keep-original-source", "keepOriginalSource"], ["data-measure-performance", "measurePerformance"], ["data-show-missing-icons", "showMissingIcons"]];
|
|
attrs.forEach(function(_ref2) {
|
|
var _ref22 = _slicedToArray(_ref2, 2), attr = _ref22[0], key = _ref22[1];
|
|
var val = coerce(getAttrConfig(attr));
|
|
if (val !== void 0 && val !== null) {
|
|
initial[key] = val;
|
|
}
|
|
});
|
|
}
|
|
var attrs;
|
|
var _default = {
|
|
familyPrefix: DEFAULT_FAMILY_PREFIX,
|
|
replacementClass: DEFAULT_REPLACEMENT_CLASS,
|
|
autoReplaceSvg: true,
|
|
autoAddCss: true,
|
|
autoA11y: true,
|
|
searchPseudoElements: false,
|
|
observeMutations: true,
|
|
mutateApproach: "async",
|
|
keepOriginalSource: true,
|
|
measurePerformance: false,
|
|
showMissingIcons: true
|
|
};
|
|
var _config = _objectSpread({}, _default, initial);
|
|
if (!_config.autoReplaceSvg)
|
|
_config.observeMutations = false;
|
|
var config = _objectSpread({}, _config);
|
|
WINDOW.FontAwesomeConfig = config;
|
|
var w = WINDOW || {};
|
|
if (!w[NAMESPACE_IDENTIFIER])
|
|
w[NAMESPACE_IDENTIFIER] = {};
|
|
if (!w[NAMESPACE_IDENTIFIER].styles)
|
|
w[NAMESPACE_IDENTIFIER].styles = {};
|
|
if (!w[NAMESPACE_IDENTIFIER].hooks)
|
|
w[NAMESPACE_IDENTIFIER].hooks = {};
|
|
if (!w[NAMESPACE_IDENTIFIER].shims)
|
|
w[NAMESPACE_IDENTIFIER].shims = [];
|
|
var namespace = w[NAMESPACE_IDENTIFIER];
|
|
var functions = [];
|
|
var listener = function listener2() {
|
|
DOCUMENT.removeEventListener("DOMContentLoaded", listener2);
|
|
loaded = 1;
|
|
functions.map(function(fn) {
|
|
return fn();
|
|
});
|
|
};
|
|
var loaded = false;
|
|
if (IS_DOM) {
|
|
loaded = (DOCUMENT.documentElement.doScroll ? /^loaded|^c/ : /^loaded|^i|^c/).test(DOCUMENT.readyState);
|
|
if (!loaded)
|
|
DOCUMENT.addEventListener("DOMContentLoaded", listener);
|
|
}
|
|
var PENDING = "pending";
|
|
var SETTLED = "settled";
|
|
var FULFILLED = "fulfilled";
|
|
var REJECTED = "rejected";
|
|
var NOOP = function NOOP2() {
|
|
};
|
|
var isNode = typeof global !== "undefined" && typeof global.process !== "undefined" && typeof global.process.emit === "function";
|
|
var asyncSetTimer = typeof setImmediate === "undefined" ? setTimeout : setImmediate;
|
|
var asyncQueue = [];
|
|
var asyncTimer;
|
|
function asyncFlush() {
|
|
for (var i = 0; i < asyncQueue.length; i++) {
|
|
asyncQueue[i][0](asyncQueue[i][1]);
|
|
}
|
|
asyncQueue = [];
|
|
asyncTimer = false;
|
|
}
|
|
function asyncCall(callback, arg) {
|
|
asyncQueue.push([callback, arg]);
|
|
if (!asyncTimer) {
|
|
asyncTimer = true;
|
|
asyncSetTimer(asyncFlush, 0);
|
|
}
|
|
}
|
|
function invokeResolver(resolver, promise) {
|
|
function resolvePromise(value) {
|
|
resolve(promise, value);
|
|
}
|
|
function rejectPromise(reason) {
|
|
reject(promise, reason);
|
|
}
|
|
try {
|
|
resolver(resolvePromise, rejectPromise);
|
|
} catch (e) {
|
|
rejectPromise(e);
|
|
}
|
|
}
|
|
function invokeCallback(subscriber) {
|
|
var owner = subscriber.owner;
|
|
var settled = owner._state;
|
|
var value = owner._data;
|
|
var callback = subscriber[settled];
|
|
var promise = subscriber.then;
|
|
if (typeof callback === "function") {
|
|
settled = FULFILLED;
|
|
try {
|
|
value = callback(value);
|
|
} catch (e) {
|
|
reject(promise, e);
|
|
}
|
|
}
|
|
if (!handleThenable(promise, value)) {
|
|
if (settled === FULFILLED) {
|
|
resolve(promise, value);
|
|
}
|
|
if (settled === REJECTED) {
|
|
reject(promise, value);
|
|
}
|
|
}
|
|
}
|
|
function handleThenable(promise, value) {
|
|
var resolved;
|
|
try {
|
|
if (promise === value) {
|
|
throw new TypeError("A promises callback cannot return that same promise.");
|
|
}
|
|
if (value && (typeof value === "function" || _typeof(value) === "object")) {
|
|
var then2 = value.then;
|
|
if (typeof then2 === "function") {
|
|
then2.call(value, function(val) {
|
|
if (!resolved) {
|
|
resolved = true;
|
|
if (value === val) {
|
|
fulfill(promise, val);
|
|
} else {
|
|
resolve(promise, val);
|
|
}
|
|
}
|
|
}, function(reason) {
|
|
if (!resolved) {
|
|
resolved = true;
|
|
reject(promise, reason);
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (!resolved) {
|
|
reject(promise, e);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function resolve(promise, value) {
|
|
if (promise === value || !handleThenable(promise, value)) {
|
|
fulfill(promise, value);
|
|
}
|
|
}
|
|
function fulfill(promise, value) {
|
|
if (promise._state === PENDING) {
|
|
promise._state = SETTLED;
|
|
promise._data = value;
|
|
asyncCall(publishFulfillment, promise);
|
|
}
|
|
}
|
|
function reject(promise, reason) {
|
|
if (promise._state === PENDING) {
|
|
promise._state = SETTLED;
|
|
promise._data = reason;
|
|
asyncCall(publishRejection, promise);
|
|
}
|
|
}
|
|
function publish(promise) {
|
|
promise._then = promise._then.forEach(invokeCallback);
|
|
}
|
|
function publishFulfillment(promise) {
|
|
promise._state = FULFILLED;
|
|
publish(promise);
|
|
}
|
|
function publishRejection(promise) {
|
|
promise._state = REJECTED;
|
|
publish(promise);
|
|
if (!promise._handled && isNode) {
|
|
global.process.emit("unhandledRejection", promise._data, promise);
|
|
}
|
|
}
|
|
function notifyRejectionHandled(promise) {
|
|
global.process.emit("rejectionHandled", promise);
|
|
}
|
|
function P(resolver) {
|
|
if (typeof resolver !== "function") {
|
|
throw new TypeError("Promise resolver " + resolver + " is not a function");
|
|
}
|
|
if (this instanceof P === false) {
|
|
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
|
|
}
|
|
this._then = [];
|
|
invokeResolver(resolver, this);
|
|
}
|
|
P.prototype = {
|
|
constructor: P,
|
|
_state: PENDING,
|
|
_then: null,
|
|
_data: void 0,
|
|
_handled: false,
|
|
then: function then(onFulfillment, onRejection) {
|
|
var subscriber = {
|
|
owner: this,
|
|
then: new this.constructor(NOOP),
|
|
fulfilled: onFulfillment,
|
|
rejected: onRejection
|
|
};
|
|
if ((onRejection || onFulfillment) && !this._handled) {
|
|
this._handled = true;
|
|
if (this._state === REJECTED && isNode) {
|
|
asyncCall(notifyRejectionHandled, this);
|
|
}
|
|
}
|
|
if (this._state === FULFILLED || this._state === REJECTED) {
|
|
asyncCall(invokeCallback, subscriber);
|
|
} else {
|
|
this._then.push(subscriber);
|
|
}
|
|
return subscriber.then;
|
|
},
|
|
catch: function _catch(onRejection) {
|
|
return this.then(null, onRejection);
|
|
}
|
|
};
|
|
P.all = function(promises) {
|
|
if (!Array.isArray(promises)) {
|
|
throw new TypeError("You must pass an array to Promise.all().");
|
|
}
|
|
return new P(function(resolve2, reject2) {
|
|
var results = [];
|
|
var remaining = 0;
|
|
function resolver(index) {
|
|
remaining++;
|
|
return function(value) {
|
|
results[index] = value;
|
|
if (!--remaining) {
|
|
resolve2(results);
|
|
}
|
|
};
|
|
}
|
|
for (var i = 0, promise; i < promises.length; i++) {
|
|
promise = promises[i];
|
|
if (promise && typeof promise.then === "function") {
|
|
promise.then(resolver(i), reject2);
|
|
} else {
|
|
results[i] = promise;
|
|
}
|
|
}
|
|
if (!remaining) {
|
|
resolve2(results);
|
|
}
|
|
});
|
|
};
|
|
P.race = function(promises) {
|
|
if (!Array.isArray(promises)) {
|
|
throw new TypeError("You must pass an array to Promise.race().");
|
|
}
|
|
return new P(function(resolve2, reject2) {
|
|
for (var i = 0, promise; i < promises.length; i++) {
|
|
promise = promises[i];
|
|
if (promise && typeof promise.then === "function") {
|
|
promise.then(resolve2, reject2);
|
|
} else {
|
|
resolve2(promise);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
P.resolve = function(value) {
|
|
if (value && _typeof(value) === "object" && value.constructor === P) {
|
|
return value;
|
|
}
|
|
return new P(function(resolve2) {
|
|
resolve2(value);
|
|
});
|
|
};
|
|
P.reject = function(reason) {
|
|
return new P(function(resolve2, reject2) {
|
|
reject2(reason);
|
|
});
|
|
};
|
|
var meaninglessTransform = {
|
|
size: 16,
|
|
x: 0,
|
|
y: 0,
|
|
rotate: 0,
|
|
flipX: false,
|
|
flipY: false
|
|
};
|
|
function insertCss(css2) {
|
|
if (!css2 || !IS_DOM) {
|
|
return;
|
|
}
|
|
var style = DOCUMENT.createElement("style");
|
|
style.setAttribute("type", "text/css");
|
|
style.innerHTML = css2;
|
|
var headChildren = DOCUMENT.head.childNodes;
|
|
var beforeChild = null;
|
|
for (var i = headChildren.length - 1; i > -1; i--) {
|
|
var child = headChildren[i];
|
|
var tagName = (child.tagName || "").toUpperCase();
|
|
if (["STYLE", "LINK"].indexOf(tagName) > -1) {
|
|
beforeChild = child;
|
|
}
|
|
}
|
|
DOCUMENT.head.insertBefore(style, beforeChild);
|
|
return css2;
|
|
}
|
|
var idPool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
function nextUniqueId() {
|
|
var size = 12;
|
|
var id = "";
|
|
while (size-- > 0) {
|
|
id += idPool[Math.random() * 62 | 0];
|
|
}
|
|
return id;
|
|
}
|
|
function htmlEscape(str) {
|
|
return "".concat(str).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
}
|
|
function joinAttributes(attributes) {
|
|
return Object.keys(attributes || {}).reduce(function(acc, attributeName) {
|
|
return acc + "".concat(attributeName, '="').concat(htmlEscape(attributes[attributeName]), '" ');
|
|
}, "").trim();
|
|
}
|
|
function joinStyles(styles2) {
|
|
return Object.keys(styles2 || {}).reduce(function(acc, styleName) {
|
|
return acc + "".concat(styleName, ": ").concat(styles2[styleName], ";");
|
|
}, "");
|
|
}
|
|
function transformIsMeaningful(transform) {
|
|
return transform.size !== meaninglessTransform.size || transform.x !== meaninglessTransform.x || transform.y !== meaninglessTransform.y || transform.rotate !== meaninglessTransform.rotate || transform.flipX || transform.flipY;
|
|
}
|
|
function transformForSvg(_ref2) {
|
|
var transform = _ref2.transform, containerWidth = _ref2.containerWidth, iconWidth = _ref2.iconWidth;
|
|
var outer = {
|
|
transform: "translate(".concat(containerWidth / 2, " 256)")
|
|
};
|
|
var innerTranslate = "translate(".concat(transform.x * 32, ", ").concat(transform.y * 32, ") ");
|
|
var innerScale = "scale(".concat(transform.size / 16 * (transform.flipX ? -1 : 1), ", ").concat(transform.size / 16 * (transform.flipY ? -1 : 1), ") ");
|
|
var innerRotate = "rotate(".concat(transform.rotate, " 0 0)");
|
|
var inner = {
|
|
transform: "".concat(innerTranslate, " ").concat(innerScale, " ").concat(innerRotate)
|
|
};
|
|
var path = {
|
|
transform: "translate(".concat(iconWidth / 2 * -1, " -256)")
|
|
};
|
|
return {
|
|
outer,
|
|
inner,
|
|
path
|
|
};
|
|
}
|
|
var ALL_SPACE = {
|
|
x: 0,
|
|
y: 0,
|
|
width: "100%",
|
|
height: "100%"
|
|
};
|
|
function fillBlack(abstract) {
|
|
var force = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
|
|
if (abstract.attributes && (abstract.attributes.fill || force)) {
|
|
abstract.attributes.fill = "black";
|
|
}
|
|
return abstract;
|
|
}
|
|
function deGroup(abstract) {
|
|
if (abstract.tag === "g") {
|
|
return abstract.children;
|
|
} else {
|
|
return [abstract];
|
|
}
|
|
}
|
|
function makeIconMasking(_ref2) {
|
|
var children = _ref2.children, attributes = _ref2.attributes, main = _ref2.main, mask = _ref2.mask, explicitMaskId = _ref2.maskId, transform = _ref2.transform;
|
|
var mainWidth = main.width, mainPath = main.icon;
|
|
var maskWidth = mask.width, maskPath = mask.icon;
|
|
var trans = transformForSvg({
|
|
transform,
|
|
containerWidth: maskWidth,
|
|
iconWidth: mainWidth
|
|
});
|
|
var maskRect = {
|
|
tag: "rect",
|
|
attributes: _objectSpread({}, ALL_SPACE, {
|
|
fill: "white"
|
|
})
|
|
};
|
|
var maskInnerGroupChildrenMixin = mainPath.children ? {
|
|
children: mainPath.children.map(fillBlack)
|
|
} : {};
|
|
var maskInnerGroup = {
|
|
tag: "g",
|
|
attributes: _objectSpread({}, trans.inner),
|
|
children: [fillBlack(_objectSpread({
|
|
tag: mainPath.tag,
|
|
attributes: _objectSpread({}, mainPath.attributes, trans.path)
|
|
}, maskInnerGroupChildrenMixin))]
|
|
};
|
|
var maskOuterGroup = {
|
|
tag: "g",
|
|
attributes: _objectSpread({}, trans.outer),
|
|
children: [maskInnerGroup]
|
|
};
|
|
var maskId = "mask-".concat(explicitMaskId || nextUniqueId());
|
|
var clipId = "clip-".concat(explicitMaskId || nextUniqueId());
|
|
var maskTag = {
|
|
tag: "mask",
|
|
attributes: _objectSpread({}, ALL_SPACE, {
|
|
id: maskId,
|
|
maskUnits: "userSpaceOnUse",
|
|
maskContentUnits: "userSpaceOnUse"
|
|
}),
|
|
children: [maskRect, maskOuterGroup]
|
|
};
|
|
var defs = {
|
|
tag: "defs",
|
|
children: [{
|
|
tag: "clipPath",
|
|
attributes: {
|
|
id: clipId
|
|
},
|
|
children: deGroup(maskPath)
|
|
}, maskTag]
|
|
};
|
|
children.push(defs, {
|
|
tag: "rect",
|
|
attributes: _objectSpread({
|
|
fill: "currentColor",
|
|
"clip-path": "url(#".concat(clipId, ")"),
|
|
mask: "url(#".concat(maskId, ")")
|
|
}, ALL_SPACE)
|
|
});
|
|
return {
|
|
children,
|
|
attributes
|
|
};
|
|
}
|
|
function makeIconStandard(_ref2) {
|
|
var children = _ref2.children, attributes = _ref2.attributes, main = _ref2.main, transform = _ref2.transform, styles2 = _ref2.styles;
|
|
var styleString = joinStyles(styles2);
|
|
if (styleString.length > 0) {
|
|
attributes["style"] = styleString;
|
|
}
|
|
if (transformIsMeaningful(transform)) {
|
|
var trans = transformForSvg({
|
|
transform,
|
|
containerWidth: main.width,
|
|
iconWidth: main.width
|
|
});
|
|
children.push({
|
|
tag: "g",
|
|
attributes: _objectSpread({}, trans.outer),
|
|
children: [{
|
|
tag: "g",
|
|
attributes: _objectSpread({}, trans.inner),
|
|
children: [{
|
|
tag: main.icon.tag,
|
|
children: main.icon.children,
|
|
attributes: _objectSpread({}, main.icon.attributes, trans.path)
|
|
}]
|
|
}]
|
|
});
|
|
} else {
|
|
children.push(main.icon);
|
|
}
|
|
return {
|
|
children,
|
|
attributes
|
|
};
|
|
}
|
|
function asIcon(_ref2) {
|
|
var children = _ref2.children, main = _ref2.main, mask = _ref2.mask, attributes = _ref2.attributes, styles2 = _ref2.styles, transform = _ref2.transform;
|
|
if (transformIsMeaningful(transform) && main.found && !mask.found) {
|
|
var width = main.width, height = main.height;
|
|
var offset = {
|
|
x: width / height / 2,
|
|
y: 0.5
|
|
};
|
|
attributes["style"] = joinStyles(_objectSpread({}, styles2, {
|
|
"transform-origin": "".concat(offset.x + transform.x / 16, "em ").concat(offset.y + transform.y / 16, "em")
|
|
}));
|
|
}
|
|
return [{
|
|
tag: "svg",
|
|
attributes,
|
|
children
|
|
}];
|
|
}
|
|
function asSymbol(_ref2) {
|
|
var prefix = _ref2.prefix, iconName = _ref2.iconName, children = _ref2.children, attributes = _ref2.attributes, symbol = _ref2.symbol;
|
|
var id = symbol === true ? "".concat(prefix, "-").concat(config.familyPrefix, "-").concat(iconName) : symbol;
|
|
return [{
|
|
tag: "svg",
|
|
attributes: {
|
|
style: "display: none;"
|
|
},
|
|
children: [{
|
|
tag: "symbol",
|
|
attributes: _objectSpread({}, attributes, {
|
|
id
|
|
}),
|
|
children
|
|
}]
|
|
}];
|
|
}
|
|
function makeInlineSvgAbstract(params) {
|
|
var _params$icons = params.icons, main = _params$icons.main, mask = _params$icons.mask, prefix = params.prefix, iconName = params.iconName, transform = params.transform, symbol = params.symbol, title = params.title, maskId = params.maskId, titleId = params.titleId, extra = params.extra, _params$watchable = params.watchable, watchable = _params$watchable === void 0 ? false : _params$watchable;
|
|
var _ref2 = mask.found ? mask : main, width = _ref2.width, height = _ref2.height;
|
|
var isUploadedIcon = prefix === "fak";
|
|
var widthClass = isUploadedIcon ? "" : "fa-w-".concat(Math.ceil(width / height * 16));
|
|
var attrClass = [config.replacementClass, iconName ? "".concat(config.familyPrefix, "-").concat(iconName) : "", widthClass].filter(function(c2) {
|
|
return extra.classes.indexOf(c2) === -1;
|
|
}).filter(function(c2) {
|
|
return c2 !== "" || !!c2;
|
|
}).concat(extra.classes).join(" ");
|
|
var content = {
|
|
children: [],
|
|
attributes: _objectSpread({}, extra.attributes, {
|
|
"data-prefix": prefix,
|
|
"data-icon": iconName,
|
|
"class": attrClass,
|
|
"role": extra.attributes.role || "img",
|
|
"xmlns": "http://www.w3.org/2000/svg",
|
|
"viewBox": "0 0 ".concat(width, " ").concat(height)
|
|
})
|
|
};
|
|
var uploadedIconWidthStyle = isUploadedIcon && !~extra.classes.indexOf("fa-fw") ? {
|
|
width: "".concat(width / height * 16 * 0.0625, "em")
|
|
} : {};
|
|
if (watchable) {
|
|
content.attributes[DATA_FA_I2SVG] = "";
|
|
}
|
|
if (title)
|
|
content.children.push({
|
|
tag: "title",
|
|
attributes: {
|
|
id: content.attributes["aria-labelledby"] || "title-".concat(titleId || nextUniqueId())
|
|
},
|
|
children: [title]
|
|
});
|
|
var args = _objectSpread({}, content, {
|
|
prefix,
|
|
iconName,
|
|
main,
|
|
mask,
|
|
maskId,
|
|
transform,
|
|
symbol,
|
|
styles: _objectSpread({}, uploadedIconWidthStyle, extra.styles)
|
|
});
|
|
var _ref22 = mask.found && main.found ? makeIconMasking(args) : makeIconStandard(args), children = _ref22.children, attributes = _ref22.attributes;
|
|
args.children = children;
|
|
args.attributes = attributes;
|
|
if (symbol) {
|
|
return asSymbol(args);
|
|
} else {
|
|
return asIcon(args);
|
|
}
|
|
}
|
|
var noop$1 = function noop3() {
|
|
};
|
|
var p = config.measurePerformance && PERFORMANCE && PERFORMANCE.mark && PERFORMANCE.measure ? PERFORMANCE : {
|
|
mark: noop$1,
|
|
measure: noop$1
|
|
};
|
|
var bindInternal4 = function bindInternal42(func, thisContext) {
|
|
return function(a2, b2, c2, d) {
|
|
return func.call(thisContext, a2, b2, c2, d);
|
|
};
|
|
};
|
|
var reduce = function fastReduceObject(subject, fn, initialValue, thisContext) {
|
|
var keys = Object.keys(subject), length = keys.length, iterator = thisContext !== void 0 ? bindInternal4(fn, thisContext) : fn, i, key, result;
|
|
if (initialValue === void 0) {
|
|
i = 1;
|
|
result = subject[keys[0]];
|
|
} else {
|
|
i = 0;
|
|
result = initialValue;
|
|
}
|
|
for (; i < length; i++) {
|
|
key = keys[i];
|
|
result = iterator(result, subject[key], key, subject);
|
|
}
|
|
return result;
|
|
};
|
|
function defineIcons(prefix, icons) {
|
|
var params = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
var _params$skipHooks = params.skipHooks, skipHooks = _params$skipHooks === void 0 ? false : _params$skipHooks;
|
|
var normalized = Object.keys(icons).reduce(function(acc, iconName) {
|
|
var icon2 = icons[iconName];
|
|
var expanded = !!icon2.icon;
|
|
if (expanded) {
|
|
acc[icon2.iconName] = icon2.icon;
|
|
} else {
|
|
acc[iconName] = icon2;
|
|
}
|
|
return acc;
|
|
}, {});
|
|
if (typeof namespace.hooks.addPack === "function" && !skipHooks) {
|
|
namespace.hooks.addPack(prefix, normalized);
|
|
} else {
|
|
namespace.styles[prefix] = _objectSpread({}, namespace.styles[prefix] || {}, normalized);
|
|
}
|
|
if (prefix === "fas") {
|
|
defineIcons("fa", icons);
|
|
}
|
|
}
|
|
var styles = namespace.styles;
|
|
var shims = namespace.shims;
|
|
var _byUnicode = {};
|
|
var _byLigature = {};
|
|
var _byOldName = {};
|
|
var build = function build2() {
|
|
var lookup = function lookup2(reducer) {
|
|
return reduce(styles, function(o, style, prefix) {
|
|
o[prefix] = reduce(style, reducer, {});
|
|
return o;
|
|
}, {});
|
|
};
|
|
_byUnicode = lookup(function(acc, icon2, iconName) {
|
|
if (icon2[3]) {
|
|
acc[icon2[3]] = iconName;
|
|
}
|
|
return acc;
|
|
});
|
|
_byLigature = lookup(function(acc, icon2, iconName) {
|
|
var ligatures = icon2[2];
|
|
acc[iconName] = iconName;
|
|
ligatures.forEach(function(ligature) {
|
|
acc[ligature] = iconName;
|
|
});
|
|
return acc;
|
|
});
|
|
var hasRegular = "far" in styles;
|
|
_byOldName = reduce(shims, function(acc, shim) {
|
|
var oldName = shim[0];
|
|
var prefix = shim[1];
|
|
var iconName = shim[2];
|
|
if (prefix === "far" && !hasRegular) {
|
|
prefix = "fas";
|
|
}
|
|
acc[oldName] = {
|
|
prefix,
|
|
iconName
|
|
};
|
|
return acc;
|
|
}, {});
|
|
};
|
|
build();
|
|
var styles$1 = namespace.styles;
|
|
function iconFromMapping(mapping, prefix, iconName) {
|
|
if (mapping && mapping[prefix] && mapping[prefix][iconName]) {
|
|
return {
|
|
prefix,
|
|
iconName,
|
|
icon: mapping[prefix][iconName]
|
|
};
|
|
}
|
|
}
|
|
function toHtml(abstractNodes) {
|
|
var tag = abstractNodes.tag, _abstractNodes$attrib = abstractNodes.attributes, attributes = _abstractNodes$attrib === void 0 ? {} : _abstractNodes$attrib, _abstractNodes$childr = abstractNodes.children, children = _abstractNodes$childr === void 0 ? [] : _abstractNodes$childr;
|
|
if (typeof abstractNodes === "string") {
|
|
return htmlEscape(abstractNodes);
|
|
} else {
|
|
return "<".concat(tag, " ").concat(joinAttributes(attributes), ">").concat(children.map(toHtml).join(""), "</").concat(tag, ">");
|
|
}
|
|
}
|
|
function MissingIcon(error) {
|
|
this.name = "MissingIcon";
|
|
this.message = error || "Icon unavailable";
|
|
this.stack = new Error().stack;
|
|
}
|
|
MissingIcon.prototype = Object.create(Error.prototype);
|
|
MissingIcon.prototype.constructor = MissingIcon;
|
|
var FILL = {
|
|
fill: "currentColor"
|
|
};
|
|
var ANIMATION_BASE = {
|
|
attributeType: "XML",
|
|
repeatCount: "indefinite",
|
|
dur: "2s"
|
|
};
|
|
var RING = {
|
|
tag: "path",
|
|
attributes: _objectSpread({}, FILL, {
|
|
d: "M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z"
|
|
})
|
|
};
|
|
var OPACITY_ANIMATE = _objectSpread({}, ANIMATION_BASE, {
|
|
attributeName: "opacity"
|
|
});
|
|
var DOT = {
|
|
tag: "circle",
|
|
attributes: _objectSpread({}, FILL, {
|
|
cx: "256",
|
|
cy: "364",
|
|
r: "28"
|
|
}),
|
|
children: [{
|
|
tag: "animate",
|
|
attributes: _objectSpread({}, ANIMATION_BASE, {
|
|
attributeName: "r",
|
|
values: "28;14;28;28;14;28;"
|
|
})
|
|
}, {
|
|
tag: "animate",
|
|
attributes: _objectSpread({}, OPACITY_ANIMATE, {
|
|
values: "1;0;1;1;0;1;"
|
|
})
|
|
}]
|
|
};
|
|
var QUESTION = {
|
|
tag: "path",
|
|
attributes: _objectSpread({}, FILL, {
|
|
opacity: "1",
|
|
d: "M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z"
|
|
}),
|
|
children: [{
|
|
tag: "animate",
|
|
attributes: _objectSpread({}, OPACITY_ANIMATE, {
|
|
values: "1;0;0;0;0;1;"
|
|
})
|
|
}]
|
|
};
|
|
var EXCLAMATION = {
|
|
tag: "path",
|
|
attributes: _objectSpread({}, FILL, {
|
|
opacity: "0",
|
|
d: "M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z"
|
|
}),
|
|
children: [{
|
|
tag: "animate",
|
|
attributes: _objectSpread({}, OPACITY_ANIMATE, {
|
|
values: "0;0;1;1;0;0;"
|
|
})
|
|
}]
|
|
};
|
|
var styles$2 = namespace.styles;
|
|
function asFoundIcon(icon2) {
|
|
var width = icon2[0];
|
|
var height = icon2[1];
|
|
var _icon$slice = icon2.slice(4), _icon$slice2 = _slicedToArray(_icon$slice, 1), vectorData = _icon$slice2[0];
|
|
var element = null;
|
|
if (Array.isArray(vectorData)) {
|
|
element = {
|
|
tag: "g",
|
|
attributes: {
|
|
class: "".concat(config.familyPrefix, "-").concat(DUOTONE_CLASSES.GROUP)
|
|
},
|
|
children: [{
|
|
tag: "path",
|
|
attributes: {
|
|
class: "".concat(config.familyPrefix, "-").concat(DUOTONE_CLASSES.SECONDARY),
|
|
fill: "currentColor",
|
|
d: vectorData[0]
|
|
}
|
|
}, {
|
|
tag: "path",
|
|
attributes: {
|
|
class: "".concat(config.familyPrefix, "-").concat(DUOTONE_CLASSES.PRIMARY),
|
|
fill: "currentColor",
|
|
d: vectorData[1]
|
|
}
|
|
}]
|
|
};
|
|
} else {
|
|
element = {
|
|
tag: "path",
|
|
attributes: {
|
|
fill: "currentColor",
|
|
d: vectorData
|
|
}
|
|
};
|
|
}
|
|
return {
|
|
found: true,
|
|
width,
|
|
height,
|
|
icon: element
|
|
};
|
|
}
|
|
var styles$3 = namespace.styles;
|
|
var baseStyles = 'svg:not(:root).svg-inline--fa {\n overflow: visible;\n}\n\n.svg-inline--fa {\n display: inline-block;\n font-size: inherit;\n height: 1em;\n overflow: visible;\n vertical-align: -0.125em;\n}\n.svg-inline--fa.fa-lg {\n vertical-align: -0.225em;\n}\n.svg-inline--fa.fa-w-1 {\n width: 0.0625em;\n}\n.svg-inline--fa.fa-w-2 {\n width: 0.125em;\n}\n.svg-inline--fa.fa-w-3 {\n width: 0.1875em;\n}\n.svg-inline--fa.fa-w-4 {\n width: 0.25em;\n}\n.svg-inline--fa.fa-w-5 {\n width: 0.3125em;\n}\n.svg-inline--fa.fa-w-6 {\n width: 0.375em;\n}\n.svg-inline--fa.fa-w-7 {\n width: 0.4375em;\n}\n.svg-inline--fa.fa-w-8 {\n width: 0.5em;\n}\n.svg-inline--fa.fa-w-9 {\n width: 0.5625em;\n}\n.svg-inline--fa.fa-w-10 {\n width: 0.625em;\n}\n.svg-inline--fa.fa-w-11 {\n width: 0.6875em;\n}\n.svg-inline--fa.fa-w-12 {\n width: 0.75em;\n}\n.svg-inline--fa.fa-w-13 {\n width: 0.8125em;\n}\n.svg-inline--fa.fa-w-14 {\n width: 0.875em;\n}\n.svg-inline--fa.fa-w-15 {\n width: 0.9375em;\n}\n.svg-inline--fa.fa-w-16 {\n width: 1em;\n}\n.svg-inline--fa.fa-w-17 {\n width: 1.0625em;\n}\n.svg-inline--fa.fa-w-18 {\n width: 1.125em;\n}\n.svg-inline--fa.fa-w-19 {\n width: 1.1875em;\n}\n.svg-inline--fa.fa-w-20 {\n width: 1.25em;\n}\n.svg-inline--fa.fa-pull-left {\n margin-right: 0.3em;\n width: auto;\n}\n.svg-inline--fa.fa-pull-right {\n margin-left: 0.3em;\n width: auto;\n}\n.svg-inline--fa.fa-border {\n height: 1.5em;\n}\n.svg-inline--fa.fa-li {\n width: 2em;\n}\n.svg-inline--fa.fa-fw {\n width: 1.25em;\n}\n\n.fa-layers svg.svg-inline--fa {\n bottom: 0;\n left: 0;\n margin: auto;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.fa-layers {\n display: inline-block;\n height: 1em;\n position: relative;\n text-align: center;\n vertical-align: -0.125em;\n width: 1em;\n}\n.fa-layers svg.svg-inline--fa {\n -webkit-transform-origin: center center;\n transform-origin: center center;\n}\n\n.fa-layers-counter, .fa-layers-text {\n display: inline-block;\n position: absolute;\n text-align: center;\n}\n\n.fa-layers-text {\n left: 50%;\n top: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n -webkit-transform-origin: center center;\n transform-origin: center center;\n}\n\n.fa-layers-counter {\n background-color: #ff253a;\n border-radius: 1em;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n color: #fff;\n height: 1.5em;\n line-height: 1;\n max-width: 5em;\n min-width: 1.5em;\n overflow: hidden;\n padding: 0.25em;\n right: 0;\n text-overflow: ellipsis;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top right;\n transform-origin: top right;\n}\n\n.fa-layers-bottom-right {\n bottom: 0;\n right: 0;\n top: auto;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: bottom right;\n transform-origin: bottom right;\n}\n\n.fa-layers-bottom-left {\n bottom: 0;\n left: 0;\n right: auto;\n top: auto;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: bottom left;\n transform-origin: bottom left;\n}\n\n.fa-layers-top-right {\n right: 0;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top right;\n transform-origin: top right;\n}\n\n.fa-layers-top-left {\n left: 0;\n right: auto;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top left;\n transform-origin: top left;\n}\n\n.fa-lg {\n font-size: 1.3333333333em;\n line-height: 0.75em;\n vertical-align: -0.0667em;\n}\n\n.fa-xs {\n font-size: 0.75em;\n}\n\n.fa-sm {\n font-size: 0.875em;\n}\n\n.fa-1x {\n font-size: 1em;\n}\n\n.fa-2x {\n font-size: 2em;\n}\n\n.fa-3x {\n font-size: 3em;\n}\n\n.fa-4x {\n font-size: 4em;\n}\n\n.fa-5x {\n font-size: 5em;\n}\n\n.fa-6x {\n font-size: 6em;\n}\n\n.fa-7x {\n font-size: 7em;\n}\n\n.fa-8x {\n font-size: 8em;\n}\n\n.fa-9x {\n font-size: 9em;\n}\n\n.fa-10x {\n font-size: 10em;\n}\n\n.fa-fw {\n text-align: center;\n width: 1.25em;\n}\n\n.fa-ul {\n list-style-type: none;\n margin-left: 2.5em;\n padding-left: 0;\n}\n.fa-ul > li {\n position: relative;\n}\n\n.fa-li {\n left: -2em;\n position: absolute;\n text-align: center;\n width: 2em;\n line-height: inherit;\n}\n\n.fa-border {\n border: solid 0.08em #eee;\n border-radius: 0.1em;\n padding: 0.2em 0.25em 0.15em;\n}\n\n.fa-pull-left {\n float: left;\n}\n\n.fa-pull-right {\n float: right;\n}\n\n.fa.fa-pull-left,\n.fas.fa-pull-left,\n.far.fa-pull-left,\n.fal.fa-pull-left,\n.fab.fa-pull-left {\n margin-right: 0.3em;\n}\n.fa.fa-pull-right,\n.fas.fa-pull-right,\n.far.fa-pull-right,\n.fal.fa-pull-right,\n.fab.fa-pull-right {\n margin-left: 0.3em;\n}\n\n.fa-spin {\n -webkit-animation: fa-spin 2s infinite linear;\n animation: fa-spin 2s infinite linear;\n}\n\n.fa-pulse {\n -webkit-animation: fa-spin 1s infinite steps(8);\n animation: fa-spin 1s infinite steps(8);\n}\n\n@-webkit-keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n@keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n.fa-rotate-90 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";\n -webkit-transform: rotate(90deg);\n transform: rotate(90deg);\n}\n\n.fa-rotate-180 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";\n -webkit-transform: rotate(180deg);\n transform: rotate(180deg);\n}\n\n.fa-rotate-270 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";\n -webkit-transform: rotate(270deg);\n transform: rotate(270deg);\n}\n\n.fa-flip-horizontal {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";\n -webkit-transform: scale(-1, 1);\n transform: scale(-1, 1);\n}\n\n.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(1, -1);\n transform: scale(1, -1);\n}\n\n.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(-1, -1);\n transform: scale(-1, -1);\n}\n\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical,\n:root .fa-flip-both {\n -webkit-filter: none;\n filter: none;\n}\n\n.fa-stack {\n display: inline-block;\n height: 2em;\n position: relative;\n width: 2.5em;\n}\n\n.fa-stack-1x,\n.fa-stack-2x {\n bottom: 0;\n left: 0;\n margin: auto;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.svg-inline--fa.fa-stack-1x {\n height: 1em;\n width: 1.25em;\n}\n.svg-inline--fa.fa-stack-2x {\n height: 2em;\n width: 2.5em;\n}\n\n.fa-inverse {\n color: #fff;\n}\n\n.sr-only {\n border: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n position: absolute;\n width: 1px;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n clip: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n position: static;\n width: auto;\n}\n\n.svg-inline--fa .fa-primary {\n fill: var(--fa-primary-color, currentColor);\n opacity: 1;\n opacity: var(--fa-primary-opacity, 1);\n}\n\n.svg-inline--fa .fa-secondary {\n fill: var(--fa-secondary-color, currentColor);\n opacity: 0.4;\n opacity: var(--fa-secondary-opacity, 0.4);\n}\n\n.svg-inline--fa.fa-swap-opacity .fa-primary {\n opacity: 0.4;\n opacity: var(--fa-secondary-opacity, 0.4);\n}\n\n.svg-inline--fa.fa-swap-opacity .fa-secondary {\n opacity: 1;\n opacity: var(--fa-primary-opacity, 1);\n}\n\n.svg-inline--fa mask .fa-primary,\n.svg-inline--fa mask .fa-secondary {\n fill: black;\n}\n\n.fad.fa-inverse {\n color: #fff;\n}';
|
|
function css() {
|
|
var dfp = DEFAULT_FAMILY_PREFIX;
|
|
var drc = DEFAULT_REPLACEMENT_CLASS;
|
|
var fp = config.familyPrefix;
|
|
var rc = config.replacementClass;
|
|
var s = baseStyles;
|
|
if (fp !== dfp || rc !== drc) {
|
|
var dPatt = new RegExp("\\.".concat(dfp, "\\-"), "g");
|
|
var customPropPatt = new RegExp("\\--".concat(dfp, "\\-"), "g");
|
|
var rPatt = new RegExp("\\.".concat(drc), "g");
|
|
s = s.replace(dPatt, ".".concat(fp, "-")).replace(customPropPatt, "--".concat(fp, "-")).replace(rPatt, ".".concat(rc));
|
|
}
|
|
return s;
|
|
}
|
|
var Library = /* @__PURE__ */ function() {
|
|
function Library2() {
|
|
_classCallCheck(this, Library2);
|
|
this.definitions = {};
|
|
}
|
|
_createClass(Library2, [{
|
|
key: "add",
|
|
value: function add() {
|
|
var _this = this;
|
|
for (var _len = arguments.length, definitions = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
definitions[_key] = arguments[_key];
|
|
}
|
|
var additions2 = definitions.reduce(this._pullDefinitions, {});
|
|
Object.keys(additions2).forEach(function(key) {
|
|
_this.definitions[key] = _objectSpread({}, _this.definitions[key] || {}, additions2[key]);
|
|
defineIcons(key, additions2[key]);
|
|
build();
|
|
});
|
|
}
|
|
}, {
|
|
key: "reset",
|
|
value: function reset() {
|
|
this.definitions = {};
|
|
}
|
|
}, {
|
|
key: "_pullDefinitions",
|
|
value: function _pullDefinitions(additions2, definition) {
|
|
var normalized = definition.prefix && definition.iconName && definition.icon ? {
|
|
0: definition
|
|
} : definition;
|
|
Object.keys(normalized).map(function(key) {
|
|
var _normalized$key = normalized[key], prefix = _normalized$key.prefix, iconName = _normalized$key.iconName, icon2 = _normalized$key.icon;
|
|
if (!additions2[prefix])
|
|
additions2[prefix] = {};
|
|
additions2[prefix][iconName] = icon2;
|
|
});
|
|
return additions2;
|
|
}
|
|
}]);
|
|
return Library2;
|
|
}();
|
|
function ensureCss() {
|
|
if (config.autoAddCss && !_cssInserted) {
|
|
insertCss(css());
|
|
_cssInserted = true;
|
|
}
|
|
}
|
|
function apiObject(val, abstractCreator) {
|
|
Object.defineProperty(val, "abstract", {
|
|
get: abstractCreator
|
|
});
|
|
Object.defineProperty(val, "html", {
|
|
get: function get() {
|
|
return val.abstract.map(function(a2) {
|
|
return toHtml(a2);
|
|
});
|
|
}
|
|
});
|
|
Object.defineProperty(val, "node", {
|
|
get: function get() {
|
|
if (!IS_DOM)
|
|
return;
|
|
var container = DOCUMENT.createElement("div");
|
|
container.innerHTML = val.html;
|
|
return container.children;
|
|
}
|
|
});
|
|
return val;
|
|
}
|
|
function findIconDefinition(iconLookup) {
|
|
var _iconLookup$prefix = iconLookup.prefix, prefix = _iconLookup$prefix === void 0 ? "fa" : _iconLookup$prefix, iconName = iconLookup.iconName;
|
|
if (!iconName)
|
|
return;
|
|
return iconFromMapping(library.definitions, prefix, iconName) || iconFromMapping(namespace.styles, prefix, iconName);
|
|
}
|
|
function resolveIcons(next) {
|
|
return function(maybeIconDefinition) {
|
|
var params = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
var iconDefinition = (maybeIconDefinition || {}).icon ? maybeIconDefinition : findIconDefinition(maybeIconDefinition || {});
|
|
var mask = params.mask;
|
|
if (mask) {
|
|
mask = (mask || {}).icon ? mask : findIconDefinition(mask || {});
|
|
}
|
|
return next(iconDefinition, _objectSpread({}, params, {
|
|
mask
|
|
}));
|
|
};
|
|
}
|
|
var library = new Library();
|
|
var _cssInserted = false;
|
|
var icon = resolveIcons(function(iconDefinition) {
|
|
var params = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
var _params$transform = params.transform, transform = _params$transform === void 0 ? meaninglessTransform : _params$transform, _params$symbol = params.symbol, symbol = _params$symbol === void 0 ? false : _params$symbol, _params$mask = params.mask, mask = _params$mask === void 0 ? null : _params$mask, _params$maskId = params.maskId, maskId = _params$maskId === void 0 ? null : _params$maskId, _params$title = params.title, title = _params$title === void 0 ? null : _params$title, _params$titleId = params.titleId, titleId = _params$titleId === void 0 ? null : _params$titleId, _params$classes = params.classes, classes = _params$classes === void 0 ? [] : _params$classes, _params$attributes = params.attributes, attributes = _params$attributes === void 0 ? {} : _params$attributes, _params$styles = params.styles, styles2 = _params$styles === void 0 ? {} : _params$styles;
|
|
if (!iconDefinition)
|
|
return;
|
|
var prefix = iconDefinition.prefix, iconName = iconDefinition.iconName, icon2 = iconDefinition.icon;
|
|
return apiObject(_objectSpread({
|
|
type: "icon"
|
|
}, iconDefinition), function() {
|
|
ensureCss();
|
|
if (config.autoA11y) {
|
|
if (title) {
|
|
attributes["aria-labelledby"] = "".concat(config.replacementClass, "-title-").concat(titleId || nextUniqueId());
|
|
} else {
|
|
attributes["aria-hidden"] = "true";
|
|
attributes["focusable"] = "false";
|
|
}
|
|
}
|
|
return makeInlineSvgAbstract({
|
|
icons: {
|
|
main: asFoundIcon(icon2),
|
|
mask: mask ? asFoundIcon(mask.icon) : {
|
|
found: false,
|
|
width: null,
|
|
height: null,
|
|
icon: {}
|
|
}
|
|
},
|
|
prefix,
|
|
iconName,
|
|
transform: _objectSpread({}, meaninglessTransform, transform),
|
|
symbol,
|
|
title,
|
|
maskId,
|
|
titleId,
|
|
extra: {
|
|
attributes,
|
|
styles: styles2,
|
|
classes
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
// src/parser/parser.ts
|
|
var Parser = class {
|
|
constructor(table) {
|
|
this.table = table;
|
|
}
|
|
parse(input) {
|
|
var length = input.length, table = this.table, output = [], stack = [], index = 0;
|
|
while (index < length) {
|
|
var token = input[index++];
|
|
switch (token.data) {
|
|
case "(":
|
|
stack.unshift(token);
|
|
break;
|
|
case ")":
|
|
if (input[index] && input[index].type == "dice" && /^d/.test(input[index].original)) {
|
|
input[index].parenedDice = true;
|
|
}
|
|
while (stack.length) {
|
|
var token = stack.shift();
|
|
if (token.data === "(")
|
|
break;
|
|
else {
|
|
output.push(token);
|
|
}
|
|
}
|
|
if (token.data !== "(")
|
|
throw new Error("Mismatched parentheses.");
|
|
break;
|
|
default:
|
|
if (table.hasOwnProperty(token.data)) {
|
|
while (stack.length) {
|
|
var punctuator = stack[0];
|
|
if (punctuator.data === "(")
|
|
break;
|
|
var operator = table[token.data], precedence = operator.precedence, antecedence = table[punctuator.data].precedence;
|
|
if (precedence > antecedence || precedence === antecedence && operator.associativity === "right")
|
|
break;
|
|
else
|
|
output.push(stack.shift());
|
|
}
|
|
stack.unshift(token);
|
|
} else {
|
|
output.push(token);
|
|
}
|
|
}
|
|
}
|
|
while (stack.length) {
|
|
var token = stack.shift();
|
|
if (token.data !== "(")
|
|
output.push(token);
|
|
else
|
|
throw new Error("Mismatched parentheses.");
|
|
}
|
|
return output;
|
|
}
|
|
};
|
|
|
|
// node_modules/monkey-around/mjs/index.js
|
|
function around(obj, factories) {
|
|
const removers = Object.keys(factories).map((key) => around1(obj, key, factories[key]));
|
|
return removers.length === 1 ? removers[0] : function() {
|
|
removers.forEach((r) => r());
|
|
};
|
|
}
|
|
function around1(obj, method, createWrapper) {
|
|
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
|
|
let current = createWrapper(original);
|
|
if (original)
|
|
Object.setPrototypeOf(current, original);
|
|
Object.setPrototypeOf(wrapper, current);
|
|
obj[method] = wrapper;
|
|
return remove;
|
|
function wrapper(...args) {
|
|
if (current === original && obj[method] === wrapper)
|
|
remove();
|
|
return current.apply(this, args);
|
|
}
|
|
function remove() {
|
|
if (obj[method] === wrapper) {
|
|
if (hadOwn)
|
|
obj[method] = original;
|
|
else
|
|
delete obj[method];
|
|
}
|
|
if (current === original)
|
|
return;
|
|
current = original;
|
|
Object.setPrototypeOf(wrapper, original || Function);
|
|
}
|
|
}
|
|
|
|
// src/main.ts
|
|
var import_he = __toModule(require_he());
|
|
|
|
// src/utils/constants.ts
|
|
var TAG_REGEX = /(?:(?<roll>\d+)[Dd])?#(?<tag>[\p{Letter}\p{Emoji_Presentation}\w/-]+)(?:\|(?<collapse>[\+-]))?(?:\|(?<types>[^\+-]+))?/u;
|
|
var TABLE_REGEX = /(?:(?<roll>\d+)[Dd])?\[\[(?<link>[\s\S]+?)#?\^(?<block>[\s\S]+?)\]\]\|?(?<header>[\s\S]+)?/;
|
|
var SECTION_REGEX = /(?:(?<roll>\d+)[Dd])?\[\[(?<link>[\s\S]+)\]\]\|?(?<types>[\s\S]+)?/;
|
|
var MATH_REGEX = /[\(\^\+\-\*\/\)]/;
|
|
var OMITTED_REGEX = /(?<roll>\d+)?[Dd](?<faces>\[?(?:-?\d+\s?,)?\s?(?:-?\d+|%|F)\]?)?(?<conditional>(?:(?:=|=!|<|>|<=|>=|=<|=>|\-=|=\-)\d+)*)?/;
|
|
var CONDITIONAL_REGEX = /(?:(?<operator>=|=!|<|>|<=|>=|=<|=>|\-=|=\-)(?<comparer>\d+))/g;
|
|
var ICON_DEFINITION = "dice-roller-icon";
|
|
var COPY_DEFINITION = "dice-roller-copy";
|
|
|
|
// src/roller/dice.ts
|
|
var import_obsidian2 = __toModule(require("obsidian"));
|
|
|
|
// src/utils/util.ts
|
|
function _insertIntoMap(map, index, value) {
|
|
let toUpdate = [...map].slice(index).reverse();
|
|
toUpdate.forEach(([key, value2]) => {
|
|
map.set(key + 1, value2);
|
|
});
|
|
map.set(index, value);
|
|
}
|
|
|
|
// src/roller/roller.ts
|
|
var import_obsidian = __toModule(require("obsidian"));
|
|
var BasicRoller = class extends import_obsidian.Events {
|
|
constructor(plugin, original, lexemes, showDice = plugin.data.showDice) {
|
|
super();
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexemes = lexemes;
|
|
this.showDice = showDice;
|
|
this.loaded = false;
|
|
this.containerEl = createDiv({
|
|
cls: "dice-roller",
|
|
attr: {
|
|
"aria-label-position": "top",
|
|
"data-dice": this.original
|
|
}
|
|
});
|
|
this.save = false;
|
|
this.resultEl = this.containerEl.createDiv("dice-roller-result");
|
|
if (this.showDice) {
|
|
const icon2 = this.containerEl.createDiv({
|
|
cls: "dice-roller-button"
|
|
});
|
|
(0, import_obsidian.setIcon)(icon2, ICON_DEFINITION);
|
|
icon2.onclick = this.onClick.bind(this);
|
|
} else {
|
|
this.containerEl.addClass("no-icon");
|
|
}
|
|
this.containerEl.onclick = this.onClick.bind(this);
|
|
}
|
|
setTooltip() {
|
|
if (this.plugin.data.displayResultsInline)
|
|
return;
|
|
this.containerEl.setAttrs({
|
|
"aria-label": this.tooltip
|
|
});
|
|
}
|
|
getRandomBetween(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
async render() {
|
|
this.setTooltip();
|
|
await this.build();
|
|
}
|
|
get inlineText() {
|
|
return `${this.tooltip.split("\n").join(" -> ")} -> `;
|
|
}
|
|
async onClick(evt) {
|
|
evt.stopPropagation();
|
|
evt.stopImmediatePropagation();
|
|
if (window.getSelection()?.isCollapsed) {
|
|
await this.roll();
|
|
}
|
|
}
|
|
};
|
|
var GenericRoller = class extends BasicRoller {
|
|
};
|
|
var GenericFileRoller = class extends GenericRoller {
|
|
constructor(plugin, original, lexeme, source, showDice = plugin.data.showDice) {
|
|
super(plugin, original, [lexeme], showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexeme = lexeme;
|
|
this.source = source;
|
|
this.watch = true;
|
|
this.getPath();
|
|
this.getFile();
|
|
}
|
|
async getFile() {
|
|
this.file = this.plugin.app.metadataCache.getFirstLinkpathDest(this.path, this.source);
|
|
if (!this.file || !(this.file instanceof import_obsidian.TFile))
|
|
throw new Error("Could not load file.");
|
|
await this.load();
|
|
this.registerFileWatcher();
|
|
}
|
|
registerFileWatcher() {
|
|
this.plugin.registerEvent(this.plugin.app.vault.on("modify", async (file) => {
|
|
if (!this.watch)
|
|
return;
|
|
if (this.save)
|
|
return;
|
|
if (file !== this.file)
|
|
return;
|
|
await this.getOptions();
|
|
}));
|
|
}
|
|
};
|
|
|
|
// src/roller/dice.ts
|
|
var DiceRoller = class {
|
|
constructor(dice, lexeme = {
|
|
original: dice,
|
|
conditionals: [],
|
|
type: "dice",
|
|
data: dice
|
|
}) {
|
|
this.lexeme = lexeme;
|
|
this.modifiers = /* @__PURE__ */ new Map();
|
|
this.modifiersAllowed = true;
|
|
this.static = false;
|
|
this.conditions = [];
|
|
this.fudge = false;
|
|
if (!/(\-?\d+)[dD]?(\d+|%|\[\d+,\s?\d+\])?/.test(dice)) {
|
|
throw new Error("Non parseable dice string passed to DiceRoll.");
|
|
}
|
|
this.dice = dice.split(" ").join("");
|
|
if (/^-?\d+$/.test(this.dice)) {
|
|
this.static = true;
|
|
this.modifiersAllowed = false;
|
|
}
|
|
let [, rolls, min = null, max = 1] = this.dice.match(/(\-?\d+)[dD]\[?(?:(-?\d+)\s?,)?\s?(-?\d+|%|F)\]?/) || [, 1, null, 1];
|
|
this.multiplier = rolls < 0 ? -1 : 1;
|
|
this.rolls = Math.abs(Number(rolls)) || 1;
|
|
if (Number(max) < 0 && !min) {
|
|
min = -1;
|
|
}
|
|
if (max === "%")
|
|
max = 100;
|
|
if (max === "F") {
|
|
max = 1;
|
|
min = -1;
|
|
this.fudge = true;
|
|
}
|
|
if (Number(max) < Number(min)) {
|
|
[max, min] = [min, max];
|
|
}
|
|
this.faces = { max: max ? Number(max) : 1, min: min ? Number(min) : 1 };
|
|
this.conditions = this.lexeme.conditionals ?? [];
|
|
this.results = new Map([...this.roll()].map((n, i) => {
|
|
return [
|
|
i,
|
|
{
|
|
usable: true,
|
|
value: n,
|
|
display: `${n}`,
|
|
modifiers: /* @__PURE__ */ new Set()
|
|
}
|
|
];
|
|
}));
|
|
}
|
|
get text() {
|
|
return `${this.result}`;
|
|
}
|
|
get result() {
|
|
if (this.static) {
|
|
return Number(this.dice);
|
|
}
|
|
const results = [...this.results].map(([, { usable, value }]) => usable ? value : 0);
|
|
return results.reduce((a2, b2) => a2 + b2, 0);
|
|
}
|
|
get display() {
|
|
if (this.static) {
|
|
return `${this.result}`;
|
|
}
|
|
return `[${[...this.results].map(([, { modifiers, display }]) => `${display}${[...modifiers].join("")}`).join(", ")}]`;
|
|
}
|
|
keepLow(drop = 1) {
|
|
if (!this.modifiersAllowed) {
|
|
new import_obsidian2.Notice("Modifiers are only allowed on dice rolls.");
|
|
return;
|
|
}
|
|
[...this.results].sort((a2, b2) => a2[1].value - b2[1].value).slice(drop - this.results.size).forEach(([index]) => {
|
|
const previous = this.results.get(index);
|
|
previous.usable = false;
|
|
previous.modifiers.add("d");
|
|
this.results.set(index, { ...previous });
|
|
});
|
|
}
|
|
keepHigh(drop = 1) {
|
|
if (!this.modifiersAllowed) {
|
|
new import_obsidian2.Notice("Modifiers are only allowed on dice rolls.");
|
|
return;
|
|
}
|
|
[...this.results].sort((a2, b2) => b2[1].value - a2[1].value).slice(drop).forEach(([index]) => {
|
|
const previous = this.results.get(index);
|
|
previous.usable = false;
|
|
previous.modifiers.add("d");
|
|
this.results.set(index, { ...previous });
|
|
});
|
|
}
|
|
reroll(times, conditionals) {
|
|
if (!this.modifiersAllowed) {
|
|
new import_obsidian2.Notice("Modifiers are only allowed on dice rolls.");
|
|
return;
|
|
}
|
|
if (!conditionals.length) {
|
|
conditionals.push({
|
|
operator: "=",
|
|
comparer: this.faces.min
|
|
});
|
|
}
|
|
let i = 0, toReroll = [...this.results].filter(([, { value }]) => this.checkCondition(value, conditionals));
|
|
while (i < times && toReroll.filter(([, { value }]) => this.checkCondition(value, conditionals)).length > 0) {
|
|
i++;
|
|
toReroll.map(([, roll]) => {
|
|
roll.modifiers.add("r");
|
|
roll.value = this.getRandomBetween(this.faces.min, this.faces.max);
|
|
});
|
|
}
|
|
toReroll.forEach(([index, value]) => {
|
|
this.results.set(index, value);
|
|
});
|
|
}
|
|
explodeAndCombine(times, conditionals) {
|
|
if (!this.modifiersAllowed) {
|
|
new import_obsidian2.Notice("Modifiers are only allowed on dice rolls.");
|
|
return;
|
|
}
|
|
if (!conditionals.length) {
|
|
conditionals.push({
|
|
operator: "=",
|
|
comparer: this.faces.max
|
|
});
|
|
}
|
|
let i = 0, toExplode = [...this.results].filter(([, { value }]) => this.checkCondition(value, conditionals));
|
|
toExplode.forEach(([index, value]) => {
|
|
let newRoll = this.getRandomBetween(this.faces.min, this.faces.max);
|
|
i++;
|
|
value.modifiers.add("!");
|
|
value.value += newRoll;
|
|
value.display = `${value.value}`;
|
|
this.results.set(index, value);
|
|
while (i < times && this.checkCondition(newRoll, conditionals)) {
|
|
i++;
|
|
newRoll = this.getRandomBetween(this.faces.min, this.faces.max);
|
|
value.value += newRoll;
|
|
value.display = `${value.value}`;
|
|
this.results.set(index, value);
|
|
}
|
|
});
|
|
}
|
|
explode(times, conditionals) {
|
|
if (!this.modifiersAllowed) {
|
|
new import_obsidian2.Notice("Modifiers are only allowed on dice rolls.");
|
|
return;
|
|
}
|
|
if (!conditionals.length) {
|
|
conditionals.push({
|
|
operator: "=",
|
|
comparer: this.faces.max
|
|
});
|
|
}
|
|
let toExplode = [...this.results].filter(([, { value }]) => this.checkCondition(value, conditionals));
|
|
let inserted = 0;
|
|
toExplode.forEach(([key, value]) => {
|
|
let newRoll = value.value;
|
|
let i = 0;
|
|
while (i < times && this.checkCondition(newRoll, conditionals)) {
|
|
let previous = this.results.get(key + inserted + i);
|
|
previous.modifiers.add("!");
|
|
newRoll = this.getRandomBetween(this.faces.min, this.faces.max);
|
|
_insertIntoMap(this.results, key + inserted + i + 1, {
|
|
usable: true,
|
|
value: newRoll,
|
|
display: `${newRoll}`,
|
|
modifiers: /* @__PURE__ */ new Set()
|
|
});
|
|
i++;
|
|
}
|
|
inserted += i;
|
|
});
|
|
}
|
|
_roll() {
|
|
if (this.static) {
|
|
return [Number(this.dice)];
|
|
}
|
|
return [...Array(this.rolls)].map(() => this.multiplier * this.getRandomBetween(this.faces.min, this.faces.max));
|
|
}
|
|
setResults(results) {
|
|
this.results = new Map([...results].map((n, i) => {
|
|
return [
|
|
i,
|
|
{
|
|
usable: true,
|
|
value: n,
|
|
display: `${n}`,
|
|
modifiers: /* @__PURE__ */ new Set()
|
|
}
|
|
];
|
|
}));
|
|
}
|
|
roll() {
|
|
const roll = this._roll();
|
|
this.results = new Map([...roll].map((n, i) => {
|
|
return [
|
|
i,
|
|
{
|
|
usable: true,
|
|
value: n,
|
|
display: `${n}`,
|
|
modifiers: /* @__PURE__ */ new Set()
|
|
}
|
|
];
|
|
}));
|
|
for (let [type, modifier] of this.modifiers) {
|
|
this.applyModifier(type, modifier);
|
|
}
|
|
if (this.conditions?.length)
|
|
this.applyConditions();
|
|
return roll;
|
|
}
|
|
applyConditions() {
|
|
for (let [index, result] of this.results) {
|
|
const negate = this.conditions.find(({ operator }) => operator === "-=" || operator === "=-");
|
|
if (negate) {
|
|
if (result.value === negate.comparer) {
|
|
result.value = -1;
|
|
result.modifiers.add("-");
|
|
continue;
|
|
}
|
|
}
|
|
const check = this.checkCondition(result.value, this.conditions);
|
|
if (!check) {
|
|
result.usable = false;
|
|
} else {
|
|
result.modifiers.add("*");
|
|
result.value = 1;
|
|
}
|
|
}
|
|
}
|
|
applyModifier(type, modifier) {
|
|
switch (type) {
|
|
case "kh": {
|
|
this.keepHigh(modifier.data);
|
|
break;
|
|
}
|
|
case "kl": {
|
|
this.keepLow(modifier.data);
|
|
break;
|
|
}
|
|
case "!": {
|
|
this.explode(modifier.data, modifier.conditionals);
|
|
break;
|
|
}
|
|
case "!!": {
|
|
this.explodeAndCombine(modifier.data, modifier.conditionals);
|
|
break;
|
|
}
|
|
case "r": {
|
|
this.reroll(modifier.data, modifier.conditionals);
|
|
break;
|
|
}
|
|
case "condition": {
|
|
}
|
|
}
|
|
}
|
|
checkCondition(value, conditions) {
|
|
if (!conditions || !conditions.length)
|
|
return value;
|
|
return conditions.some(({ operator, comparer }) => {
|
|
if (Number.isNaN(value) || Number.isNaN(comparer)) {
|
|
return false;
|
|
}
|
|
let result = false;
|
|
switch (operator) {
|
|
case "=":
|
|
result = value === comparer;
|
|
break;
|
|
case "!=":
|
|
case "=!":
|
|
result = value !== comparer;
|
|
break;
|
|
case "<":
|
|
result = value < comparer;
|
|
break;
|
|
case "<=":
|
|
result = value <= comparer;
|
|
break;
|
|
case ">":
|
|
result = value > comparer;
|
|
break;
|
|
case ">=":
|
|
result = value >= comparer;
|
|
break;
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
getRandomBetween(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
};
|
|
var StuntRoller = class extends DiceRoller {
|
|
constructor(dice, lexeme) {
|
|
super(`3d6`, lexeme);
|
|
this.dice = dice;
|
|
this.lexeme = lexeme;
|
|
}
|
|
get doubles() {
|
|
return new Set([...this.results].map(([, { usable, value }]) => usable ? value : 0)).size < 3;
|
|
}
|
|
get result() {
|
|
if (this.static) {
|
|
return Number(this.dice);
|
|
}
|
|
const results = [...this.results].map(([, { usable, value }]) => usable ? value : 0);
|
|
return results.reduce((a2, b2) => a2 + b2, 0);
|
|
}
|
|
get display() {
|
|
let str = [];
|
|
for (let result of this.results) {
|
|
if (result[0] == 0 && this.doubles) {
|
|
str.push(`${result[1].value}S`);
|
|
continue;
|
|
}
|
|
str.push(`${result[1].value}`);
|
|
}
|
|
return `[${str.join(", ")}]`;
|
|
}
|
|
};
|
|
var PercentRoller = class extends DiceRoller {
|
|
constructor(dice, lexeme) {
|
|
super(dice, lexeme);
|
|
this.dice = dice;
|
|
this.lexeme = lexeme;
|
|
this.stack = [];
|
|
const faces = `${this.faces.max}`.split("");
|
|
for (let i = 0; i < this.rolls; i++) {
|
|
const stack = [];
|
|
for (const face of faces) {
|
|
const roller = new DiceRoller(`1d${face}`);
|
|
stack.push(roller);
|
|
roller.roll();
|
|
}
|
|
this.stack.push(stack);
|
|
}
|
|
}
|
|
get result() {
|
|
return this.stack.map((stack) => Number(stack.map((dice) => dice.result).join(""))).reduce((a2, b2) => a2 + b2);
|
|
}
|
|
get display() {
|
|
return this.stack.map((stack) => stack.map((v) => v.result).join(",")).join("|");
|
|
}
|
|
roll() {
|
|
if (!this.stack || !this.stack.length)
|
|
return super.roll();
|
|
this.stack.forEach((stack) => stack.map((dice) => dice.roll()));
|
|
return [
|
|
...this.stack.map((stack) => stack.map((dice) => dice.result)).flat()
|
|
];
|
|
}
|
|
};
|
|
var StackRoller = class extends GenericRoller {
|
|
constructor(plugin, original, lexemes, showDice = plugin.data.showDice) {
|
|
super(plugin, original, lexemes, showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexemes = lexemes;
|
|
this.stunted = "";
|
|
this.shouldRender = false;
|
|
this.operators = {
|
|
"+": (a2, b2) => a2 + b2,
|
|
"-": (a2, b2) => a2 - b2,
|
|
"*": (a2, b2) => a2 * b2,
|
|
"/": (a2, b2) => a2 / b2,
|
|
"^": (a2, b2) => {
|
|
return Math.pow(a2, b2);
|
|
}
|
|
};
|
|
this.stack = [];
|
|
this.stackCopy = [];
|
|
this.dice = [];
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
get replacer() {
|
|
return `${this.result}`;
|
|
}
|
|
get resultText() {
|
|
let text = [];
|
|
let index = 0;
|
|
this.dice.forEach((dice) => {
|
|
const slice = this.original.slice(index);
|
|
text.push(slice.slice(0, slice.indexOf(dice.lexeme.original)), dice.display);
|
|
index += slice.indexOf(dice.lexeme.original) + dice.lexeme.original.length;
|
|
});
|
|
return text.join("");
|
|
}
|
|
get tooltip() {
|
|
if (this._tooltip)
|
|
return this._tooltip;
|
|
return `${this.original}
|
|
${this.resultText}`;
|
|
}
|
|
async build() {
|
|
const result = [
|
|
this.result.toLocaleString(navigator.language, {
|
|
maximumFractionDigits: 2
|
|
})
|
|
];
|
|
if (this.plugin.data.displayResultsInline) {
|
|
result.unshift(this.inlineText);
|
|
}
|
|
this.resultEl.setText(result.join("") + this.stunted);
|
|
}
|
|
async onClick(evt) {
|
|
evt.stopPropagation();
|
|
evt.stopImmediatePropagation();
|
|
if (window.getSelection()?.isCollapsed) {
|
|
await this.roll();
|
|
}
|
|
}
|
|
get dynamic() {
|
|
return this.dice.filter((d) => !d.static);
|
|
}
|
|
get static() {
|
|
return this.dice.filter((d) => d.static);
|
|
}
|
|
get isStatic() {
|
|
return this.dice.every((d) => d.static);
|
|
}
|
|
async roll() {
|
|
let index = 0;
|
|
this.stunted = "";
|
|
if (this.shouldRender) {
|
|
await this.plugin.renderRoll(this);
|
|
} else {
|
|
for (const dice of this.lexemes) {
|
|
switch (dice.type) {
|
|
case "+":
|
|
case "-":
|
|
case "*":
|
|
case "/":
|
|
case "^":
|
|
case "math":
|
|
let b2 = this.stack.pop(), a2 = this.stack.pop();
|
|
if (!a2) {
|
|
if (dice.data === "-") {
|
|
b2 = new DiceRoller(`-${b2.dice}`, b2.lexeme);
|
|
}
|
|
this.stackCopy.push(dice.data);
|
|
this.stack.push(b2);
|
|
continue;
|
|
}
|
|
b2.roll();
|
|
if (b2 instanceof StuntRoller) {
|
|
if (b2.doubles) {
|
|
this.stunted = ` - ${b2.results.get(0).value} Stunt Points`;
|
|
}
|
|
}
|
|
a2.roll();
|
|
if (a2 instanceof StuntRoller) {
|
|
if (a2.doubles) {
|
|
this.stunted = ` - ${a2.results.get(0).value} Stunt Points`;
|
|
}
|
|
}
|
|
const result = this.operators[dice.data](a2.result, b2.result);
|
|
this.stackCopy.push(dice.data);
|
|
this.stack.push(new DiceRoller(`${result}`, dice));
|
|
break;
|
|
case "kh": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = dice.data ? Number(dice.data) : 1;
|
|
diceInstance.modifiers.set("kh", {
|
|
data,
|
|
conditionals: []
|
|
});
|
|
break;
|
|
}
|
|
case "dl": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = dice.data ? Number(dice.data) : 1;
|
|
data = diceInstance.results.size - data;
|
|
diceInstance.modifiers.set("kh", {
|
|
data,
|
|
conditionals: []
|
|
});
|
|
break;
|
|
}
|
|
case "kl": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = dice.data ? Number(dice.data) : 1;
|
|
diceInstance.modifiers.set("kl", {
|
|
data,
|
|
conditionals: []
|
|
});
|
|
break;
|
|
}
|
|
case "dh": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = dice.data ? Number(dice.data) : 1;
|
|
data = diceInstance.results.size - data;
|
|
diceInstance.modifiers.set("kl", {
|
|
data,
|
|
conditionals: []
|
|
});
|
|
break;
|
|
}
|
|
case "!": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = Number(dice.data) || 1;
|
|
diceInstance.modifiers.set("!", {
|
|
data,
|
|
conditionals: dice.conditionals
|
|
});
|
|
break;
|
|
}
|
|
case "!!": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = Number(dice.data) || 1;
|
|
diceInstance.modifiers.set("!!", {
|
|
data,
|
|
conditionals: dice.conditionals
|
|
});
|
|
break;
|
|
}
|
|
case "r": {
|
|
let diceInstance = this.dice[index - 1];
|
|
let data = Number(dice.data) || 1;
|
|
diceInstance.modifiers.set("r", {
|
|
data,
|
|
conditionals: dice.conditionals
|
|
});
|
|
break;
|
|
}
|
|
case "dice": {
|
|
if (dice.parenedDice && /^d/.test(dice.original) && this.stack.length) {
|
|
const previous = this.stack.pop();
|
|
dice.data = `${previous.result}${dice.original}`;
|
|
this.dice[index] = new DiceRoller(dice.data, dice);
|
|
}
|
|
if (!this.dice[index]) {
|
|
this.dice[index] = new DiceRoller(dice.data, dice);
|
|
}
|
|
this.stack.push(this.dice[index]);
|
|
this.stackCopy.push(this.dice[index]);
|
|
index++;
|
|
break;
|
|
}
|
|
case "stunt": {
|
|
if (!this.dice[index]) {
|
|
this.dice[index] = new StuntRoller(dice.original, dice);
|
|
}
|
|
this.stack.push(this.dice[index]);
|
|
this.stackCopy.push(this.dice[index]);
|
|
index++;
|
|
break;
|
|
}
|
|
case "%": {
|
|
if (!this.dice[index]) {
|
|
this.dice[index] = new PercentRoller(dice.original, dice);
|
|
}
|
|
this.stack.push(this.dice[index]);
|
|
this.stackCopy.push(this.dice[index]);
|
|
index++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
const final = this.stack.pop();
|
|
final.roll();
|
|
if (final instanceof StuntRoller) {
|
|
if (final.doubles) {
|
|
this.stunted = ` - ${final.results.get(0).value} Stunt Points`;
|
|
}
|
|
}
|
|
this.result = final.result;
|
|
this._tooltip = null;
|
|
}
|
|
this.render();
|
|
this.trigger("new-result");
|
|
return this.result;
|
|
}
|
|
recalculate() {
|
|
let stack = [];
|
|
let result = 0;
|
|
for (let item of this.stackCopy) {
|
|
if (typeof item === "string") {
|
|
let b2 = stack.pop(), a2 = stack.pop();
|
|
if (!a2) {
|
|
if (item === "-") {
|
|
b2 = new DiceRoller(`-${b2.result}`, b2.lexeme);
|
|
}
|
|
stack.push(b2);
|
|
continue;
|
|
}
|
|
const r = this.operators[item](a2.result, b2.result);
|
|
stack.push(new DiceRoller(`${r}`));
|
|
} else {
|
|
stack.push(item);
|
|
}
|
|
}
|
|
if (stack.length && stack[0] instanceof DiceRoller) {
|
|
result += stack[0].result;
|
|
}
|
|
this.result = result;
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "dice",
|
|
result: this.result,
|
|
tooltip: this.tooltip
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "dice")
|
|
return;
|
|
if (result.result) {
|
|
this.result = result.result;
|
|
}
|
|
if (result.tooltip) {
|
|
this._tooltip = result.tooltip;
|
|
}
|
|
await this.render();
|
|
}
|
|
setResult(result) {
|
|
}
|
|
};
|
|
|
|
// src/roller/section.ts
|
|
var import_obsidian3 = __toModule(require("obsidian"));
|
|
function nanoid(num) {
|
|
let result = "";
|
|
const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
const charactersLength = characters.length;
|
|
for (let i = 0; i < num; i++) {
|
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
}
|
|
return result;
|
|
}
|
|
function blockid(len) {
|
|
return `dice-${nanoid(4)}`;
|
|
}
|
|
var SectionRoller = class extends GenericFileRoller {
|
|
constructor(plugin, original, lexeme, source, inline = true, showDice = plugin.data.showDice) {
|
|
super(plugin, original, lexeme, source, showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexeme = lexeme;
|
|
this.inline = inline;
|
|
this.containerEl.addClasses(["has-embed", "markdown-embed"]);
|
|
this.resultEl.addClass("internal-embed");
|
|
this.resultEl.setAttrs({ src: source });
|
|
this.copy = this.containerEl.createDiv({
|
|
cls: "dice-content-copy dice-roller-button no-show",
|
|
attr: { "aria-label": "Copy Contents" }
|
|
});
|
|
this.copy.addEventListener("click", (evt) => {
|
|
evt.stopPropagation();
|
|
navigator.clipboard.writeText(this.displayFromCache(...this.results).trim()).then(async () => {
|
|
new import_obsidian3.Notice("Result copied to clipboard.");
|
|
});
|
|
});
|
|
(0, import_obsidian3.setIcon)(this.copy, COPY_DEFINITION);
|
|
}
|
|
get replacer() {
|
|
const blockID = this.getBlockId(this.result);
|
|
if (blockID) {
|
|
return `![[${this.path}#^${blockID}]]`;
|
|
}
|
|
return ``;
|
|
}
|
|
get tooltip() {
|
|
return `${this.original}
|
|
${this.path}`;
|
|
}
|
|
async build() {
|
|
this.resultEl.empty();
|
|
if (this.plugin.data.displayResultsInline && this.inline) {
|
|
this.resultEl.createSpan({
|
|
text: this.inlineText
|
|
});
|
|
}
|
|
if (!this.results || !this.results.length) {
|
|
this.resultEl.createDiv({
|
|
cls: "dice-no-results",
|
|
text: "No results."
|
|
});
|
|
return;
|
|
}
|
|
if (this.plugin.data.copyContentButton) {
|
|
this.copy.removeClass("no-show");
|
|
}
|
|
for (const result of this.results) {
|
|
this.resultEl.onclick = async (evt) => {
|
|
if (evt && evt.getModifierState("Control") || evt.getModifierState("Meta")) {
|
|
evt.stopPropagation();
|
|
return;
|
|
}
|
|
};
|
|
const ret = this.resultEl.createDiv({
|
|
cls: "markdown-embed"
|
|
});
|
|
if (!this.plugin.data.displayResultsInline) {
|
|
const type = "type" in result ? result.type : "List Item";
|
|
ret.setAttrs({
|
|
"aria-label": `${this.file.basename}: ${type}`
|
|
});
|
|
}
|
|
if (!result) {
|
|
ret.createDiv({
|
|
cls: "dice-no-results",
|
|
text: "No results."
|
|
});
|
|
continue;
|
|
}
|
|
import_obsidian3.MarkdownRenderer.renderMarkdown(this.displayFromCache(result), ret.createDiv(), this.source, null);
|
|
if (this.plugin.data.copyContentButton && this.results.length > 1) {
|
|
let copy = ret.createDiv({
|
|
cls: "dice-content-copy dice-roller-button",
|
|
attr: { "aria-label": "Copy Contents" }
|
|
});
|
|
copy.addEventListener("click", (evt) => {
|
|
evt.stopPropagation();
|
|
navigator.clipboard.writeText(this.displayFromCache(result).trim()).then(async () => {
|
|
new import_obsidian3.Notice("Result copied to clipboard.");
|
|
});
|
|
});
|
|
(0, import_obsidian3.setIcon)(copy, COPY_DEFINITION);
|
|
}
|
|
}
|
|
}
|
|
async load() {
|
|
await this.getOptions();
|
|
}
|
|
displayFromCache(...caches) {
|
|
let res = [];
|
|
for (let cache of caches) {
|
|
res.push(this.content.slice(cache.position.start.offset, cache.position.end.offset));
|
|
}
|
|
return res.join("\n\n");
|
|
}
|
|
getBlockId(cache) {
|
|
const blocks = this.cache.blocks ?? {};
|
|
const block = Object.entries(blocks).find(([id, block2]) => {
|
|
return samePosition(block2.position, cache.position);
|
|
});
|
|
if (!block) {
|
|
const blockID = `${blockid(4)}`;
|
|
const content = `${this.content.slice(0, this.result.position.end.offset + 1)}^${blockID}${this.content.slice(this.result.position.end.offset)}`;
|
|
this.watch = false;
|
|
this.plugin.app.vault.modify(this.file, content);
|
|
return blockID;
|
|
}
|
|
return block[0];
|
|
}
|
|
getPath() {
|
|
const { groups } = this.lexeme.data.match(SECTION_REGEX);
|
|
const { roll = 1, link, types } = groups;
|
|
if (!link)
|
|
throw new Error("Could not parse link.");
|
|
this.rolls = (roll && !isNaN(Number(roll)) && Number(roll)) ?? 1;
|
|
this.path = link.replace(/(\[|\])/g, "");
|
|
this.types = types?.split(",");
|
|
this.levels = types?.split(",").map((type) => /heading\-\d+/.test(type) ? type.split("-").pop() : null).filter((t) => t);
|
|
this.types = types?.split(",").map((type) => /heading\-\d+/.test(type) ? type.split("-").shift() : type);
|
|
}
|
|
async getOptions() {
|
|
this.cache = this.plugin.app.metadataCache.getFileCache(this.file);
|
|
if (!this.cache || !this.cache.sections) {
|
|
throw new Error("Could not read file cache.");
|
|
}
|
|
this.content = await this.plugin.app.vault.cachedRead(this.file);
|
|
this.options = this.cache.sections.filter(({ type, position }) => {
|
|
if (!this.types)
|
|
return !["yaml", "thematicBreak"].includes(type);
|
|
if (type == "heading" && this.types.includes(type) && this.levels.length) {
|
|
const headings = (this.cache.headings ?? []).filter(({ level }) => this.levels.includes(`${level}`));
|
|
return headings.some(({ position: pos }) => samePosition(pos, position));
|
|
}
|
|
return this.types.includes(type);
|
|
});
|
|
if (this.types && this.types.includes("listItem")) {
|
|
this.options.push(...this.cache.listItems);
|
|
}
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
async roll() {
|
|
return new Promise((resolve2, reject2) => {
|
|
if (!this.loaded) {
|
|
this.on("loaded", () => {
|
|
const options = [...this.options];
|
|
this.results = [...Array(this.rolls)].map(() => {
|
|
let option = options[this.getRandomBetween(0, options.length - 1)];
|
|
options.splice(options.indexOf(option), 1);
|
|
return option;
|
|
}).filter((r) => r);
|
|
this.render();
|
|
this.trigger("new-result");
|
|
this.result = this.results[0];
|
|
resolve2(this.results[0]);
|
|
});
|
|
} else {
|
|
const options = [...this.options];
|
|
this.results = [...Array(this.rolls)].map(() => {
|
|
let option = options[this.getRandomBetween(0, options.length - 1)];
|
|
options.splice(options.indexOf(option), 1);
|
|
return option;
|
|
}).filter((r) => r);
|
|
this.render();
|
|
this.trigger("new-result");
|
|
this.result = this.results[0];
|
|
resolve2(this.results[0]);
|
|
}
|
|
});
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "section",
|
|
result: this.results
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "section")
|
|
return;
|
|
if (result.result) {
|
|
this.results = result.result;
|
|
}
|
|
await this.render();
|
|
}
|
|
};
|
|
var TagRoller = class extends GenericRoller {
|
|
constructor(plugin, original, lexeme, source, showDice = plugin.data.showDice) {
|
|
super(plugin, original, [lexeme], showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexeme = lexeme;
|
|
this.source = source;
|
|
this.loaded = false;
|
|
if (!this.plugin.canUseDataview) {
|
|
new import_obsidian3.Notice("A tag can only be rolled with the Dataview plugin enabled.");
|
|
throw new Error("A tag can only be rolled with the Dataview plugin enabled.");
|
|
}
|
|
this.containerEl.addClasses(["has-embed", "markdown-embed"]);
|
|
const {
|
|
roll = 1,
|
|
tag,
|
|
collapse,
|
|
types
|
|
} = lexeme.data.match(TAG_REGEX).groups;
|
|
this.collapse = collapse === "-" ? true : collapse === "+" ? false : !this.plugin.data.returnAllTags;
|
|
this.tag = `#${tag}`;
|
|
this.rolls = Number(roll);
|
|
this.types = types;
|
|
this.getFiles();
|
|
}
|
|
get replacer() {
|
|
return this.result.replacer;
|
|
}
|
|
get typeText() {
|
|
if (!this.types?.length) {
|
|
return "";
|
|
}
|
|
return `|${this.types}`;
|
|
}
|
|
async getFiles() {
|
|
await this.plugin.dataviewReady();
|
|
const files = this.plugin.dataview.index.tags.invMap.get(this.tag);
|
|
if (files)
|
|
files.delete(this.source);
|
|
if (!files || !files.size) {
|
|
throw new Error("No files found with that tag. Is the tag correct?\n\n" + this.tag);
|
|
}
|
|
const links = Array.from(files).map((file) => `${this.rolls}d[[${file}]]${this.typeText}`);
|
|
this.results = links.map((link) => {
|
|
return new SectionRoller(this.plugin, link, {
|
|
data: link,
|
|
original: link,
|
|
conditionals: null,
|
|
type: "section"
|
|
}, this.source, false);
|
|
});
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
async build() {
|
|
this.resultEl.empty();
|
|
if (this.plugin.data.displayResultsInline) {
|
|
this.resultEl.createSpan({
|
|
text: this.inlineText
|
|
});
|
|
}
|
|
if (this.collapse) {
|
|
this.chosen = this.random ?? this.getRandomBetween(0, this.results.length - 1);
|
|
let section = this.results[this.chosen];
|
|
this.random = null;
|
|
const container = this.resultEl.createDiv();
|
|
container.createEl("h5", {
|
|
cls: "dice-file-name",
|
|
text: section.file.basename
|
|
});
|
|
container.appendChild(section.containerEl);
|
|
} else {
|
|
for (let section of this.results) {
|
|
const container = this.resultEl.createDiv();
|
|
container.createEl("h5", {
|
|
cls: "dice-file-name",
|
|
text: section.file.basename
|
|
});
|
|
container.appendChild(section.containerEl);
|
|
}
|
|
}
|
|
}
|
|
async roll() {
|
|
return new Promise((resolve2, reject2) => {
|
|
if (this.loaded) {
|
|
this.results.forEach(async (section) => await section.roll());
|
|
this.render();
|
|
this.trigger("new-result");
|
|
this.result = this.results[0];
|
|
resolve2(this.result);
|
|
} else {
|
|
this.on("loaded", () => {
|
|
this.results.forEach(async (section) => await section.roll());
|
|
this.render();
|
|
this.trigger("new-result");
|
|
this.result = this.results[0];
|
|
resolve2(this.result);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
get tooltip() {
|
|
return this.original;
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "tag",
|
|
random: this.chosen,
|
|
result: Object.fromEntries(this.results.map((section) => [
|
|
section.path,
|
|
section.toResult()
|
|
]))
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "tag")
|
|
return;
|
|
if (result.result) {
|
|
for (let path in result.result) {
|
|
const section = this.results.find((section2) => section2.path === path);
|
|
if (!section)
|
|
continue;
|
|
section.applyResult(result.result[path]);
|
|
}
|
|
}
|
|
if (result.random) {
|
|
this.random = result.random;
|
|
}
|
|
await this.render();
|
|
}
|
|
};
|
|
var LinkRoller = class extends GenericRoller {
|
|
constructor(plugin, original, lexeme, source, showDice = plugin.data.showDice) {
|
|
super(plugin, original, [lexeme], showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexeme = lexeme;
|
|
this.source = source;
|
|
const { roll = 1, tag } = lexeme.data.match(TAG_REGEX).groups;
|
|
this.tag = `#${tag}`;
|
|
this.rolls = (roll && !isNaN(Number(roll)) && Number(roll)) ?? 1;
|
|
this.getFiles();
|
|
}
|
|
get replacer() {
|
|
return `[[${this.result.basename}]]`;
|
|
}
|
|
get tooltip() {
|
|
return `${this.original}
|
|
${this.result.basename}`;
|
|
}
|
|
async roll() {
|
|
return new Promise((resolve2, reject2) => {
|
|
if (this.loaded) {
|
|
this.result = this.links[this.getRandomBetween(0, this.links.length - 1)];
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.result);
|
|
} else {
|
|
this.on("loaded", () => {
|
|
this.result = this.links[this.getRandomBetween(0, this.links.length - 1)];
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.result);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
async build() {
|
|
this.resultEl.empty();
|
|
if (this.plugin.data.displayResultsInline) {
|
|
this.resultEl.createSpan({
|
|
text: this.inlineText
|
|
});
|
|
}
|
|
const link = this.resultEl.createEl("a", {
|
|
cls: "internal-link",
|
|
text: this.result.basename
|
|
});
|
|
link.onclick = async (evt) => {
|
|
evt.stopPropagation();
|
|
this.plugin.app.workspace.openLinkText(this.result.path, this.plugin.app.workspace.getActiveFile()?.path, true);
|
|
};
|
|
link.onmouseenter = async (evt) => {
|
|
this.plugin.app.workspace.trigger("link-hover", this, link, this.result.path, this.plugin.app.workspace.getActiveFile()?.path);
|
|
};
|
|
}
|
|
async getFiles() {
|
|
await this.plugin.dataviewReady();
|
|
const files = this.plugin.dataview.index.tags.invMap.get(this.tag);
|
|
if (files)
|
|
files.delete(this.source);
|
|
if (!files || !files.size) {
|
|
throw new Error("No files found with that tag. Is the tag correct?\n\n" + this.tag);
|
|
}
|
|
this.links = Array.from(files).map((link) => this.plugin.app.metadataCache.getFirstLinkpathDest(link, this.source));
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "link",
|
|
result: this.result.path
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "link")
|
|
return;
|
|
if (result.result) {
|
|
const file = this.plugin.app.vault.getAbstractFileByPath(result.result);
|
|
if (file && file instanceof import_obsidian3.TFile) {
|
|
this.result = file;
|
|
}
|
|
}
|
|
await this.render();
|
|
}
|
|
};
|
|
var LineRoller = class extends GenericFileRoller {
|
|
constructor(plugin, original, lexeme, source, inline = true, showDice = plugin.data.showDice) {
|
|
super(plugin, original, lexeme, source, showDice);
|
|
this.plugin = plugin;
|
|
this.original = original;
|
|
this.lexeme = lexeme;
|
|
this.inline = inline;
|
|
this.containerEl.addClasses(["has-embed", "markdown-embed"]);
|
|
this.resultEl.addClass("internal-embed");
|
|
this.resultEl.setAttrs({ src: source });
|
|
this.copy = this.containerEl.createDiv({
|
|
cls: "dice-content-copy dice-roller-button no-show",
|
|
attr: { "aria-label": "Copy Contents" }
|
|
});
|
|
this.copy.addEventListener("click", (evt) => {
|
|
evt.stopPropagation();
|
|
navigator.clipboard.writeText(this.results.join("\n")).then(async () => {
|
|
new import_obsidian3.Notice("Result copied to clipboard.");
|
|
});
|
|
});
|
|
(0, import_obsidian3.setIcon)(this.copy, COPY_DEFINITION);
|
|
}
|
|
get replacer() {
|
|
return this.result;
|
|
}
|
|
get tooltip() {
|
|
return `${this.original}
|
|
${this.path}`;
|
|
}
|
|
async build() {
|
|
this.resultEl.empty();
|
|
if (this.plugin.data.displayResultsInline && this.inline) {
|
|
this.resultEl.createSpan({
|
|
text: this.inlineText
|
|
});
|
|
}
|
|
if (!this.results || !this.results.length) {
|
|
this.resultEl.createDiv({
|
|
cls: "dice-no-results",
|
|
text: "No results."
|
|
});
|
|
return;
|
|
}
|
|
if (this.plugin.data.copyContentButton) {
|
|
this.copy.removeClass("no-show");
|
|
}
|
|
for (const result of this.results) {
|
|
this.resultEl.onclick = async (evt) => {
|
|
if (evt && evt.getModifierState("Control") || evt.getModifierState("Meta")) {
|
|
evt.stopPropagation();
|
|
return;
|
|
}
|
|
};
|
|
const ret = this.resultEl.createDiv({
|
|
cls: "markdown-embed"
|
|
});
|
|
if (!result) {
|
|
ret.createDiv({
|
|
cls: "dice-no-results",
|
|
text: "No results."
|
|
});
|
|
continue;
|
|
}
|
|
import_obsidian3.MarkdownRenderer.renderMarkdown(result, ret.createDiv(), this.source, null);
|
|
if (this.plugin.data.copyContentButton && this.results.length > 1) {
|
|
let copy = ret.createDiv({
|
|
cls: "dice-content-copy dice-roller-button",
|
|
attr: { "aria-label": "Copy Contents" }
|
|
});
|
|
copy.addEventListener("click", (evt) => {
|
|
evt.stopPropagation();
|
|
navigator.clipboard.writeText(result).then(async () => {
|
|
new import_obsidian3.Notice("Result copied to clipboard.");
|
|
});
|
|
});
|
|
(0, import_obsidian3.setIcon)(copy, COPY_DEFINITION);
|
|
}
|
|
}
|
|
}
|
|
async load() {
|
|
await this.getOptions();
|
|
}
|
|
getPath() {
|
|
const { groups } = this.lexeme.data.match(SECTION_REGEX);
|
|
const { roll = 1, link, types } = groups;
|
|
if (!link)
|
|
throw new Error("Could not parse link.");
|
|
this.rolls = (roll && !isNaN(Number(roll)) && Number(roll)) ?? 1;
|
|
this.path = link.replace(/(\[|\])/g, "");
|
|
this.types = types?.split(",");
|
|
}
|
|
async getOptions() {
|
|
this.content = await this.plugin.app.vault.cachedRead(this.file);
|
|
if (!this.content) {
|
|
throw new Error("Could not read file cache.");
|
|
}
|
|
this.options = this.content.trim().split("\n").map((c2) => c2.trim()).filter((c2) => c2 && c2.length);
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
async roll() {
|
|
return new Promise((resolve2, reject2) => {
|
|
if (!this.loaded) {
|
|
this.on("loaded", () => {
|
|
const options = [...this.options];
|
|
this.results = [...Array(this.rolls)].map(() => {
|
|
let option = options[this.getRandomBetween(0, options.length - 1)];
|
|
options.splice(options.indexOf(option), 1);
|
|
return option;
|
|
}).filter((r) => r);
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.results[0]);
|
|
});
|
|
} else {
|
|
const options = [...this.options];
|
|
this.results = [...Array(this.rolls)].map(() => {
|
|
let option = options[this.getRandomBetween(0, options.length - 1)];
|
|
options.splice(options.indexOf(option), 1);
|
|
return option;
|
|
}).filter((r) => r);
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.results[0]);
|
|
}
|
|
});
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "section",
|
|
result: this.results
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "section")
|
|
return;
|
|
if (result.result) {
|
|
this.results = result.result;
|
|
}
|
|
await this.render();
|
|
}
|
|
};
|
|
var samePosition = (pos, pos2) => {
|
|
return pos.start.col == pos2.start.col && pos.start.line == pos2.start.line && pos.start.offset == pos2.start.offset;
|
|
};
|
|
|
|
// src/roller/table.ts
|
|
var import_obsidian4 = __toModule(require("obsidian"));
|
|
var TableRoller = class extends GenericFileRoller {
|
|
getPath() {
|
|
const { groups } = this.lexeme.data.match(TABLE_REGEX);
|
|
const { roll = 1, link, block, header } = groups;
|
|
if (!link || !block)
|
|
throw new Error("Could not parse link.");
|
|
this.rolls = (roll && !isNaN(Number(roll)) && Number(roll)) ?? 1;
|
|
this.path = link.replace(/(\[|\])/g, "");
|
|
this.block = block.replace(/(\^|#)/g, "").trim().toLowerCase();
|
|
this.header = header;
|
|
}
|
|
get tooltip() {
|
|
return `${this.original}
|
|
${this.path} > ${this.block}${this.header ? " | " + this.header : ""}`;
|
|
}
|
|
get replacer() {
|
|
return this.result;
|
|
}
|
|
async build() {
|
|
this.resultEl.empty();
|
|
const result = [this.result];
|
|
if (this.plugin.data.displayResultsInline) {
|
|
result.unshift(this.inlineText);
|
|
}
|
|
import_obsidian4.MarkdownRenderer.renderMarkdown(result.join(""), this.resultEl.createSpan("embedded-table-result"), this.source, null);
|
|
}
|
|
async getResult() {
|
|
if (this.isLookup) {
|
|
const result = await this.lookupRoller.roll();
|
|
const option = this.lookupRanges.find(([range]) => range[1] === void 0 && result === range[0] || result >= range[0] && range[1] >= result);
|
|
if (option) {
|
|
return option[1];
|
|
}
|
|
}
|
|
const options = [...this.options];
|
|
return [...Array(this.rolls)].map(() => {
|
|
let option = options[this.getRandomBetween(0, options.length - 1)];
|
|
options.splice(options.indexOf(option), 1);
|
|
return option;
|
|
}).join("||");
|
|
}
|
|
async roll() {
|
|
return new Promise(async (resolve2) => {
|
|
if (this.loaded) {
|
|
this.result = await this.getResult();
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.result);
|
|
} else {
|
|
this.on("loaded", async () => {
|
|
this.result = await this.getResult();
|
|
this.render();
|
|
this.trigger("new-result");
|
|
resolve2(this.result);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
async load() {
|
|
await this.getOptions();
|
|
}
|
|
async getOptions() {
|
|
this.cache = this.plugin.app.metadataCache.getFileCache(this.file);
|
|
if (!this.cache || !this.cache.blocks || !(this.block in this.cache.blocks)) {
|
|
throw new Error(`Could not read file cache. Does the block reference exist?
|
|
|
|
${this.path} > ${this.block}`);
|
|
}
|
|
const section = this.cache.sections?.find((s) => s.position == this.cache.blocks[this.block].position);
|
|
this.position = this.cache.blocks[this.block].position;
|
|
this.content = (await this.plugin.app.vault.cachedRead(this.file))?.slice(this.position.start.offset, this.position.end.offset);
|
|
if (section && section.type === "list") {
|
|
this.options = this.content.split("\n");
|
|
} else {
|
|
let table = extract(this.content);
|
|
if (Object.keys(table.columns).length === 2 && /dice:\s*([\s\S]+)\s*?/.test(Object.keys(table.columns)[0])) {
|
|
const roller = this.plugin.getRoller(Object.keys(table.columns)[0].split(":").pop(), this.source);
|
|
if (roller instanceof StackRoller) {
|
|
this.lookupRoller = roller;
|
|
await this.lookupRoller.roll();
|
|
this.lookupRanges = table.rows.map((row) => {
|
|
const [range, option] = row.split("|").map((str) => str.replace("{ESCAPED_PIPE}", "|")).map((s) => s.trim());
|
|
let [, min, max] = range.match(/(\d+)(?:[^\d]+?(\d+))?/) ?? [];
|
|
if (!min && !max)
|
|
return;
|
|
return [
|
|
[Number(min), max ? Number(max) : void 0],
|
|
option
|
|
];
|
|
});
|
|
this.isLookup = true;
|
|
}
|
|
}
|
|
if (this.header && table.columns[this.header]) {
|
|
this.options = table.columns[this.header];
|
|
} else {
|
|
if (this.header) {
|
|
throw new Error(`Header ${this.header} was not found in table ${this.path} > ${this.block}.`);
|
|
}
|
|
this.options = table.rows;
|
|
}
|
|
}
|
|
this.loaded = true;
|
|
this.trigger("loaded");
|
|
}
|
|
toResult() {
|
|
return {
|
|
type: "table",
|
|
result: this.result
|
|
};
|
|
}
|
|
async applyResult(result) {
|
|
if (result.type !== "table")
|
|
return;
|
|
if (result.result) {
|
|
this.result = result.result;
|
|
}
|
|
await this.render();
|
|
}
|
|
};
|
|
var MATCH = /^\|?([\s\S]+?)\|?$/;
|
|
var SPLIT = /\|/;
|
|
function extract(content) {
|
|
const lines = content.split("\n");
|
|
const inner = lines.map((l) => (l.trim().match(MATCH) ?? [, l.trim()])[1]);
|
|
const headers = inner[0].replace("\\|", "{ESCAPED_PIPE}").split(SPLIT);
|
|
const rows = [];
|
|
const ret = [];
|
|
for (let index in headers) {
|
|
let header = headers[index];
|
|
if (!header.trim().length)
|
|
header = index;
|
|
ret.push([header.trim(), []]);
|
|
}
|
|
for (let line of lines.slice(2)) {
|
|
const entries = line.trim().replace("\\|", "{ESCAPED_PIPE}").split(SPLIT).map((e) => e.trim()).filter((e) => e.length);
|
|
rows.push(entries.join(" | "));
|
|
for (let index in entries) {
|
|
const entry = entries[index].trim();
|
|
if (!entry.length || !ret[index])
|
|
continue;
|
|
ret[index][1].push(entry);
|
|
}
|
|
}
|
|
return {
|
|
columns: Object.fromEntries(ret),
|
|
rows
|
|
};
|
|
}
|
|
|
|
// src/settings/settings.ts
|
|
var import_obsidian5 = __toModule(require("obsidian"));
|
|
var SettingTab = class extends import_obsidian5.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
this.plugin = plugin;
|
|
}
|
|
async display() {
|
|
let { containerEl } = this;
|
|
containerEl.empty();
|
|
containerEl.addClass("dice-roller-settings");
|
|
containerEl.createEl("h2", { text: "Dice Roller Settings" });
|
|
new import_obsidian5.Setting(containerEl).setName("Roll All Files for Tags").setDesc("Return a result for each file when rolling tags.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.returnAllTags);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.returnAllTags = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Always Return Links for Tags").setDesc("Enables random link rolling with the link parameter. Override by specifying a section type.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.rollLinksForTags);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.rollLinksForTags = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Add Copy Button to Section Results").setDesc("Randomly rolled sections will have a copy-content button to easy add result to clipboard.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.copyContentButton);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.copyContentButton = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Display Formula With Results").setDesc("Both the formula and the results will both be displayed in preview mode.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.displayResultsInline);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.displayResultsInline = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Add Formula When Modifying").setDesc(createFragment((e) => {
|
|
e.createSpan({
|
|
text: "Both the formula and the results will both be added to the node when using "
|
|
});
|
|
e.createEl("code", { text: "dice-mod" });
|
|
e.createSpan({ text: "." });
|
|
})).addToggle((t) => {
|
|
t.setValue(this.plugin.data.displayFormulaForMod);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.displayFormulaForMod = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Display Lookup Table Roll").setDesc("Lookup table rolls will display the rolled number along with the result.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.displayLookupRoll);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.displayLookupRoll = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Show Dice Button").setDesc("A dice button will appear next to results.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.showDice);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.showDice = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
const save = new import_obsidian5.Setting(containerEl).setName("Globally Save Results").setDesc("Dice results will be saved by default. This can be overridden using ").addToggle((t) => {
|
|
t.setValue(this.plugin.data.persistResults);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.persistResults = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Open Dice View on Startup").setDesc("The dice view can always be opened using the command from the command palette.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.showLeafOnStartup);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.showLeafOnStartup = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Display graphics for Dice View Rolls").setDesc("Dice rolls from dice view will be displayed on screen.").addToggle((t) => {
|
|
t.setValue(this.plugin.data.renderer);
|
|
t.onChange(async (v) => {
|
|
this.plugin.data.renderer = v;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
const diceColor = new import_obsidian5.Setting(containerEl).setName("Dice Base Color").setDesc("Rendered dice will be this color.");
|
|
diceColor.controlEl.createEl("input", {
|
|
type: "color",
|
|
value: this.plugin.data.diceColor
|
|
}, (el) => {
|
|
el.value = this.plugin.data.diceColor;
|
|
el.onchange = async ({ target }) => {
|
|
let color = target.value;
|
|
this.plugin.data.diceColor = color;
|
|
await this.plugin.saveSettings();
|
|
this.plugin.app.workspace.trigger("dice-roller:update-colors");
|
|
};
|
|
});
|
|
const textColor = new import_obsidian5.Setting(containerEl).setName("Dice Text Color").setDesc("Rendered dice will use this color for their numbers.");
|
|
textColor.controlEl.createEl("input", {
|
|
type: "color",
|
|
value: this.plugin.data.textColor
|
|
}, (el) => {
|
|
el.value = this.plugin.data.textColor;
|
|
el.onchange = async ({ target }) => {
|
|
let color = target.value;
|
|
if (!color)
|
|
return;
|
|
this.plugin.data.textColor = color;
|
|
await this.plugin.saveSettings();
|
|
this.plugin.app.workspace.trigger("dice-roller:update-colors");
|
|
};
|
|
});
|
|
new import_obsidian5.Setting(containerEl).setName("Default Face").setDesc("Use this as the number of faces when it is omitted.").addText((t) => {
|
|
t.setValue(`${this.plugin.data.defaultFace}`);
|
|
t.inputEl.onblur = async () => {
|
|
if (isNaN(Number(t.inputEl.value))) {
|
|
new import_obsidian5.Notice("The default face must be a number.");
|
|
}
|
|
this.plugin.data.defaultFace = Number(t.inputEl.value);
|
|
await this.plugin.saveSettings();
|
|
};
|
|
});
|
|
save.descEl.createEl("code", { text: `dice-: formula` });
|
|
save.descEl.createEl("p", {
|
|
text: "Please note that the plugin will attempt to save the result but may not be able to."
|
|
});
|
|
this.additionalContainer = containerEl.createDiv("dice-roller-setting-additional-container");
|
|
this.buildFormulaSettings();
|
|
const div = containerEl.createDiv("coffee");
|
|
div.createEl("a", {
|
|
href: "https://www.buymeacoffee.com/valentine195"
|
|
}).createEl("img", {
|
|
attr: {
|
|
src: "https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=\u2615&slug=valentine195&button_colour=e3e7ef&font_colour=262626&font_family=Inter&outline_colour=262626&coffee_colour=ff0000"
|
|
}
|
|
});
|
|
}
|
|
buildFormulaSettings() {
|
|
this.additionalContainer.empty();
|
|
const addNew = this.additionalContainer.createDiv();
|
|
new import_obsidian5.Setting(addNew).setName("Add Formula").setDesc("Add a new formula shortcut.").addButton((button) => {
|
|
let b2 = button.setTooltip("Add Formula").setButtonText("+").onClick(async () => {
|
|
const formula = await this.buildFormulaForm(addNew);
|
|
if (formula) {
|
|
this.plugin.data.formulas[formula.alias] = formula.formula;
|
|
this.buildFormulaSettings();
|
|
await this.plugin.saveSettings();
|
|
}
|
|
});
|
|
return b2;
|
|
});
|
|
const additional = this.additionalContainer.createDiv("additional");
|
|
const formulas = this.plugin.data.formulas;
|
|
for (const [alias, formula] of Object.entries(formulas)) {
|
|
const setting = new import_obsidian5.Setting(additional).setName(alias);
|
|
setting.controlEl.createSpan({ text: formula });
|
|
setting.addExtraButton((b2) => b2.setIcon("pencil").setTooltip("Edit").onClick(async () => {
|
|
const edited = await this.buildFormulaForm(addNew, {
|
|
alias,
|
|
formula
|
|
});
|
|
if (edited) {
|
|
delete this.plugin.data.formulas[alias];
|
|
this.plugin.data.formulas[edited.alias] = edited.formula;
|
|
this.buildFormulaSettings();
|
|
await this.plugin.saveSettings();
|
|
}
|
|
})).addExtraButton((b2) => b2.setIcon("trash").setTooltip("Delete").onClick(async () => {
|
|
delete this.plugin.data.formulas[alias];
|
|
await this.plugin.saveSettings();
|
|
this.buildFormulaSettings();
|
|
}));
|
|
}
|
|
if (!Object.values(formulas).length) {
|
|
additional.createSpan({
|
|
text: "Create a formula to see it here!",
|
|
cls: "no-formulas"
|
|
});
|
|
}
|
|
}
|
|
async buildFormulaForm(el, temp = {
|
|
alias: null,
|
|
formula: null
|
|
}) {
|
|
return new Promise((resolve2) => {
|
|
const formulaEl = el.createDiv("add-new-formula");
|
|
const dataEl = formulaEl.createDiv("formula-data");
|
|
new import_obsidian5.Setting(dataEl).setName("Alias").addText((t) => {
|
|
t.setValue(temp.alias).onChange((v) => temp.alias = v);
|
|
});
|
|
new import_obsidian5.Setting(dataEl).setName("Formula").addText((t) => {
|
|
t.setValue(temp.formula).onChange((v) => temp.formula = v);
|
|
});
|
|
const buttonEl = formulaEl.createDiv("formula-buttons");
|
|
new import_obsidian5.Setting(buttonEl).addButton((b2) => b2.setCta().setButtonText("Save").onClick(async () => {
|
|
formulaEl.detach();
|
|
resolve2(temp);
|
|
})).addExtraButton((b2) => b2.setIcon("cross").setTooltip("Cancel").onClick(() => {
|
|
formulaEl.detach();
|
|
resolve2(null);
|
|
}));
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/view/view.ts
|
|
var import_obsidian6 = __toModule(require("obsidian"));
|
|
var VIEW_TYPE = "DICE_ROLLER_VIEW";
|
|
var D4 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><path class="cls-1" d="M244.62,49.31,40.31,403.19a6.21,6.21,0,0,0,5.38,9.31H454.31a6.21,6.21,0,0,0,5.38-9.31L255.38,49.31A6.21,6.21,0,0,0,244.62,49.31Z"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M270.21,278.16h21.7v16.22h-21.7v36.31h-20V294.38H179V282.67l70-108.39h21.16Zm-68.64,0h48.66v-76.7l-2.36,4.3Z"/></g></svg>`;
|
|
var D6 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><rect class="cls-1" x="87.5" y="87.5" width="325" height="325" rx="10"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M279.22,174.18V191h-3.65q-23.2.44-37,13.75t-15.9,37.49q12.36-14.17,33.74-14.18,20.4,0,32.6,14.4t12.19,37.17q0,24.16-13.16,38.67t-35.29,14.5q-22.46,0-36.41-17.24t-14-44.42v-7.63q0-43.19,18.42-66t54.84-23.36Zm-26.1,70.47a33.41,33.41,0,0,0-30.73,21.48v7.31q0,19.33,8.7,31.15t21.7,11.81q13.43,0,21.11-9.88t7.68-25.89q0-16.11-7.79-26A25,25,0,0,0,253.12,244.65Z"/></g></svg>`;
|
|
var D8 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><rect class="cls-1" x="102.75" y="102.75" width="294.51" height="294.51" rx="9.8" transform="translate(-103.55 250) rotate(-45)"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M292.08,215.1a36.35,36.35,0,0,1-6.17,20.84,42.05,42.05,0,0,1-16.71,14.29,44.8,44.8,0,0,1,19.39,15.36,38.7,38.7,0,0,1,7.15,22.88q0,20.31-13.7,32.34t-36,12q-22.56,0-36.15-12.09t-13.59-32.28a39.84,39.84,0,0,1,6.93-22.88,43.14,43.14,0,0,1,19.18-15.47,40.88,40.88,0,0,1-16.44-14.28,36.85,36.85,0,0,1-6-20.74q0-19.75,12.67-31.36T246,172.14q20.63,0,33.35,11.6T292.08,215.1ZM275.86,288q0-13.1-8.32-21.37t-21.75-8.27q-13.44,0-21.54,8.16T216.14,288q0,13.33,7.89,20.95t22,7.63q14,0,21.91-7.68T275.86,288ZM246,188.46q-11.72,0-19,7.26t-7.25,19.71q0,11.92,7.14,19.28T246,242.07q11.92,0,19.07-7.36t7.14-19.28q0-11.93-7.41-19.45T246,188.46Z"/></g></svg>`;
|
|
var D10 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><rect class="cls-1" x="102.75" y="102.75" width="294.51" height="294.51" rx="9.8" transform="translate(-103.55 250) rotate(-45)"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M219,330.69H199V198.24L158.92,213V194.91l56.93-21.38H219Z"/><path d="M344.47,264q0,34.92-11.93,51.89t-37.27,17q-25,0-37.06-16.6t-12.46-49.57V240.13q0-34.47,11.92-51.24t37.38-16.75q25.24,0,37.17,16.16t12.25,49.9ZM324.59,236.8q0-25.23-7.09-36.79t-22.45-11.55q-15.26,0-22.23,11.5t-7.2,35.34v31.8q0,25.35,7.36,37.43t22.29,12.09q14.72,0,21.86-11.39t7.46-35.88Z"/></g></svg>`;
|
|
var D12 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><path class="cls-1" d="M244.31,29.14,52,168.87a9.72,9.72,0,0,0-3.52,10.84l73.47,226.1a9.69,9.69,0,0,0,9.21,6.69H368.87a9.69,9.69,0,0,0,9.21-6.69l73.47-226.1A9.72,9.72,0,0,0,448,168.87L255.69,29.14A9.66,9.66,0,0,0,244.31,29.14Z"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M208,330.69H188V198.24L147.93,213V194.91l56.93-21.38H208Z"/><path d="M342.28,330.69H239.8V316.4l54.14-60.15q12-13.65,16.6-22.19a37,37,0,0,0,4.56-17.67q0-12.24-7.41-20.08t-19.77-7.85q-14.82,0-23,8.44t-8.22,23.47H236.79q0-21.6,13.91-34.91t37.22-13.32q21.81,0,34.49,11.44T335.08,214q0,23.1-29.43,55l-41.9,45.44h78.53Z"/></g></svg>`;
|
|
var D20 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><path class="cls-1" d="M55.14,143.27V356.73a10,10,0,0,0,5,8.66L245,472.11a10,10,0,0,0,10,0L439.86,365.39a10,10,0,0,0,5-8.66V143.27a10,10,0,0,0-5-8.66L255,27.89a10,10,0,0,0-10,0L60.14,134.61A10,10,0,0,0,55.14,143.27Z"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M251.34,330.69H148.86V316.4L203,256.25q12-13.65,16.6-22.19a37,37,0,0,0,4.57-17.67q0-12.24-7.42-20.08T197,188.46q-14.82,0-23,8.44t-8.22,23.47H145.86q0-21.6,13.91-34.91T197,172.14q21.81,0,34.48,11.44T244.15,214q0,23.1-29.44,55l-41.89,45.44h78.52Z"/><path d="M361.67,264q0,34.92-11.92,51.89t-37.27,17q-25,0-37.06-16.6T263,266.67V240.13q0-34.47,11.93-51.24t37.38-16.75q25.25,0,37.17,16.16t12.24,49.9ZM341.8,236.8q0-25.23-7.09-36.79t-22.45-11.55Q297,188.46,290,200t-7.19,35.34v31.8q0,25.35,7.36,37.43t22.29,12.09q14.72,0,21.86-11.39t7.46-35.88Z"/></g></svg>`;
|
|
var D100 = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke: currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:15px !important;}</style></defs><g id="Shapes"><circle class="cls-1" cx="246.23" cy="250" r="189.38"/></g><g fill="currentColor" id="Layer_1" data-name="Layer 1"><path d="M172.54,194.88q0-15.7,10.19-25.49t26.72-9.79q16.76,0,27,9.67t10.19,26.19v8.44q0,15.82-10.19,25.43t-26.72,9.61q-16.65,0-26.9-9.67T172.54,203.2Zm22.5,9.17q0,7.06,4,11.37a13.88,13.88,0,0,0,10.61,4.3,13.24,13.24,0,0,0,10.43-4.36Q224,211,224,203.69V195c0-4.71-1.28-8.53-3.86-11.43s-6.14-4.36-10.67-4.36a13.56,13.56,0,0,0-10.43,4.3q-4,4.31-4,12Zm21.33,115.87L199.84,311l83.32-133.36,16.53,8.91Zm37.73-29.06q0-15.83,10.31-25.49t26.72-9.67q16.65,0,26.9,9.55t10.25,26.31V300q0,15.71-10.08,25.37T291.37,335q-16.87,0-27.07-9.73t-10.2-25.78Zm22.5,9.28a15.82,15.82,0,0,0,4.22,11.08,13.71,13.71,0,0,0,10.55,4.6q14.29,0,14.29-15.92V291q0-7.08-4-11.38a15.08,15.08,0,0,0-21.09,0q-4,4.31-4,11.73Z"/></g></svg>`;
|
|
(0, import_obsidian6.addIcon)("d4", D4);
|
|
(0, import_obsidian6.addIcon)("d6", D6);
|
|
(0, import_obsidian6.addIcon)("d8", D8);
|
|
(0, import_obsidian6.addIcon)("d10", D10);
|
|
(0, import_obsidian6.addIcon)("d12", D12);
|
|
(0, import_obsidian6.addIcon)("d20", D20);
|
|
(0, import_obsidian6.addIcon)("d100", D100);
|
|
(0, import_obsidian6.addIcon)("dice-roller-save", `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" data-prefix="far" data-icon="save" class="svg-inline--fa fa-save fa-w-14" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM272 80v80H144V80h128zm122 352H54a6 6 0 0 1-6-6V86a6 6 0 0 1 6-6h42v104c0 13.255 10.745 24 24 24h176c13.255 0 24-10.745 24-24V83.882l78.243 78.243a6 6 0 0 1 1.757 4.243V426a6 6 0 0 1-6 6zM224 232c-48.523 0-88 39.477-88 88s39.477 88 88 88 88-39.477 88-88-39.477-88-88-88zm0 128c-22.056 0-40-17.944-40-40s17.944-40 40-40 40 17.944 40 40-17.944 40-40 40z"/></svg>`);
|
|
(0, import_obsidian6.addIcon)("dice-roller-plus", `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" data-prefix="far" data-icon="plus-square" class="svg-inline--fa fa-plus-square fa-w-14" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M352 240v32c0 6.6-5.4 12-12 12h-88v88c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-88h-88c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h88v-88c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v88h88c6.6 0 12 5.4 12 12zm96-160v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"/></svg>`);
|
|
(0, import_obsidian6.addIcon)("dice-roller-minus", `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" data-prefix="far" data-icon="minus-square" class="svg-inline--fa fa-minus-square fa-w-14" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M108 284c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h232c6.6 0 12 5.4 12 12v32c0 6.6-5.4 12-12 12H108zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"/></svg>`);
|
|
var DiceView = class extends import_obsidian6.ItemView {
|
|
constructor(plugin, leaf) {
|
|
super(leaf);
|
|
this.plugin = plugin;
|
|
this.leaf = leaf;
|
|
this.dice = DiceView.DICE();
|
|
this.custom = "";
|
|
this.adv = false;
|
|
this.dis = false;
|
|
this.add = 0;
|
|
this.contentEl.addClass("dice-roller-view");
|
|
this.registerEvent(this.plugin.app.workspace.on("dice-roller:update-colors", () => {
|
|
this.renderer.factory.updateColors();
|
|
}));
|
|
}
|
|
static DICE() {
|
|
return {
|
|
d4: 0,
|
|
d6: 0,
|
|
d8: 0,
|
|
d10: 0,
|
|
d12: 0,
|
|
d20: 0,
|
|
d100: 0
|
|
};
|
|
}
|
|
get customFormulas() {
|
|
return this.plugin.data.customFormulas;
|
|
}
|
|
get renderer() {
|
|
return this.plugin.renderer;
|
|
}
|
|
async onOpen() {
|
|
this.display();
|
|
}
|
|
async display() {
|
|
this.contentEl.empty();
|
|
this.gridEl = this.contentEl.createDiv("dice-roller-grid");
|
|
this.formulaEl = this.contentEl.createDiv("dice-roller-formula");
|
|
const resultsEl = this.contentEl.createDiv("dice-roller-results-container");
|
|
const headerEl = resultsEl.createDiv("dice-roller-results-header");
|
|
headerEl.createEl("h4", { text: "Results" });
|
|
new import_obsidian6.ExtraButtonComponent(headerEl.createDiv("clear-all")).setIcon("trash").setTooltip("Clear All").onClick(() => {
|
|
this.resultEl.empty();
|
|
this.resultEl.append(this.noResultsEl);
|
|
});
|
|
this.resultEl = resultsEl.createDiv("dice-roller-results");
|
|
this.noResultsEl = this.resultEl.createSpan({
|
|
text: "No results yet! Roll some dice to get started :)"
|
|
});
|
|
this.buildButtons();
|
|
this.buildFormula();
|
|
}
|
|
buildButtons() {
|
|
this.gridEl.empty();
|
|
const buttons = this.gridEl.createDiv("dice-buttons");
|
|
for (let type in this.dice) {
|
|
const button = new import_obsidian6.ExtraButtonComponent(buttons.createDiv("dice-button")).setIcon(type);
|
|
button.extraSettingsEl.onclick = async (evt) => {
|
|
let add2 = evt.getModifierState("Shift") ? -1 : 1;
|
|
this.dice[type] += add2;
|
|
this.setFormula();
|
|
const roller = await this.plugin.getRoller(this.formulaComponent.inputEl.value, "view");
|
|
if (roller instanceof StackRoller) {
|
|
this.stack = roller;
|
|
}
|
|
};
|
|
}
|
|
const advDis = this.gridEl.createDiv("advantage-disadvantage");
|
|
const adv = new import_obsidian6.ButtonComponent(advDis).setButtonText("ADV").onClick(() => {
|
|
this.adv = !this.adv;
|
|
this.dis = false;
|
|
if (this.adv) {
|
|
adv.setCta();
|
|
dis.removeCta();
|
|
} else {
|
|
adv.removeCta();
|
|
}
|
|
this.setFormula();
|
|
});
|
|
const dis = new import_obsidian6.ButtonComponent(advDis).setButtonText("DIS").onClick(() => {
|
|
this.dis = !this.dis;
|
|
if (this.dis) {
|
|
dis.setCta();
|
|
adv.removeCta();
|
|
} else {
|
|
dis.removeCta();
|
|
}
|
|
this.adv = false;
|
|
this.setFormula();
|
|
});
|
|
const add = this.gridEl.createDiv("dice-context").createDiv("add-subtract");
|
|
new import_obsidian6.ExtraButtonComponent(add).setIcon("dice-roller-minus").onClick(() => {
|
|
this.add -= 1;
|
|
addComponent.setValue(`${this.add}`);
|
|
this.setFormula();
|
|
});
|
|
const addComponent = new import_obsidian6.TextComponent(add).setValue(`${this.add ? this.add : ""}`).onChange((v) => {
|
|
if (!isNaN(Number(v)))
|
|
this.add = Number(v);
|
|
this.setFormula();
|
|
});
|
|
new import_obsidian6.ExtraButtonComponent(add).setIcon("dice-roller-plus").onClick(() => {
|
|
this.add += 1;
|
|
addComponent.setValue(`${this.add}`);
|
|
this.setFormula();
|
|
});
|
|
if (this.customFormulas.length) {
|
|
const customs = this.gridEl.createDiv("dice-roller-results-container");
|
|
const headerEl = customs.createDiv("dice-roller-results-header");
|
|
headerEl.createEl("h4", { text: "Saved Formulas" });
|
|
for (let formula of this.customFormulas) {
|
|
const containerEl = customs.createDiv("dice-custom-formula-container");
|
|
const formulaEl = containerEl.createDiv("dice-custom-formula");
|
|
new import_obsidian6.ExtraButtonComponent(formulaEl).setIcon(ICON_DEFINITION).setTooltip("Roll").onClick(() => this.roll(formula));
|
|
formulaEl.createSpan({ text: formula });
|
|
new import_obsidian6.ExtraButtonComponent(containerEl).setIcon("trash").setTooltip("Remove").onClick(() => {
|
|
this.plugin.data.customFormulas = this.plugin.data.customFormulas.filter((f) => f != formula);
|
|
this.plugin.saveSettings();
|
|
this.buildButtons();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
async roll(formula = this.formulaComponent.inputEl.value) {
|
|
if (!formula) {
|
|
return;
|
|
}
|
|
this.rollButton.setDisabled(true);
|
|
const roller = await this.plugin.getRoller(formula, "view");
|
|
if (!(roller instanceof StackRoller)) {
|
|
new import_obsidian6.Notice("The Dice View only supports dice rolls.");
|
|
return;
|
|
}
|
|
await roller.roll();
|
|
if (!roller.dice.length) {
|
|
new import_obsidian6.Notice("Invalid formula.");
|
|
return;
|
|
}
|
|
try {
|
|
if (this.plugin.data.renderer) {
|
|
this.addChild(this.renderer);
|
|
this.renderer.setDice(roller);
|
|
await this.renderer.start();
|
|
roller.recalculate();
|
|
}
|
|
} catch (e) {
|
|
new import_obsidian6.Notice("There was an error rendering the roll.");
|
|
console.error(e);
|
|
}
|
|
this.rollButton.setDisabled(false);
|
|
this.addResult({
|
|
result: roller.result,
|
|
original: roller.original,
|
|
resultText: roller.resultText
|
|
});
|
|
this.dice = DiceView.DICE();
|
|
this.add = null;
|
|
this.adv = false;
|
|
this.dis = false;
|
|
this.buildButtons();
|
|
this.setFormula();
|
|
}
|
|
buildFormula() {
|
|
this.formulaEl.empty();
|
|
this.formulaComponent = new import_obsidian6.TextAreaComponent(this.formulaEl).setPlaceholder("Dice Formula");
|
|
this.formulaComponent.onChange((0, import_obsidian6.debounce)(async (v) => {
|
|
}, 500, true));
|
|
const buttons = this.formulaEl.createDiv("action-buttons");
|
|
this.saveButton = new import_obsidian6.ButtonComponent(buttons).setIcon("plus-with-circle").setCta().setTooltip("Save Formula").onClick(() => this.save());
|
|
this.saveButton.buttonEl.addClass("dice-roller-roll");
|
|
this.rollButton = new import_obsidian6.ButtonComponent(buttons).setIcon(ICON_DEFINITION).setCta().setTooltip("Roll").onClick(() => this.roll());
|
|
this.rollButton.buttonEl.addClass("dice-roller-roll");
|
|
}
|
|
save() {
|
|
if (!this.formulaComponent.inputEl.value)
|
|
return;
|
|
this.plugin.data.customFormulas.push(this.formulaComponent.inputEl.value);
|
|
this.buildButtons();
|
|
this.plugin.saveSettings();
|
|
}
|
|
addResult(roller) {
|
|
if (this.noResultsEl) {
|
|
this.noResultsEl.detach();
|
|
}
|
|
const result = createDiv("view-result");
|
|
result.createSpan({
|
|
text: roller.original
|
|
});
|
|
result.createEl("strong", {
|
|
text: `${roller.result}`,
|
|
attr: {
|
|
"aria-label": roller.resultText
|
|
}
|
|
});
|
|
const context = result.createDiv("result-context");
|
|
context.createEl("em", { text: new Date().toLocaleString() });
|
|
new import_obsidian6.ExtraButtonComponent(context).setIcon("trash").onClick(() => {
|
|
result.detach();
|
|
if (this.resultEl.children.length === 0) {
|
|
this.resultEl.prepend(this.noResultsEl);
|
|
}
|
|
});
|
|
const copy = new import_obsidian6.ExtraButtonComponent(context).setIcon(COPY_DEFINITION).setTooltip("Copy Result").onClick(async () => {
|
|
await navigator.clipboard.writeText(`${roller.result}`);
|
|
});
|
|
copy.extraSettingsEl.addClass("dice-content-copy");
|
|
const reroll = new import_obsidian6.ExtraButtonComponent(context).setIcon(ICON_DEFINITION).setTooltip("Roll Again").onClick(() => this.roll(roller.original));
|
|
reroll.extraSettingsEl.addClass("dice-result-reroll");
|
|
this.resultEl.prepend(result);
|
|
}
|
|
get formulaString() {
|
|
const result = [];
|
|
const dice = Object.entries(this.dice).filter(([type, num]) => num != 0);
|
|
if (!dice.length)
|
|
return "";
|
|
dice.sort((a2, b2) => Number(b2[0].slice(1)) - Number(a2[0].slice(1)));
|
|
const first = dice.shift();
|
|
result.push(`${first[1]}${first[0]}`);
|
|
if (this.adv) {
|
|
result.push("kh");
|
|
} else if (this.dis) {
|
|
result.push("dh");
|
|
}
|
|
if (dice.length) {
|
|
result.push(...dice.map(([type, num]) => `${num > 0 ? "+" : "-"}${Math.abs(num)}${type}`));
|
|
}
|
|
if (this.add && this.add != 0) {
|
|
result.push(this.add > 0 ? "+" : "-");
|
|
result.push(Math.abs(this.add));
|
|
}
|
|
return result.join("");
|
|
}
|
|
setFormula() {
|
|
this.formulaComponent.setValue(this.formulaString);
|
|
}
|
|
getDisplayText() {
|
|
return "Dice Roller";
|
|
}
|
|
getViewType() {
|
|
return VIEW_TYPE;
|
|
}
|
|
getIcon() {
|
|
return ICON_DEFINITION;
|
|
}
|
|
async onClose() {
|
|
await super.onClose();
|
|
this.renderer.unload();
|
|
}
|
|
};
|
|
|
|
// src/view/renderer.ts
|
|
var import_obsidian7 = __toModule(require("obsidian"));
|
|
|
|
// node_modules/three/build/three.module.js
|
|
var REVISION = "132";
|
|
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 FlatShading = 1;
|
|
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 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 UVMapping = 300;
|
|
var CubeReflectionMapping = 301;
|
|
var CubeRefractionMapping = 302;
|
|
var EquirectangularReflectionMapping = 303;
|
|
var EquirectangularRefractionMapping = 304;
|
|
var CubeUVReflectionMapping = 306;
|
|
var CubeUVRefractionMapping = 307;
|
|
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 UnsignedShort565Type = 1019;
|
|
var UnsignedInt248Type = 1020;
|
|
var AlphaFormat = 1021;
|
|
var RGBFormat = 1022;
|
|
var RGBAFormat = 1023;
|
|
var LuminanceFormat = 1024;
|
|
var LuminanceAlphaFormat = 1025;
|
|
var RGBEFormat = RGBAFormat;
|
|
var DepthFormat = 1026;
|
|
var DepthStencilFormat = 1027;
|
|
var RedFormat = 1028;
|
|
var RedIntegerFormat = 1029;
|
|
var RGFormat = 1030;
|
|
var RGIntegerFormat = 1031;
|
|
var RGBIntegerFormat = 1032;
|
|
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 SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
|
|
var SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
|
|
var SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
|
|
var SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
|
|
var SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
|
|
var SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
|
|
var SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
|
|
var SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
|
|
var SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
|
|
var SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
|
|
var SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
|
|
var SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
|
|
var SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
|
|
var SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
|
|
var LoopOnce = 2200;
|
|
var LoopRepeat = 2201;
|
|
var LoopPingPong = 2202;
|
|
var InterpolateDiscrete = 2300;
|
|
var InterpolateLinear = 2301;
|
|
var InterpolateSmooth = 2302;
|
|
var ZeroCurvatureEnding = 2400;
|
|
var ZeroSlopeEnding = 2401;
|
|
var WrapAroundEnding = 2402;
|
|
var NormalAnimationBlendMode = 2500;
|
|
var AdditiveAnimationBlendMode = 2501;
|
|
var TrianglesDrawMode = 0;
|
|
var LinearEncoding = 3e3;
|
|
var sRGBEncoding = 3001;
|
|
var GammaEncoding = 3007;
|
|
var RGBEEncoding = 3002;
|
|
var LogLuvEncoding = 3003;
|
|
var RGBM7Encoding = 3004;
|
|
var RGBM16Encoding = 3005;
|
|
var RGBDEncoding = 3006;
|
|
var BasicDepthPacking = 3200;
|
|
var RGBADepthPacking = 3201;
|
|
var TangentSpaceNormalMap = 0;
|
|
var ObjectSpaceNormalMap = 1;
|
|
var KeepStencilOp = 7680;
|
|
var AlwaysStencilFunc = 519;
|
|
var StaticDrawUsage = 35044;
|
|
var DynamicDrawUsage = 35048;
|
|
var GLSL3 = "300 es";
|
|
var EventDispatcher = class {
|
|
addEventListener(type, listener3) {
|
|
if (this._listeners === void 0)
|
|
this._listeners = {};
|
|
const listeners = this._listeners;
|
|
if (listeners[type] === void 0) {
|
|
listeners[type] = [];
|
|
}
|
|
if (listeners[type].indexOf(listener3) === -1) {
|
|
listeners[type].push(listener3);
|
|
}
|
|
}
|
|
hasEventListener(type, listener3) {
|
|
if (this._listeners === void 0)
|
|
return false;
|
|
const listeners = this._listeners;
|
|
return listeners[type] !== void 0 && listeners[type].indexOf(listener3) !== -1;
|
|
}
|
|
removeEventListener(type, listener3) {
|
|
if (this._listeners === void 0)
|
|
return;
|
|
const listeners = this._listeners;
|
|
const listenerArray = listeners[type];
|
|
if (listenerArray !== void 0) {
|
|
const index = listenerArray.indexOf(listener3);
|
|
if (index !== -1) {
|
|
listenerArray.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
dispatchEvent(event) {
|
|
if (this._listeners === void 0)
|
|
return;
|
|
const listeners = this._listeners;
|
|
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 = [];
|
|
for (let i = 0; i < 256; i++) {
|
|
_lut[i] = (i < 16 ? "0" : "") + i.toString(16);
|
|
}
|
|
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.toUpperCase();
|
|
}
|
|
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 isPowerOfTwo(value) {
|
|
return (value & value - 1) === 0 && value !== 0;
|
|
}
|
|
function floorPowerOfTwo(value) {
|
|
return Math.pow(2, Math.floor(Math.log(value) / Math.LN2));
|
|
}
|
|
var Vector2 = class {
|
|
constructor(x = 0, y = 0) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
get width() {
|
|
return this.x;
|
|
}
|
|
set width(value) {
|
|
this.x = value;
|
|
}
|
|
get height() {
|
|
return this.y;
|
|
}
|
|
set height(value) {
|
|
this.y = value;
|
|
}
|
|
set(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
setScalar(scalar) {
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
return this;
|
|
}
|
|
setX(x) {
|
|
this.x = x;
|
|
return this;
|
|
}
|
|
setY(y) {
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
getComponent(index) {
|
|
switch (index) {
|
|
case 0:
|
|
return this.x;
|
|
case 1:
|
|
return this.y;
|
|
default:
|
|
throw new Error("index is out of range: " + index);
|
|
}
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.x, this.y);
|
|
}
|
|
copy(v) {
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
return this;
|
|
}
|
|
add(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.");
|
|
return this.addVectors(v, w2);
|
|
}
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
return this;
|
|
}
|
|
addScalar(s) {
|
|
this.x += s;
|
|
this.y += s;
|
|
return this;
|
|
}
|
|
addVectors(a2, b2) {
|
|
this.x = a2.x + b2.x;
|
|
this.y = a2.y + b2.y;
|
|
return this;
|
|
}
|
|
addScaledVector(v, s) {
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
return this;
|
|
}
|
|
sub(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.");
|
|
return this.subVectors(v, w2);
|
|
}
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
return this;
|
|
}
|
|
subScalar(s) {
|
|
this.x -= s;
|
|
this.y -= s;
|
|
return this;
|
|
}
|
|
subVectors(a2, b2) {
|
|
this.x = a2.x - b2.x;
|
|
this.y = a2.y - b2.y;
|
|
return this;
|
|
}
|
|
multiply(v) {
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
return this;
|
|
}
|
|
multiplyScalar(scalar) {
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
return this;
|
|
}
|
|
divide(v) {
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
return this;
|
|
}
|
|
divideScalar(scalar) {
|
|
return this.multiplyScalar(1 / scalar);
|
|
}
|
|
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;
|
|
}
|
|
min(v) {
|
|
this.x = Math.min(this.x, v.x);
|
|
this.y = Math.min(this.y, v.y);
|
|
return this;
|
|
}
|
|
max(v) {
|
|
this.x = Math.max(this.x, v.x);
|
|
this.y = Math.max(this.y, v.y);
|
|
return this;
|
|
}
|
|
clamp(min, max) {
|
|
this.x = Math.max(min.x, Math.min(max.x, this.x));
|
|
this.y = Math.max(min.y, Math.min(max.y, this.y));
|
|
return this;
|
|
}
|
|
clampScalar(minVal, maxVal) {
|
|
this.x = Math.max(minVal, Math.min(maxVal, this.x));
|
|
this.y = Math.max(minVal, Math.min(maxVal, this.y));
|
|
return this;
|
|
}
|
|
clampLength(min, max) {
|
|
const length = this.length();
|
|
return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
|
|
}
|
|
floor() {
|
|
this.x = Math.floor(this.x);
|
|
this.y = Math.floor(this.y);
|
|
return this;
|
|
}
|
|
ceil() {
|
|
this.x = Math.ceil(this.x);
|
|
this.y = Math.ceil(this.y);
|
|
return this;
|
|
}
|
|
round() {
|
|
this.x = Math.round(this.x);
|
|
this.y = Math.round(this.y);
|
|
return this;
|
|
}
|
|
roundToZero() {
|
|
this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x);
|
|
this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y);
|
|
return this;
|
|
}
|
|
negate() {
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
return this;
|
|
}
|
|
dot(v) {
|
|
return this.x * v.x + this.y * v.y;
|
|
}
|
|
cross(v) {
|
|
return this.x * v.y - this.y * v.x;
|
|
}
|
|
lengthSq() {
|
|
return this.x * this.x + this.y * this.y;
|
|
}
|
|
length() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
}
|
|
manhattanLength() {
|
|
return Math.abs(this.x) + Math.abs(this.y);
|
|
}
|
|
normalize() {
|
|
return this.divideScalar(this.length() || 1);
|
|
}
|
|
angle() {
|
|
const angle = Math.atan2(-this.y, -this.x) + Math.PI;
|
|
return angle;
|
|
}
|
|
distanceTo(v) {
|
|
return Math.sqrt(this.distanceToSquared(v));
|
|
}
|
|
distanceToSquared(v) {
|
|
const dx = this.x - v.x, dy = this.y - v.y;
|
|
return dx * dx + dy * dy;
|
|
}
|
|
manhattanDistanceTo(v) {
|
|
return Math.abs(this.x - v.x) + Math.abs(this.y - v.y);
|
|
}
|
|
setLength(length) {
|
|
return this.normalize().multiplyScalar(length);
|
|
}
|
|
lerp(v, alpha) {
|
|
this.x += (v.x - this.x) * alpha;
|
|
this.y += (v.y - this.y) * alpha;
|
|
return this;
|
|
}
|
|
lerpVectors(v12, v22, alpha) {
|
|
this.x = v12.x + (v22.x - v12.x) * alpha;
|
|
this.y = v12.y + (v22.y - v12.y) * alpha;
|
|
return this;
|
|
}
|
|
equals(v) {
|
|
return v.x === this.x && v.y === this.y;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
this.x = array[offset];
|
|
this.y = array[offset + 1];
|
|
return this;
|
|
}
|
|
toArray(array = [], offset = 0) {
|
|
array[offset] = this.x;
|
|
array[offset + 1] = this.y;
|
|
return array;
|
|
}
|
|
fromBufferAttribute(attribute, index, offset) {
|
|
if (offset !== void 0) {
|
|
console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute().");
|
|
}
|
|
this.x = attribute.getX(index);
|
|
this.y = attribute.getY(index);
|
|
return this;
|
|
}
|
|
rotateAround(center, angle) {
|
|
const c2 = Math.cos(angle), s = Math.sin(angle);
|
|
const x = this.x - center.x;
|
|
const y = this.y - center.y;
|
|
this.x = x * c2 - y * s + center.x;
|
|
this.y = x * s + y * c2 + center.y;
|
|
return this;
|
|
}
|
|
random() {
|
|
this.x = Math.random();
|
|
this.y = Math.random();
|
|
return this;
|
|
}
|
|
};
|
|
Vector2.prototype.isVector2 = true;
|
|
var Matrix3 = class {
|
|
constructor() {
|
|
this.elements = [
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
1
|
|
];
|
|
if (arguments.length > 0) {
|
|
console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.");
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
identity() {
|
|
this.set(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
extractBasis(xAxis, yAxis, zAxis) {
|
|
xAxis.setFromMatrix3Column(this, 0);
|
|
yAxis.setFromMatrix3Column(this, 1);
|
|
zAxis.setFromMatrix3Column(this, 2);
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
multiply(m) {
|
|
return this.multiplyMatrices(this, m);
|
|
}
|
|
premultiply(m) {
|
|
return this.multiplyMatrices(m, this);
|
|
}
|
|
multiplyMatrices(a2, b2) {
|
|
const ae = a2.elements;
|
|
const be = b2.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;
|
|
}
|
|
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;
|
|
}
|
|
determinant() {
|
|
const te = this.elements;
|
|
const a2 = te[0], b2 = te[1], c2 = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i = te[8];
|
|
return a2 * e * i - a2 * f * h - b2 * d * i + b2 * f * g + c2 * d * h - c2 * e * g;
|
|
}
|
|
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;
|
|
}
|
|
transpose() {
|
|
let tmp3;
|
|
const m = this.elements;
|
|
tmp3 = m[1];
|
|
m[1] = m[3];
|
|
m[3] = tmp3;
|
|
tmp3 = m[2];
|
|
m[2] = m[6];
|
|
m[6] = tmp3;
|
|
tmp3 = m[5];
|
|
m[5] = m[7];
|
|
m[7] = tmp3;
|
|
return this;
|
|
}
|
|
getNormalMatrix(matrix4) {
|
|
return this.setFromMatrix4(matrix4).invert().transpose();
|
|
}
|
|
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;
|
|
}
|
|
setUvTransform(tx, ty, sx, sy, rotation, cx, cy) {
|
|
const c2 = Math.cos(rotation);
|
|
const s = Math.sin(rotation);
|
|
this.set(sx * c2, sx * s, -sx * (c2 * cx + s * cy) + cx + tx, -sy * s, sy * c2, -sy * (-s * cx + c2 * cy) + cy + ty, 0, 0, 1);
|
|
return this;
|
|
}
|
|
scale(sx, sy) {
|
|
const te = this.elements;
|
|
te[0] *= sx;
|
|
te[3] *= sx;
|
|
te[6] *= sx;
|
|
te[1] *= sy;
|
|
te[4] *= sy;
|
|
te[7] *= sy;
|
|
return this;
|
|
}
|
|
rotate(theta) {
|
|
const c2 = Math.cos(theta);
|
|
const s = Math.sin(theta);
|
|
const te = this.elements;
|
|
const a11 = te[0], a12 = te[3], a13 = te[6];
|
|
const a21 = te[1], a22 = te[4], a23 = te[7];
|
|
te[0] = c2 * a11 + s * a21;
|
|
te[3] = c2 * a12 + s * a22;
|
|
te[6] = c2 * a13 + s * a23;
|
|
te[1] = -s * a11 + c2 * a21;
|
|
te[4] = -s * a12 + c2 * a22;
|
|
te[7] = -s * a13 + c2 * a23;
|
|
return this;
|
|
}
|
|
translate(tx, ty) {
|
|
const te = this.elements;
|
|
te[0] += tx * te[2];
|
|
te[3] += tx * te[5];
|
|
te[6] += tx * te[8];
|
|
te[1] += ty * te[2];
|
|
te[4] += ty * te[5];
|
|
te[7] += ty * te[8];
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.elements[i] = array[i + offset];
|
|
}
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
clone() {
|
|
return new this.constructor().fromArray(this.elements);
|
|
}
|
|
};
|
|
Matrix3.prototype.isMatrix3 = true;
|
|
var _canvas;
|
|
var ImageUtils = class {
|
|
static getDataURL(image) {
|
|
if (/^data:/i.test(image.src)) {
|
|
return image.src;
|
|
}
|
|
if (typeof HTMLCanvasElement == "undefined") {
|
|
return image.src;
|
|
}
|
|
let canvas;
|
|
if (image instanceof HTMLCanvasElement) {
|
|
canvas = image;
|
|
} else {
|
|
if (_canvas === void 0)
|
|
_canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
|
_canvas.width = image.width;
|
|
_canvas.height = image.height;
|
|
const context = _canvas.getContext("2d");
|
|
if (image instanceof ImageData) {
|
|
context.putImageData(image, 0, 0);
|
|
} else {
|
|
context.drawImage(image, 0, 0, image.width, image.height);
|
|
}
|
|
canvas = _canvas;
|
|
}
|
|
if (canvas.width > 2048 || canvas.height > 2048) {
|
|
console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons", image);
|
|
return canvas.toDataURL("image/jpeg", 0.6);
|
|
} else {
|
|
return canvas.toDataURL("image/png");
|
|
}
|
|
}
|
|
};
|
|
var textureId = 0;
|
|
var Texture = class extends EventDispatcher {
|
|
constructor(image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding) {
|
|
super();
|
|
Object.defineProperty(this, "id", { value: textureId++ });
|
|
this.uuid = generateUUID();
|
|
this.name = "";
|
|
this.image = image;
|
|
this.mipmaps = [];
|
|
this.mapping = mapping;
|
|
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.encoding = encoding;
|
|
this.version = 0;
|
|
this.onUpdate = null;
|
|
this.isRenderTargetTexture = false;
|
|
}
|
|
updateMatrix() {
|
|
this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(source) {
|
|
this.name = source.name;
|
|
this.image = source.image;
|
|
this.mipmaps = source.mipmaps.slice(0);
|
|
this.mapping = source.mapping;
|
|
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.encoding = source.encoding;
|
|
return this;
|
|
}
|
|
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.5,
|
|
type: "Texture",
|
|
generator: "Texture.toJSON"
|
|
},
|
|
uuid: this.uuid,
|
|
name: this.name,
|
|
mapping: this.mapping,
|
|
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,
|
|
type: this.type,
|
|
encoding: this.encoding,
|
|
minFilter: this.minFilter,
|
|
magFilter: this.magFilter,
|
|
anisotropy: this.anisotropy,
|
|
flipY: this.flipY,
|
|
premultiplyAlpha: this.premultiplyAlpha,
|
|
unpackAlignment: this.unpackAlignment
|
|
};
|
|
if (this.image !== void 0) {
|
|
const image = this.image;
|
|
if (image.uuid === void 0) {
|
|
image.uuid = generateUUID();
|
|
}
|
|
if (!isRootObject && meta.images[image.uuid] === void 0) {
|
|
let url;
|
|
if (Array.isArray(image)) {
|
|
url = [];
|
|
for (let i = 0, l = image.length; i < l; i++) {
|
|
if (image[i].isDataTexture) {
|
|
url.push(serializeImage(image[i].image));
|
|
} else {
|
|
url.push(serializeImage(image[i]));
|
|
}
|
|
}
|
|
} else {
|
|
url = serializeImage(image);
|
|
}
|
|
meta.images[image.uuid] = {
|
|
uuid: image.uuid,
|
|
url
|
|
};
|
|
}
|
|
output.image = image.uuid;
|
|
}
|
|
if (!isRootObject) {
|
|
meta.textures[this.uuid] = output;
|
|
}
|
|
return output;
|
|
}
|
|
dispose() {
|
|
this.dispatchEvent({ type: "dispose" });
|
|
}
|
|
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;
|
|
}
|
|
set needsUpdate(value) {
|
|
if (value === true)
|
|
this.version++;
|
|
}
|
|
};
|
|
Texture.DEFAULT_IMAGE = void 0;
|
|
Texture.DEFAULT_MAPPING = UVMapping;
|
|
Texture.prototype.isTexture = true;
|
|
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.prototype.slice.call(image.data),
|
|
width: image.width,
|
|
height: image.height,
|
|
type: image.data.constructor.name
|
|
};
|
|
} else {
|
|
console.warn("THREE.Texture: Unable to serialize Texture.");
|
|
return {};
|
|
}
|
|
}
|
|
}
|
|
var Vector4 = class {
|
|
constructor(x = 0, y = 0, z = 0, w2 = 1) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w2;
|
|
}
|
|
get width() {
|
|
return this.z;
|
|
}
|
|
set width(value) {
|
|
this.z = value;
|
|
}
|
|
get height() {
|
|
return this.w;
|
|
}
|
|
set height(value) {
|
|
this.w = value;
|
|
}
|
|
set(x, y, z, w2) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w2;
|
|
return this;
|
|
}
|
|
setScalar(scalar) {
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
this.z = scalar;
|
|
this.w = scalar;
|
|
return this;
|
|
}
|
|
setX(x) {
|
|
this.x = x;
|
|
return this;
|
|
}
|
|
setY(y) {
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
setZ(z) {
|
|
this.z = z;
|
|
return this;
|
|
}
|
|
setW(w2) {
|
|
this.w = w2;
|
|
return this;
|
|
}
|
|
setComponent(index, value) {
|
|
switch (index) {
|
|
case 0:
|
|
this.x = value;
|
|
break;
|
|
case 1:
|
|
this.y = value;
|
|
break;
|
|
case 2:
|
|
this.z = value;
|
|
break;
|
|
case 3:
|
|
this.w = value;
|
|
break;
|
|
default:
|
|
throw new Error("index is out of range: " + index);
|
|
}
|
|
return this;
|
|
}
|
|
getComponent(index) {
|
|
switch (index) {
|
|
case 0:
|
|
return this.x;
|
|
case 1:
|
|
return this.y;
|
|
case 2:
|
|
return this.z;
|
|
case 3:
|
|
return this.w;
|
|
default:
|
|
throw new Error("index is out of range: " + index);
|
|
}
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.x, this.y, this.z, this.w);
|
|
}
|
|
copy(v) {
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = v.z;
|
|
this.w = v.w !== void 0 ? v.w : 1;
|
|
return this;
|
|
}
|
|
add(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.");
|
|
return this.addVectors(v, w2);
|
|
}
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z;
|
|
this.w += v.w;
|
|
return this;
|
|
}
|
|
addScalar(s) {
|
|
this.x += s;
|
|
this.y += s;
|
|
this.z += s;
|
|
this.w += s;
|
|
return this;
|
|
}
|
|
addVectors(a2, b2) {
|
|
this.x = a2.x + b2.x;
|
|
this.y = a2.y + b2.y;
|
|
this.z = a2.z + b2.z;
|
|
this.w = a2.w + b2.w;
|
|
return this;
|
|
}
|
|
addScaledVector(v, s) {
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
this.z += v.z * s;
|
|
this.w += v.w * s;
|
|
return this;
|
|
}
|
|
sub(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.");
|
|
return this.subVectors(v, w2);
|
|
}
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z;
|
|
this.w -= v.w;
|
|
return this;
|
|
}
|
|
subScalar(s) {
|
|
this.x -= s;
|
|
this.y -= s;
|
|
this.z -= s;
|
|
this.w -= s;
|
|
return this;
|
|
}
|
|
subVectors(a2, b2) {
|
|
this.x = a2.x - b2.x;
|
|
this.y = a2.y - b2.y;
|
|
this.z = a2.z - b2.z;
|
|
this.w = a2.w - b2.w;
|
|
return this;
|
|
}
|
|
multiply(v) {
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
this.z *= v.z;
|
|
this.w *= v.w;
|
|
return this;
|
|
}
|
|
multiplyScalar(scalar) {
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
this.z *= scalar;
|
|
this.w *= scalar;
|
|
return this;
|
|
}
|
|
applyMatrix4(m) {
|
|
const x = this.x, y = this.y, z = this.z, w2 = this.w;
|
|
const e = m.elements;
|
|
this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w2;
|
|
this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w2;
|
|
this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w2;
|
|
this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w2;
|
|
return this;
|
|
}
|
|
divideScalar(scalar) {
|
|
return this.multiplyScalar(1 / scalar);
|
|
}
|
|
setAxisAngleFromQuaternion(q) {
|
|
this.w = 2 * Math.acos(q.w);
|
|
const s = Math.sqrt(1 - q.w * q.w);
|
|
if (s < 1e-4) {
|
|
this.x = 1;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
} else {
|
|
this.x = q.x / s;
|
|
this.y = q.y / s;
|
|
this.z = q.z / s;
|
|
}
|
|
return this;
|
|
}
|
|
setAxisAngleFromRotationMatrix(m) {
|
|
let angle, x, y, z;
|
|
const epsilon = 0.01, epsilon2 = 0.1, te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10];
|
|
if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) {
|
|
if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) {
|
|
this.set(1, 0, 0, 0);
|
|
return this;
|
|
}
|
|
angle = Math.PI;
|
|
const xx = (m11 + 1) / 2;
|
|
const yy = (m22 + 1) / 2;
|
|
const zz = (m33 + 1) / 2;
|
|
const xy = (m12 + m21) / 4;
|
|
const xz = (m13 + m31) / 4;
|
|
const yz = (m23 + m32) / 4;
|
|
if (xx > yy && xx > zz) {
|
|
if (xx < epsilon) {
|
|
x = 0;
|
|
y = 0.707106781;
|
|
z = 0.707106781;
|
|
} else {
|
|
x = Math.sqrt(xx);
|
|
y = xy / x;
|
|
z = xz / x;
|
|
}
|
|
} else if (yy > zz) {
|
|
if (yy < epsilon) {
|
|
x = 0.707106781;
|
|
y = 0;
|
|
z = 0.707106781;
|
|
} else {
|
|
y = Math.sqrt(yy);
|
|
x = xy / y;
|
|
z = yz / y;
|
|
}
|
|
} else {
|
|
if (zz < epsilon) {
|
|
x = 0.707106781;
|
|
y = 0.707106781;
|
|
z = 0;
|
|
} else {
|
|
z = Math.sqrt(zz);
|
|
x = xz / z;
|
|
y = yz / z;
|
|
}
|
|
}
|
|
this.set(x, y, z, angle);
|
|
return this;
|
|
}
|
|
let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12));
|
|
if (Math.abs(s) < 1e-3)
|
|
s = 1;
|
|
this.x = (m32 - m23) / s;
|
|
this.y = (m13 - m31) / s;
|
|
this.z = (m21 - m12) / s;
|
|
this.w = Math.acos((m11 + m22 + m33 - 1) / 2);
|
|
return this;
|
|
}
|
|
min(v) {
|
|
this.x = Math.min(this.x, v.x);
|
|
this.y = Math.min(this.y, v.y);
|
|
this.z = Math.min(this.z, v.z);
|
|
this.w = Math.min(this.w, v.w);
|
|
return this;
|
|
}
|
|
max(v) {
|
|
this.x = Math.max(this.x, v.x);
|
|
this.y = Math.max(this.y, v.y);
|
|
this.z = Math.max(this.z, v.z);
|
|
this.w = Math.max(this.w, v.w);
|
|
return this;
|
|
}
|
|
clamp(min, max) {
|
|
this.x = Math.max(min.x, Math.min(max.x, this.x));
|
|
this.y = Math.max(min.y, Math.min(max.y, this.y));
|
|
this.z = Math.max(min.z, Math.min(max.z, this.z));
|
|
this.w = Math.max(min.w, Math.min(max.w, this.w));
|
|
return this;
|
|
}
|
|
clampScalar(minVal, maxVal) {
|
|
this.x = Math.max(minVal, Math.min(maxVal, this.x));
|
|
this.y = Math.max(minVal, Math.min(maxVal, this.y));
|
|
this.z = Math.max(minVal, Math.min(maxVal, this.z));
|
|
this.w = Math.max(minVal, Math.min(maxVal, this.w));
|
|
return this;
|
|
}
|
|
clampLength(min, max) {
|
|
const length = this.length();
|
|
return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
|
|
}
|
|
floor() {
|
|
this.x = Math.floor(this.x);
|
|
this.y = Math.floor(this.y);
|
|
this.z = Math.floor(this.z);
|
|
this.w = Math.floor(this.w);
|
|
return this;
|
|
}
|
|
ceil() {
|
|
this.x = Math.ceil(this.x);
|
|
this.y = Math.ceil(this.y);
|
|
this.z = Math.ceil(this.z);
|
|
this.w = Math.ceil(this.w);
|
|
return this;
|
|
}
|
|
round() {
|
|
this.x = Math.round(this.x);
|
|
this.y = Math.round(this.y);
|
|
this.z = Math.round(this.z);
|
|
this.w = Math.round(this.w);
|
|
return this;
|
|
}
|
|
roundToZero() {
|
|
this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x);
|
|
this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y);
|
|
this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z);
|
|
this.w = this.w < 0 ? Math.ceil(this.w) : Math.floor(this.w);
|
|
return this;
|
|
}
|
|
negate() {
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
this.z = -this.z;
|
|
this.w = -this.w;
|
|
return this;
|
|
}
|
|
dot(v) {
|
|
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
|
|
}
|
|
lengthSq() {
|
|
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
}
|
|
length() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
|
}
|
|
manhattanLength() {
|
|
return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w);
|
|
}
|
|
normalize() {
|
|
return this.divideScalar(this.length() || 1);
|
|
}
|
|
setLength(length) {
|
|
return this.normalize().multiplyScalar(length);
|
|
}
|
|
lerp(v, alpha) {
|
|
this.x += (v.x - this.x) * alpha;
|
|
this.y += (v.y - this.y) * alpha;
|
|
this.z += (v.z - this.z) * alpha;
|
|
this.w += (v.w - this.w) * alpha;
|
|
return this;
|
|
}
|
|
lerpVectors(v12, v22, alpha) {
|
|
this.x = v12.x + (v22.x - v12.x) * alpha;
|
|
this.y = v12.y + (v22.y - v12.y) * alpha;
|
|
this.z = v12.z + (v22.z - v12.z) * alpha;
|
|
this.w = v12.w + (v22.w - v12.w) * alpha;
|
|
return this;
|
|
}
|
|
equals(v) {
|
|
return v.x === this.x && v.y === this.y && v.z === this.z && v.w === this.w;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
this.x = array[offset];
|
|
this.y = array[offset + 1];
|
|
this.z = array[offset + 2];
|
|
this.w = array[offset + 3];
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
fromBufferAttribute(attribute, index, offset) {
|
|
if (offset !== void 0) {
|
|
console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute().");
|
|
}
|
|
this.x = attribute.getX(index);
|
|
this.y = attribute.getY(index);
|
|
this.z = attribute.getZ(index);
|
|
this.w = attribute.getW(index);
|
|
return this;
|
|
}
|
|
random() {
|
|
this.x = Math.random();
|
|
this.y = Math.random();
|
|
this.z = Math.random();
|
|
this.w = Math.random();
|
|
return this;
|
|
}
|
|
};
|
|
Vector4.prototype.isVector4 = true;
|
|
var WebGLRenderTarget = class extends EventDispatcher {
|
|
constructor(width, height, options = {}) {
|
|
super();
|
|
this.width = width;
|
|
this.height = height;
|
|
this.depth = 1;
|
|
this.scissor = new Vector4(0, 0, width, height);
|
|
this.scissorTest = false;
|
|
this.viewport = new Vector4(0, 0, width, height);
|
|
this.texture = new Texture(void 0, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
|
|
this.texture.isRenderTargetTexture = true;
|
|
this.texture.image = { width, height, depth: 1 };
|
|
this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false;
|
|
this.texture.internalFormat = options.internalFormat !== void 0 ? options.internalFormat : null;
|
|
this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter;
|
|
this.depthBuffer = options.depthBuffer !== void 0 ? options.depthBuffer : true;
|
|
this.stencilBuffer = options.stencilBuffer !== void 0 ? options.stencilBuffer : false;
|
|
this.depthTexture = options.depthTexture !== void 0 ? options.depthTexture : null;
|
|
}
|
|
setTexture(texture) {
|
|
texture.image = {
|
|
width: this.width,
|
|
height: this.height,
|
|
depth: this.depth
|
|
};
|
|
this.texture = texture;
|
|
}
|
|
setSize(width, height, depth = 1) {
|
|
if (this.width !== width || this.height !== height || this.depth !== depth) {
|
|
this.width = width;
|
|
this.height = height;
|
|
this.depth = depth;
|
|
this.texture.image.width = width;
|
|
this.texture.image.height = height;
|
|
this.texture.image.depth = depth;
|
|
this.dispose();
|
|
}
|
|
this.viewport.set(0, 0, width, height);
|
|
this.scissor.set(0, 0, width, height);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(source) {
|
|
this.width = source.width;
|
|
this.height = source.height;
|
|
this.depth = source.depth;
|
|
this.viewport.copy(source.viewport);
|
|
this.texture = source.texture.clone();
|
|
this.texture.image = { ...this.texture.image };
|
|
this.depthBuffer = source.depthBuffer;
|
|
this.stencilBuffer = source.stencilBuffer;
|
|
this.depthTexture = source.depthTexture;
|
|
return this;
|
|
}
|
|
dispose() {
|
|
this.dispatchEvent({ type: "dispose" });
|
|
}
|
|
};
|
|
WebGLRenderTarget.prototype.isWebGLRenderTarget = true;
|
|
var WebGLMultipleRenderTargets = class extends WebGLRenderTarget {
|
|
constructor(width, height, count) {
|
|
super(width, height);
|
|
const texture = this.texture;
|
|
this.texture = [];
|
|
for (let i = 0; i < count; i++) {
|
|
this.texture[i] = texture.clone();
|
|
}
|
|
}
|
|
setSize(width, height, depth = 1) {
|
|
if (this.width !== width || this.height !== height || this.depth !== depth) {
|
|
this.width = width;
|
|
this.height = height;
|
|
this.depth = depth;
|
|
for (let i = 0, il = this.texture.length; i < il; i++) {
|
|
this.texture[i].image.width = width;
|
|
this.texture[i].image.height = height;
|
|
this.texture[i].image.depth = depth;
|
|
}
|
|
this.dispose();
|
|
}
|
|
this.viewport.set(0, 0, width, height);
|
|
this.scissor.set(0, 0, width, height);
|
|
return this;
|
|
}
|
|
copy(source) {
|
|
this.dispose();
|
|
this.width = source.width;
|
|
this.height = source.height;
|
|
this.depth = source.depth;
|
|
this.viewport.set(0, 0, this.width, this.height);
|
|
this.scissor.set(0, 0, this.width, this.height);
|
|
this.depthBuffer = source.depthBuffer;
|
|
this.stencilBuffer = source.stencilBuffer;
|
|
this.depthTexture = source.depthTexture;
|
|
this.texture.length = 0;
|
|
for (let i = 0, il = source.texture.length; i < il; i++) {
|
|
this.texture[i] = source.texture[i].clone();
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true;
|
|
var WebGLMultisampleRenderTarget = class extends WebGLRenderTarget {
|
|
constructor(width, height, options) {
|
|
super(width, height, options);
|
|
this.samples = 4;
|
|
}
|
|
copy(source) {
|
|
super.copy.call(this, source);
|
|
this.samples = source.samples;
|
|
return this;
|
|
}
|
|
};
|
|
WebGLMultisampleRenderTarget.prototype.isWebGLMultisampleRenderTarget = true;
|
|
var Quaternion = class {
|
|
constructor(x = 0, y = 0, z = 0, w2 = 1) {
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._w = w2;
|
|
}
|
|
static slerp(qa, qb, qm, t) {
|
|
console.warn("THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.");
|
|
return qm.slerpQuaternions(qa, qb, t);
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
get x() {
|
|
return this._x;
|
|
}
|
|
set x(value) {
|
|
this._x = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get y() {
|
|
return this._y;
|
|
}
|
|
set y(value) {
|
|
this._y = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get z() {
|
|
return this._z;
|
|
}
|
|
set z(value) {
|
|
this._z = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get w() {
|
|
return this._w;
|
|
}
|
|
set w(value) {
|
|
this._w = value;
|
|
this._onChangeCallback();
|
|
}
|
|
set(x, y, z, w2) {
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._w = w2;
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor(this._x, this._y, this._z, this._w);
|
|
}
|
|
copy(quaternion) {
|
|
this._x = quaternion.x;
|
|
this._y = quaternion.y;
|
|
this._z = quaternion.z;
|
|
this._w = quaternion.w;
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
setFromEuler(euler, update) {
|
|
if (!(euler && euler.isEuler)) {
|
|
throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");
|
|
}
|
|
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 !== false)
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
setFromUnitVectors(vFrom, vTo) {
|
|
let r = vFrom.dot(vTo) + 1;
|
|
if (r < Number.EPSILON) {
|
|
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();
|
|
}
|
|
angleTo(q) {
|
|
return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1)));
|
|
}
|
|
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;
|
|
}
|
|
identity() {
|
|
return this.set(0, 0, 0, 1);
|
|
}
|
|
invert() {
|
|
return this.conjugate();
|
|
}
|
|
conjugate() {
|
|
this._x *= -1;
|
|
this._y *= -1;
|
|
this._z *= -1;
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
dot(v) {
|
|
return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
|
|
}
|
|
lengthSq() {
|
|
return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
|
|
}
|
|
length() {
|
|
return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
|
|
}
|
|
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;
|
|
}
|
|
multiply(q, p2) {
|
|
if (p2 !== void 0) {
|
|
console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.");
|
|
return this.multiplyQuaternions(q, p2);
|
|
}
|
|
return this.multiplyQuaternions(this, q);
|
|
}
|
|
premultiply(q) {
|
|
return this.multiplyQuaternions(q, this);
|
|
}
|
|
multiplyQuaternions(a2, b2) {
|
|
const qax = a2._x, qay = a2._y, qaz = a2._z, qaw = a2._w;
|
|
const qbx = b2._x, qby = b2._y, qbz = b2._z, qbw = b2._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;
|
|
}
|
|
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, w2 = this._w;
|
|
let cosHalfTheta = w2 * 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 = w2;
|
|
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 * w2 + 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();
|
|
this._onChangeCallback();
|
|
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 = w2 * 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;
|
|
}
|
|
slerpQuaternions(qa, qb, t) {
|
|
this.copy(qa).slerp(qb, t);
|
|
}
|
|
equals(quaternion) {
|
|
return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
fromBufferAttribute(attribute, index) {
|
|
this._x = attribute.getX(index);
|
|
this._y = attribute.getY(index);
|
|
this._z = attribute.getZ(index);
|
|
this._w = attribute.getW(index);
|
|
return this;
|
|
}
|
|
_onChange(callback) {
|
|
this._onChangeCallback = callback;
|
|
return this;
|
|
}
|
|
_onChangeCallback() {
|
|
}
|
|
};
|
|
Quaternion.prototype.isQuaternion = true;
|
|
var Vector3 = class {
|
|
constructor(x = 0, y = 0, z = 0) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
set(x, y, z) {
|
|
if (z === void 0)
|
|
z = this.z;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
return this;
|
|
}
|
|
setScalar(scalar) {
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
this.z = scalar;
|
|
return this;
|
|
}
|
|
setX(x) {
|
|
this.x = x;
|
|
return this;
|
|
}
|
|
setY(y) {
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
setZ(z) {
|
|
this.z = z;
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.x, this.y, this.z);
|
|
}
|
|
copy(v) {
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = v.z;
|
|
return this;
|
|
}
|
|
add(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.");
|
|
return this.addVectors(v, w2);
|
|
}
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z;
|
|
return this;
|
|
}
|
|
addScalar(s) {
|
|
this.x += s;
|
|
this.y += s;
|
|
this.z += s;
|
|
return this;
|
|
}
|
|
addVectors(a2, b2) {
|
|
this.x = a2.x + b2.x;
|
|
this.y = a2.y + b2.y;
|
|
this.z = a2.z + b2.z;
|
|
return this;
|
|
}
|
|
addScaledVector(v, s) {
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
this.z += v.z * s;
|
|
return this;
|
|
}
|
|
sub(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.");
|
|
return this.subVectors(v, w2);
|
|
}
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z;
|
|
return this;
|
|
}
|
|
subScalar(s) {
|
|
this.x -= s;
|
|
this.y -= s;
|
|
this.z -= s;
|
|
return this;
|
|
}
|
|
subVectors(a2, b2) {
|
|
this.x = a2.x - b2.x;
|
|
this.y = a2.y - b2.y;
|
|
this.z = a2.z - b2.z;
|
|
return this;
|
|
}
|
|
multiply(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.");
|
|
return this.multiplyVectors(v, w2);
|
|
}
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
this.z *= v.z;
|
|
return this;
|
|
}
|
|
multiplyScalar(scalar) {
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
this.z *= scalar;
|
|
return this;
|
|
}
|
|
multiplyVectors(a2, b2) {
|
|
this.x = a2.x * b2.x;
|
|
this.y = a2.y * b2.y;
|
|
this.z = a2.z * b2.z;
|
|
return this;
|
|
}
|
|
applyEuler(euler) {
|
|
if (!(euler && euler.isEuler)) {
|
|
console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.");
|
|
}
|
|
return this.applyQuaternion(_quaternion$4.setFromEuler(euler));
|
|
}
|
|
applyAxisAngle(axis, angle) {
|
|
return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle));
|
|
}
|
|
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;
|
|
}
|
|
applyNormalMatrix(m) {
|
|
return this.applyMatrix3(m).normalize();
|
|
}
|
|
applyMatrix4(m) {
|
|
const x = this.x, y = this.y, z = this.z;
|
|
const e = m.elements;
|
|
const w2 = 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]) * w2;
|
|
this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w2;
|
|
this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w2;
|
|
return this;
|
|
}
|
|
applyQuaternion(q) {
|
|
const x = this.x, y = this.y, z = this.z;
|
|
const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
|
|
const ix = qw * x + qy * z - qz * y;
|
|
const iy = qw * y + qz * x - qx * z;
|
|
const iz = qw * z + qx * y - qy * x;
|
|
const iw = -qx * x - qy * y - qz * z;
|
|
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
|
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
|
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
|
return this;
|
|
}
|
|
project(camera) {
|
|
return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);
|
|
}
|
|
unproject(camera) {
|
|
return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld);
|
|
}
|
|
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();
|
|
}
|
|
divide(v) {
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
this.z /= v.z;
|
|
return this;
|
|
}
|
|
divideScalar(scalar) {
|
|
return this.multiplyScalar(1 / scalar);
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
clamp(min, max) {
|
|
this.x = Math.max(min.x, Math.min(max.x, this.x));
|
|
this.y = Math.max(min.y, Math.min(max.y, this.y));
|
|
this.z = Math.max(min.z, Math.min(max.z, this.z));
|
|
return this;
|
|
}
|
|
clampScalar(minVal, maxVal) {
|
|
this.x = Math.max(minVal, Math.min(maxVal, this.x));
|
|
this.y = Math.max(minVal, Math.min(maxVal, this.y));
|
|
this.z = Math.max(minVal, Math.min(maxVal, this.z));
|
|
return this;
|
|
}
|
|
clampLength(min, max) {
|
|
const length = this.length();
|
|
return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
|
|
}
|
|
floor() {
|
|
this.x = Math.floor(this.x);
|
|
this.y = Math.floor(this.y);
|
|
this.z = Math.floor(this.z);
|
|
return this;
|
|
}
|
|
ceil() {
|
|
this.x = Math.ceil(this.x);
|
|
this.y = Math.ceil(this.y);
|
|
this.z = Math.ceil(this.z);
|
|
return this;
|
|
}
|
|
round() {
|
|
this.x = Math.round(this.x);
|
|
this.y = Math.round(this.y);
|
|
this.z = Math.round(this.z);
|
|
return this;
|
|
}
|
|
roundToZero() {
|
|
this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x);
|
|
this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y);
|
|
this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z);
|
|
return this;
|
|
}
|
|
negate() {
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
this.z = -this.z;
|
|
return this;
|
|
}
|
|
dot(v) {
|
|
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
}
|
|
lengthSq() {
|
|
return this.x * this.x + this.y * this.y + this.z * this.z;
|
|
}
|
|
length() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
}
|
|
manhattanLength() {
|
|
return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
|
|
}
|
|
normalize() {
|
|
return this.divideScalar(this.length() || 1);
|
|
}
|
|
setLength(length) {
|
|
return this.normalize().multiplyScalar(length);
|
|
}
|
|
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;
|
|
}
|
|
lerpVectors(v12, v22, alpha) {
|
|
this.x = v12.x + (v22.x - v12.x) * alpha;
|
|
this.y = v12.y + (v22.y - v12.y) * alpha;
|
|
this.z = v12.z + (v22.z - v12.z) * alpha;
|
|
return this;
|
|
}
|
|
cross(v, w2) {
|
|
if (w2 !== void 0) {
|
|
console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.");
|
|
return this.crossVectors(v, w2);
|
|
}
|
|
return this.crossVectors(this, v);
|
|
}
|
|
crossVectors(a2, b2) {
|
|
const ax = a2.x, ay = a2.y, az = a2.z;
|
|
const bx = b2.x, by = b2.y, bz = b2.z;
|
|
this.x = ay * bz - az * by;
|
|
this.y = az * bx - ax * bz;
|
|
this.z = ax * by - ay * bx;
|
|
return this;
|
|
}
|
|
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);
|
|
}
|
|
projectOnPlane(planeNormal) {
|
|
_vector$c.copy(this).projectOnVector(planeNormal);
|
|
return this.sub(_vector$c);
|
|
}
|
|
reflect(normal) {
|
|
return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)));
|
|
}
|
|
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));
|
|
}
|
|
distanceTo(v) {
|
|
return Math.sqrt(this.distanceToSquared(v));
|
|
}
|
|
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;
|
|
}
|
|
manhattanDistanceTo(v) {
|
|
return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);
|
|
}
|
|
setFromSpherical(s) {
|
|
return this.setFromSphericalCoords(s.radius, s.phi, s.theta);
|
|
}
|
|
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;
|
|
}
|
|
setFromCylindrical(c2) {
|
|
return this.setFromCylindricalCoords(c2.radius, c2.theta, c2.y);
|
|
}
|
|
setFromCylindricalCoords(radius, theta, y) {
|
|
this.x = radius * Math.sin(theta);
|
|
this.y = y;
|
|
this.z = radius * Math.cos(theta);
|
|
return this;
|
|
}
|
|
setFromMatrixPosition(m) {
|
|
const e = m.elements;
|
|
this.x = e[12];
|
|
this.y = e[13];
|
|
this.z = e[14];
|
|
return this;
|
|
}
|
|
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;
|
|
}
|
|
setFromMatrixColumn(m, index) {
|
|
return this.fromArray(m.elements, index * 4);
|
|
}
|
|
setFromMatrix3Column(m, index) {
|
|
return this.fromArray(m.elements, index * 3);
|
|
}
|
|
equals(v) {
|
|
return v.x === this.x && v.y === this.y && v.z === this.z;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
this.x = array[offset];
|
|
this.y = array[offset + 1];
|
|
this.z = array[offset + 2];
|
|
return this;
|
|
}
|
|
toArray(array = [], offset = 0) {
|
|
array[offset] = this.x;
|
|
array[offset + 1] = this.y;
|
|
array[offset + 2] = this.z;
|
|
return array;
|
|
}
|
|
fromBufferAttribute(attribute, index, offset) {
|
|
if (offset !== void 0) {
|
|
console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute().");
|
|
}
|
|
this.x = attribute.getX(index);
|
|
this.y = attribute.getY(index);
|
|
this.z = attribute.getZ(index);
|
|
return this;
|
|
}
|
|
random() {
|
|
this.x = Math.random();
|
|
this.y = Math.random();
|
|
this.z = Math.random();
|
|
return this;
|
|
}
|
|
};
|
|
Vector3.prototype.isVector3 = true;
|
|
var _vector$c = /* @__PURE__ */ new Vector3();
|
|
var _quaternion$4 = /* @__PURE__ */ new Quaternion();
|
|
var Box3 = class {
|
|
constructor(min = new Vector3(Infinity, Infinity, Infinity), max = new Vector3(-Infinity, -Infinity, -Infinity)) {
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
set(min, max) {
|
|
this.min.copy(min);
|
|
this.max.copy(max);
|
|
return this;
|
|
}
|
|
setFromArray(array) {
|
|
let minX = Infinity;
|
|
let minY = Infinity;
|
|
let minZ = Infinity;
|
|
let maxX = -Infinity;
|
|
let maxY = -Infinity;
|
|
let maxZ = -Infinity;
|
|
for (let i = 0, l = array.length; i < l; i += 3) {
|
|
const x = array[i];
|
|
const y = array[i + 1];
|
|
const z = array[i + 2];
|
|
if (x < minX)
|
|
minX = x;
|
|
if (y < minY)
|
|
minY = y;
|
|
if (z < minZ)
|
|
minZ = z;
|
|
if (x > maxX)
|
|
maxX = x;
|
|
if (y > maxY)
|
|
maxY = y;
|
|
if (z > maxZ)
|
|
maxZ = z;
|
|
}
|
|
this.min.set(minX, minY, minZ);
|
|
this.max.set(maxX, maxY, maxZ);
|
|
return this;
|
|
}
|
|
setFromBufferAttribute(attribute) {
|
|
let minX = Infinity;
|
|
let minY = Infinity;
|
|
let minZ = Infinity;
|
|
let maxX = -Infinity;
|
|
let maxY = -Infinity;
|
|
let maxZ = -Infinity;
|
|
for (let i = 0, l = attribute.count; i < l; i++) {
|
|
const x = attribute.getX(i);
|
|
const y = attribute.getY(i);
|
|
const z = attribute.getZ(i);
|
|
if (x < minX)
|
|
minX = x;
|
|
if (y < minY)
|
|
minY = y;
|
|
if (z < minZ)
|
|
minZ = z;
|
|
if (x > maxX)
|
|
maxX = x;
|
|
if (y > maxY)
|
|
maxY = y;
|
|
if (z > maxZ)
|
|
maxZ = z;
|
|
}
|
|
this.min.set(minX, minY, minZ);
|
|
this.max.set(maxX, maxY, maxZ);
|
|
return this;
|
|
}
|
|
setFromPoints(points) {
|
|
this.makeEmpty();
|
|
for (let i = 0, il = points.length; i < il; i++) {
|
|
this.expandByPoint(points[i]);
|
|
}
|
|
return this;
|
|
}
|
|
setFromCenterAndSize(center, size) {
|
|
const halfSize = _vector$b.copy(size).multiplyScalar(0.5);
|
|
this.min.copy(center).sub(halfSize);
|
|
this.max.copy(center).add(halfSize);
|
|
return this;
|
|
}
|
|
setFromObject(object) {
|
|
this.makeEmpty();
|
|
return this.expandByObject(object);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(box) {
|
|
this.min.copy(box.min);
|
|
this.max.copy(box.max);
|
|
return this;
|
|
}
|
|
makeEmpty() {
|
|
this.min.x = this.min.y = this.min.z = Infinity;
|
|
this.max.x = this.max.y = this.max.z = -Infinity;
|
|
return this;
|
|
}
|
|
isEmpty() {
|
|
return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z;
|
|
}
|
|
getCenter(target) {
|
|
return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);
|
|
}
|
|
getSize(target) {
|
|
return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min);
|
|
}
|
|
expandByPoint(point) {
|
|
this.min.min(point);
|
|
this.max.max(point);
|
|
return this;
|
|
}
|
|
expandByVector(vector) {
|
|
this.min.sub(vector);
|
|
this.max.add(vector);
|
|
return this;
|
|
}
|
|
expandByScalar(scalar) {
|
|
this.min.addScalar(-scalar);
|
|
this.max.addScalar(scalar);
|
|
return this;
|
|
}
|
|
expandByObject(object) {
|
|
object.updateWorldMatrix(false, false);
|
|
const geometry = object.geometry;
|
|
if (geometry !== void 0) {
|
|
if (geometry.boundingBox === null) {
|
|
geometry.computeBoundingBox();
|
|
}
|
|
_box$3.copy(geometry.boundingBox);
|
|
_box$3.applyMatrix4(object.matrixWorld);
|
|
this.union(_box$3);
|
|
}
|
|
const children = object.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
this.expandByObject(children[i]);
|
|
}
|
|
return this;
|
|
}
|
|
containsPoint(point) {
|
|
return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true;
|
|
}
|
|
containsBox(box) {
|
|
return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z;
|
|
}
|
|
getParameter(point, target) {
|
|
return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z));
|
|
}
|
|
intersectsBox(box) {
|
|
return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
|
|
}
|
|
intersectsSphere(sphere) {
|
|
this.clampPoint(sphere.center, _vector$b);
|
|
return _vector$b.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;
|
|
}
|
|
intersectsPlane(plane) {
|
|
let min, max;
|
|
if (plane.normal.x > 0) {
|
|
min = plane.normal.x * this.min.x;
|
|
max = plane.normal.x * this.max.x;
|
|
} else {
|
|
min = plane.normal.x * this.max.x;
|
|
max = plane.normal.x * this.min.x;
|
|
}
|
|
if (plane.normal.y > 0) {
|
|
min += plane.normal.y * this.min.y;
|
|
max += plane.normal.y * this.max.y;
|
|
} else {
|
|
min += plane.normal.y * this.max.y;
|
|
max += plane.normal.y * this.min.y;
|
|
}
|
|
if (plane.normal.z > 0) {
|
|
min += plane.normal.z * this.min.z;
|
|
max += plane.normal.z * this.max.z;
|
|
} else {
|
|
min += plane.normal.z * this.max.z;
|
|
max += plane.normal.z * this.min.z;
|
|
}
|
|
return min <= -plane.constant && max >= -plane.constant;
|
|
}
|
|
intersectsTriangle(triangle) {
|
|
if (this.isEmpty()) {
|
|
return false;
|
|
}
|
|
this.getCenter(_center);
|
|
_extents.subVectors(this.max, _center);
|
|
_v0$2.subVectors(triangle.a, _center);
|
|
_v1$7.subVectors(triangle.b, _center);
|
|
_v2$3.subVectors(triangle.c, _center);
|
|
_f0.subVectors(_v1$7, _v0$2);
|
|
_f1.subVectors(_v2$3, _v1$7);
|
|
_f2.subVectors(_v0$2, _v2$3);
|
|
let axes = [
|
|
0,
|
|
-_f0.z,
|
|
_f0.y,
|
|
0,
|
|
-_f1.z,
|
|
_f1.y,
|
|
0,
|
|
-_f2.z,
|
|
_f2.y,
|
|
_f0.z,
|
|
0,
|
|
-_f0.x,
|
|
_f1.z,
|
|
0,
|
|
-_f1.x,
|
|
_f2.z,
|
|
0,
|
|
-_f2.x,
|
|
-_f0.y,
|
|
_f0.x,
|
|
0,
|
|
-_f1.y,
|
|
_f1.x,
|
|
0,
|
|
-_f2.y,
|
|
_f2.x,
|
|
0
|
|
];
|
|
if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) {
|
|
return false;
|
|
}
|
|
axes = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
|
if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) {
|
|
return false;
|
|
}
|
|
_triangleNormal.crossVectors(_f0, _f1);
|
|
axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z];
|
|
return satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents);
|
|
}
|
|
clampPoint(point, target) {
|
|
return target.copy(point).clamp(this.min, this.max);
|
|
}
|
|
distanceToPoint(point) {
|
|
const clampedPoint = _vector$b.copy(point).clamp(this.min, this.max);
|
|
return clampedPoint.sub(point).length();
|
|
}
|
|
getBoundingSphere(target) {
|
|
this.getCenter(target.center);
|
|
target.radius = this.getSize(_vector$b).length() * 0.5;
|
|
return target;
|
|
}
|
|
intersect(box) {
|
|
this.min.max(box.min);
|
|
this.max.min(box.max);
|
|
if (this.isEmpty())
|
|
this.makeEmpty();
|
|
return this;
|
|
}
|
|
union(box) {
|
|
this.min.min(box.min);
|
|
this.max.max(box.max);
|
|
return this;
|
|
}
|
|
applyMatrix4(matrix) {
|
|
if (this.isEmpty())
|
|
return this;
|
|
_points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix);
|
|
_points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix);
|
|
_points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix);
|
|
_points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix);
|
|
_points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix);
|
|
_points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix);
|
|
_points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix);
|
|
_points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix);
|
|
this.setFromPoints(_points);
|
|
return this;
|
|
}
|
|
translate(offset) {
|
|
this.min.add(offset);
|
|
this.max.add(offset);
|
|
return this;
|
|
}
|
|
equals(box) {
|
|
return box.min.equals(this.min) && box.max.equals(this.max);
|
|
}
|
|
};
|
|
Box3.prototype.isBox3 = true;
|
|
var _points = [
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3(),
|
|
/* @__PURE__ */ new Vector3()
|
|
];
|
|
var _vector$b = /* @__PURE__ */ new Vector3();
|
|
var _box$3 = /* @__PURE__ */ new Box3();
|
|
var _v0$2 = /* @__PURE__ */ new Vector3();
|
|
var _v1$7 = /* @__PURE__ */ new Vector3();
|
|
var _v2$3 = /* @__PURE__ */ new Vector3();
|
|
var _f0 = /* @__PURE__ */ new Vector3();
|
|
var _f1 = /* @__PURE__ */ new Vector3();
|
|
var _f2 = /* @__PURE__ */ new Vector3();
|
|
var _center = /* @__PURE__ */ new Vector3();
|
|
var _extents = /* @__PURE__ */ new Vector3();
|
|
var _triangleNormal = /* @__PURE__ */ new Vector3();
|
|
var _testAxis = /* @__PURE__ */ new Vector3();
|
|
function satForAxes(axes, v02, v12, v22, extents) {
|
|
for (let i = 0, j = axes.length - 3; i <= j; i += 3) {
|
|
_testAxis.fromArray(axes, i);
|
|
const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z);
|
|
const p0 = v02.dot(_testAxis);
|
|
const p1 = v12.dot(_testAxis);
|
|
const p2 = v22.dot(_testAxis);
|
|
if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
var _box$2 = /* @__PURE__ */ new Box3();
|
|
var _v1$6 = /* @__PURE__ */ new Vector3();
|
|
var _toFarthestPoint = /* @__PURE__ */ new Vector3();
|
|
var _toPoint = /* @__PURE__ */ new Vector3();
|
|
var Sphere = class {
|
|
constructor(center = new Vector3(), radius = -1) {
|
|
this.center = center;
|
|
this.radius = radius;
|
|
}
|
|
set(center, radius) {
|
|
this.center.copy(center);
|
|
this.radius = radius;
|
|
return this;
|
|
}
|
|
setFromPoints(points, optionalCenter) {
|
|
const center = this.center;
|
|
if (optionalCenter !== void 0) {
|
|
center.copy(optionalCenter);
|
|
} else {
|
|
_box$2.setFromPoints(points).getCenter(center);
|
|
}
|
|
let maxRadiusSq = 0;
|
|
for (let i = 0, il = points.length; i < il; i++) {
|
|
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
|
|
}
|
|
this.radius = Math.sqrt(maxRadiusSq);
|
|
return this;
|
|
}
|
|
copy(sphere) {
|
|
this.center.copy(sphere.center);
|
|
this.radius = sphere.radius;
|
|
return this;
|
|
}
|
|
isEmpty() {
|
|
return this.radius < 0;
|
|
}
|
|
makeEmpty() {
|
|
this.center.set(0, 0, 0);
|
|
this.radius = -1;
|
|
return this;
|
|
}
|
|
containsPoint(point) {
|
|
return point.distanceToSquared(this.center) <= this.radius * this.radius;
|
|
}
|
|
distanceToPoint(point) {
|
|
return point.distanceTo(this.center) - this.radius;
|
|
}
|
|
intersectsSphere(sphere) {
|
|
const radiusSum = this.radius + sphere.radius;
|
|
return sphere.center.distanceToSquared(this.center) <= radiusSum * radiusSum;
|
|
}
|
|
intersectsBox(box) {
|
|
return box.intersectsSphere(this);
|
|
}
|
|
intersectsPlane(plane) {
|
|
return Math.abs(plane.distanceToPoint(this.center)) <= this.radius;
|
|
}
|
|
clampPoint(point, target) {
|
|
const deltaLengthSq = this.center.distanceToSquared(point);
|
|
target.copy(point);
|
|
if (deltaLengthSq > this.radius * this.radius) {
|
|
target.sub(this.center).normalize();
|
|
target.multiplyScalar(this.radius).add(this.center);
|
|
}
|
|
return target;
|
|
}
|
|
getBoundingBox(target) {
|
|
if (this.isEmpty()) {
|
|
target.makeEmpty();
|
|
return target;
|
|
}
|
|
target.set(this.center, this.center);
|
|
target.expandByScalar(this.radius);
|
|
return target;
|
|
}
|
|
applyMatrix4(matrix) {
|
|
this.center.applyMatrix4(matrix);
|
|
this.radius = this.radius * matrix.getMaxScaleOnAxis();
|
|
return this;
|
|
}
|
|
translate(offset) {
|
|
this.center.add(offset);
|
|
return this;
|
|
}
|
|
expandByPoint(point) {
|
|
_toPoint.subVectors(point, this.center);
|
|
const lengthSq = _toPoint.lengthSq();
|
|
if (lengthSq > this.radius * this.radius) {
|
|
const length = Math.sqrt(lengthSq);
|
|
const missingRadiusHalf = (length - this.radius) * 0.5;
|
|
this.center.add(_toPoint.multiplyScalar(missingRadiusHalf / length));
|
|
this.radius += missingRadiusHalf;
|
|
}
|
|
return this;
|
|
}
|
|
union(sphere) {
|
|
_toFarthestPoint.subVectors(sphere.center, this.center).normalize().multiplyScalar(sphere.radius);
|
|
this.expandByPoint(_v1$6.copy(sphere.center).add(_toFarthestPoint));
|
|
this.expandByPoint(_v1$6.copy(sphere.center).sub(_toFarthestPoint));
|
|
return this;
|
|
}
|
|
equals(sphere) {
|
|
return sphere.center.equals(this.center) && sphere.radius === this.radius;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
var _vector$a = /* @__PURE__ */ new Vector3();
|
|
var _segCenter = /* @__PURE__ */ new Vector3();
|
|
var _segDir = /* @__PURE__ */ new Vector3();
|
|
var _diff = /* @__PURE__ */ new Vector3();
|
|
var _edge1 = /* @__PURE__ */ new Vector3();
|
|
var _edge2 = /* @__PURE__ */ new Vector3();
|
|
var _normal$1 = /* @__PURE__ */ new Vector3();
|
|
var Ray = class {
|
|
constructor(origin = new Vector3(), direction = new Vector3(0, 0, -1)) {
|
|
this.origin = origin;
|
|
this.direction = direction;
|
|
}
|
|
set(origin, direction) {
|
|
this.origin.copy(origin);
|
|
this.direction.copy(direction);
|
|
return this;
|
|
}
|
|
copy(ray) {
|
|
this.origin.copy(ray.origin);
|
|
this.direction.copy(ray.direction);
|
|
return this;
|
|
}
|
|
at(t, target) {
|
|
return target.copy(this.direction).multiplyScalar(t).add(this.origin);
|
|
}
|
|
lookAt(v) {
|
|
this.direction.copy(v).sub(this.origin).normalize();
|
|
return this;
|
|
}
|
|
recast(t) {
|
|
this.origin.copy(this.at(t, _vector$a));
|
|
return this;
|
|
}
|
|
closestPointToPoint(point, target) {
|
|
target.subVectors(point, this.origin);
|
|
const directionDistance = target.dot(this.direction);
|
|
if (directionDistance < 0) {
|
|
return target.copy(this.origin);
|
|
}
|
|
return target.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
|
|
}
|
|
distanceToPoint(point) {
|
|
return Math.sqrt(this.distanceSqToPoint(point));
|
|
}
|
|
distanceSqToPoint(point) {
|
|
const directionDistance = _vector$a.subVectors(point, this.origin).dot(this.direction);
|
|
if (directionDistance < 0) {
|
|
return this.origin.distanceToSquared(point);
|
|
}
|
|
_vector$a.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
|
|
return _vector$a.distanceToSquared(point);
|
|
}
|
|
distanceSqToSegment(v02, v12, optionalPointOnRay, optionalPointOnSegment) {
|
|
_segCenter.copy(v02).add(v12).multiplyScalar(0.5);
|
|
_segDir.copy(v12).sub(v02).normalize();
|
|
_diff.copy(this.origin).sub(_segCenter);
|
|
const segExtent = v02.distanceTo(v12) * 0.5;
|
|
const a01 = -this.direction.dot(_segDir);
|
|
const b0 = _diff.dot(this.direction);
|
|
const b1 = -_diff.dot(_segDir);
|
|
const c2 = _diff.lengthSq();
|
|
const det = Math.abs(1 - a01 * a01);
|
|
let s0, s1, sqrDist, extDet;
|
|
if (det > 0) {
|
|
s0 = a01 * b1 - b0;
|
|
s1 = a01 * b0 - b1;
|
|
extDet = segExtent * det;
|
|
if (s0 >= 0) {
|
|
if (s1 >= -extDet) {
|
|
if (s1 <= extDet) {
|
|
const invDet = 1 / det;
|
|
s0 *= invDet;
|
|
s1 *= invDet;
|
|
sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c2;
|
|
} else {
|
|
s1 = segExtent;
|
|
s0 = Math.max(0, -(a01 * s1 + b0));
|
|
sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2;
|
|
}
|
|
} else {
|
|
s1 = -segExtent;
|
|
s0 = Math.max(0, -(a01 * s1 + b0));
|
|
sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2;
|
|
}
|
|
} else {
|
|
if (s1 <= -extDet) {
|
|
s0 = Math.max(0, -(-a01 * segExtent + b0));
|
|
s1 = s0 > 0 ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
|
|
sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2;
|
|
} else if (s1 <= extDet) {
|
|
s0 = 0;
|
|
s1 = Math.min(Math.max(-segExtent, -b1), segExtent);
|
|
sqrDist = s1 * (s1 + 2 * b1) + c2;
|
|
} else {
|
|
s0 = Math.max(0, -(a01 * segExtent + b0));
|
|
s1 = s0 > 0 ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
|
|
sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2;
|
|
}
|
|
}
|
|
} else {
|
|
s1 = a01 > 0 ? -segExtent : segExtent;
|
|
s0 = Math.max(0, -(a01 * s1 + b0));
|
|
sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2;
|
|
}
|
|
if (optionalPointOnRay) {
|
|
optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin);
|
|
}
|
|
if (optionalPointOnSegment) {
|
|
optionalPointOnSegment.copy(_segDir).multiplyScalar(s1).add(_segCenter);
|
|
}
|
|
return sqrDist;
|
|
}
|
|
intersectSphere(sphere, target) {
|
|
_vector$a.subVectors(sphere.center, this.origin);
|
|
const tca = _vector$a.dot(this.direction);
|
|
const d2 = _vector$a.dot(_vector$a) - tca * tca;
|
|
const radius2 = sphere.radius * sphere.radius;
|
|
if (d2 > radius2)
|
|
return null;
|
|
const thc = Math.sqrt(radius2 - d2);
|
|
const t0 = tca - thc;
|
|
const t1 = tca + thc;
|
|
if (t0 < 0 && t1 < 0)
|
|
return null;
|
|
if (t0 < 0)
|
|
return this.at(t1, target);
|
|
return this.at(t0, target);
|
|
}
|
|
intersectsSphere(sphere) {
|
|
return this.distanceSqToPoint(sphere.center) <= sphere.radius * sphere.radius;
|
|
}
|
|
distanceToPlane(plane) {
|
|
const denominator = plane.normal.dot(this.direction);
|
|
if (denominator === 0) {
|
|
if (plane.distanceToPoint(this.origin) === 0) {
|
|
return 0;
|
|
}
|
|
return null;
|
|
}
|
|
const t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
|
|
return t >= 0 ? t : null;
|
|
}
|
|
intersectPlane(plane, target) {
|
|
const t = this.distanceToPlane(plane);
|
|
if (t === null) {
|
|
return null;
|
|
}
|
|
return this.at(t, target);
|
|
}
|
|
intersectsPlane(plane) {
|
|
const distToPoint = plane.distanceToPoint(this.origin);
|
|
if (distToPoint === 0) {
|
|
return true;
|
|
}
|
|
const denominator = plane.normal.dot(this.direction);
|
|
if (denominator * distToPoint < 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
intersectBox(box, target) {
|
|
let tmin, tmax, tymin, tymax, tzmin, tzmax;
|
|
const invdirx = 1 / this.direction.x, invdiry = 1 / this.direction.y, invdirz = 1 / this.direction.z;
|
|
const origin = this.origin;
|
|
if (invdirx >= 0) {
|
|
tmin = (box.min.x - origin.x) * invdirx;
|
|
tmax = (box.max.x - origin.x) * invdirx;
|
|
} else {
|
|
tmin = (box.max.x - origin.x) * invdirx;
|
|
tmax = (box.min.x - origin.x) * invdirx;
|
|
}
|
|
if (invdiry >= 0) {
|
|
tymin = (box.min.y - origin.y) * invdiry;
|
|
tymax = (box.max.y - origin.y) * invdiry;
|
|
} else {
|
|
tymin = (box.max.y - origin.y) * invdiry;
|
|
tymax = (box.min.y - origin.y) * invdiry;
|
|
}
|
|
if (tmin > tymax || tymin > tmax)
|
|
return null;
|
|
if (tymin > tmin || tmin !== tmin)
|
|
tmin = tymin;
|
|
if (tymax < tmax || tmax !== tmax)
|
|
tmax = tymax;
|
|
if (invdirz >= 0) {
|
|
tzmin = (box.min.z - origin.z) * invdirz;
|
|
tzmax = (box.max.z - origin.z) * invdirz;
|
|
} else {
|
|
tzmin = (box.max.z - origin.z) * invdirz;
|
|
tzmax = (box.min.z - origin.z) * invdirz;
|
|
}
|
|
if (tmin > tzmax || tzmin > tmax)
|
|
return null;
|
|
if (tzmin > tmin || tmin !== tmin)
|
|
tmin = tzmin;
|
|
if (tzmax < tmax || tmax !== tmax)
|
|
tmax = tzmax;
|
|
if (tmax < 0)
|
|
return null;
|
|
return this.at(tmin >= 0 ? tmin : tmax, target);
|
|
}
|
|
intersectsBox(box) {
|
|
return this.intersectBox(box, _vector$a) !== null;
|
|
}
|
|
intersectTriangle(a2, b2, c2, backfaceCulling, target) {
|
|
_edge1.subVectors(b2, a2);
|
|
_edge2.subVectors(c2, a2);
|
|
_normal$1.crossVectors(_edge1, _edge2);
|
|
let DdN = this.direction.dot(_normal$1);
|
|
let sign2;
|
|
if (DdN > 0) {
|
|
if (backfaceCulling)
|
|
return null;
|
|
sign2 = 1;
|
|
} else if (DdN < 0) {
|
|
sign2 = -1;
|
|
DdN = -DdN;
|
|
} else {
|
|
return null;
|
|
}
|
|
_diff.subVectors(this.origin, a2);
|
|
const DdQxE2 = sign2 * this.direction.dot(_edge2.crossVectors(_diff, _edge2));
|
|
if (DdQxE2 < 0) {
|
|
return null;
|
|
}
|
|
const DdE1xQ = sign2 * this.direction.dot(_edge1.cross(_diff));
|
|
if (DdE1xQ < 0) {
|
|
return null;
|
|
}
|
|
if (DdQxE2 + DdE1xQ > DdN) {
|
|
return null;
|
|
}
|
|
const QdN = -sign2 * _diff.dot(_normal$1);
|
|
if (QdN < 0) {
|
|
return null;
|
|
}
|
|
return this.at(QdN / DdN, target);
|
|
}
|
|
applyMatrix4(matrix4) {
|
|
this.origin.applyMatrix4(matrix4);
|
|
this.direction.transformDirection(matrix4);
|
|
return this;
|
|
}
|
|
equals(ray) {
|
|
return ray.origin.equals(this.origin) && ray.direction.equals(this.direction);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
var Matrix4 = class {
|
|
constructor() {
|
|
this.elements = [
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1
|
|
];
|
|
if (arguments.length > 0) {
|
|
console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.");
|
|
}
|
|
}
|
|
set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
|
|
const te = this.elements;
|
|
te[0] = n11;
|
|
te[4] = n12;
|
|
te[8] = n13;
|
|
te[12] = n14;
|
|
te[1] = n21;
|
|
te[5] = n22;
|
|
te[9] = n23;
|
|
te[13] = n24;
|
|
te[2] = n31;
|
|
te[6] = n32;
|
|
te[10] = n33;
|
|
te[14] = n34;
|
|
te[3] = n41;
|
|
te[7] = n42;
|
|
te[11] = n43;
|
|
te[15] = n44;
|
|
return this;
|
|
}
|
|
identity() {
|
|
this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new Matrix4().fromArray(this.elements);
|
|
}
|
|
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];
|
|
te[9] = me[9];
|
|
te[10] = me[10];
|
|
te[11] = me[11];
|
|
te[12] = me[12];
|
|
te[13] = me[13];
|
|
te[14] = me[14];
|
|
te[15] = me[15];
|
|
return this;
|
|
}
|
|
copyPosition(m) {
|
|
const te = this.elements, me = m.elements;
|
|
te[12] = me[12];
|
|
te[13] = me[13];
|
|
te[14] = me[14];
|
|
return this;
|
|
}
|
|
setFromMatrix3(m) {
|
|
const me = m.elements;
|
|
this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
extractBasis(xAxis, yAxis, zAxis) {
|
|
xAxis.setFromMatrixColumn(this, 0);
|
|
yAxis.setFromMatrixColumn(this, 1);
|
|
zAxis.setFromMatrixColumn(this, 2);
|
|
return this;
|
|
}
|
|
makeBasis(xAxis, yAxis, zAxis) {
|
|
this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
extractRotation(m) {
|
|
const te = this.elements;
|
|
const me = m.elements;
|
|
const scaleX = 1 / _v1$5.setFromMatrixColumn(m, 0).length();
|
|
const scaleY = 1 / _v1$5.setFromMatrixColumn(m, 1).length();
|
|
const scaleZ = 1 / _v1$5.setFromMatrixColumn(m, 2).length();
|
|
te[0] = me[0] * scaleX;
|
|
te[1] = me[1] * scaleX;
|
|
te[2] = me[2] * scaleX;
|
|
te[3] = 0;
|
|
te[4] = me[4] * scaleY;
|
|
te[5] = me[5] * scaleY;
|
|
te[6] = me[6] * scaleY;
|
|
te[7] = 0;
|
|
te[8] = me[8] * scaleZ;
|
|
te[9] = me[9] * scaleZ;
|
|
te[10] = me[10] * scaleZ;
|
|
te[11] = 0;
|
|
te[12] = 0;
|
|
te[13] = 0;
|
|
te[14] = 0;
|
|
te[15] = 1;
|
|
return this;
|
|
}
|
|
makeRotationFromEuler(euler) {
|
|
if (!(euler && euler.isEuler)) {
|
|
console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");
|
|
}
|
|
const te = this.elements;
|
|
const x = euler.x, y = euler.y, z = euler.z;
|
|
const a2 = Math.cos(x), b2 = Math.sin(x);
|
|
const c2 = Math.cos(y), d = Math.sin(y);
|
|
const e = Math.cos(z), f = Math.sin(z);
|
|
if (euler.order === "XYZ") {
|
|
const ae = a2 * e, af = a2 * f, be = b2 * e, bf = b2 * f;
|
|
te[0] = c2 * e;
|
|
te[4] = -c2 * f;
|
|
te[8] = d;
|
|
te[1] = af + be * d;
|
|
te[5] = ae - bf * d;
|
|
te[9] = -b2 * c2;
|
|
te[2] = bf - ae * d;
|
|
te[6] = be + af * d;
|
|
te[10] = a2 * c2;
|
|
} else if (euler.order === "YXZ") {
|
|
const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f;
|
|
te[0] = ce + df * b2;
|
|
te[4] = de * b2 - cf;
|
|
te[8] = a2 * d;
|
|
te[1] = a2 * f;
|
|
te[5] = a2 * e;
|
|
te[9] = -b2;
|
|
te[2] = cf * b2 - de;
|
|
te[6] = df + ce * b2;
|
|
te[10] = a2 * c2;
|
|
} else if (euler.order === "ZXY") {
|
|
const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f;
|
|
te[0] = ce - df * b2;
|
|
te[4] = -a2 * f;
|
|
te[8] = de + cf * b2;
|
|
te[1] = cf + de * b2;
|
|
te[5] = a2 * e;
|
|
te[9] = df - ce * b2;
|
|
te[2] = -a2 * d;
|
|
te[6] = b2;
|
|
te[10] = a2 * c2;
|
|
} else if (euler.order === "ZYX") {
|
|
const ae = a2 * e, af = a2 * f, be = b2 * e, bf = b2 * f;
|
|
te[0] = c2 * e;
|
|
te[4] = be * d - af;
|
|
te[8] = ae * d + bf;
|
|
te[1] = c2 * f;
|
|
te[5] = bf * d + ae;
|
|
te[9] = af * d - be;
|
|
te[2] = -d;
|
|
te[6] = b2 * c2;
|
|
te[10] = a2 * c2;
|
|
} else if (euler.order === "YZX") {
|
|
const ac = a2 * c2, ad = a2 * d, bc = b2 * c2, bd = b2 * d;
|
|
te[0] = c2 * e;
|
|
te[4] = bd - ac * f;
|
|
te[8] = bc * f + ad;
|
|
te[1] = f;
|
|
te[5] = a2 * e;
|
|
te[9] = -b2 * e;
|
|
te[2] = -d * e;
|
|
te[6] = ad * f + bc;
|
|
te[10] = ac - bd * f;
|
|
} else if (euler.order === "XZY") {
|
|
const ac = a2 * c2, ad = a2 * d, bc = b2 * c2, bd = b2 * d;
|
|
te[0] = c2 * e;
|
|
te[4] = -f;
|
|
te[8] = d * e;
|
|
te[1] = ac * f + bd;
|
|
te[5] = a2 * e;
|
|
te[9] = ad * f - bc;
|
|
te[2] = bc * f - ad;
|
|
te[6] = b2 * e;
|
|
te[10] = bd * f + ac;
|
|
}
|
|
te[3] = 0;
|
|
te[7] = 0;
|
|
te[11] = 0;
|
|
te[12] = 0;
|
|
te[13] = 0;
|
|
te[14] = 0;
|
|
te[15] = 1;
|
|
return this;
|
|
}
|
|
makeRotationFromQuaternion(q) {
|
|
return this.compose(_zero, q, _one);
|
|
}
|
|
lookAt(eye, target, up) {
|
|
const te = this.elements;
|
|
_z.subVectors(eye, target);
|
|
if (_z.lengthSq() === 0) {
|
|
_z.z = 1;
|
|
}
|
|
_z.normalize();
|
|
_x.crossVectors(up, _z);
|
|
if (_x.lengthSq() === 0) {
|
|
if (Math.abs(up.z) === 1) {
|
|
_z.x += 1e-4;
|
|
} else {
|
|
_z.z += 1e-4;
|
|
}
|
|
_z.normalize();
|
|
_x.crossVectors(up, _z);
|
|
}
|
|
_x.normalize();
|
|
_y.crossVectors(_z, _x);
|
|
te[0] = _x.x;
|
|
te[4] = _y.x;
|
|
te[8] = _z.x;
|
|
te[1] = _x.y;
|
|
te[5] = _y.y;
|
|
te[9] = _z.y;
|
|
te[2] = _x.z;
|
|
te[6] = _y.z;
|
|
te[10] = _z.z;
|
|
return this;
|
|
}
|
|
multiply(m, n) {
|
|
if (n !== void 0) {
|
|
console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.");
|
|
return this.multiplyMatrices(m, n);
|
|
}
|
|
return this.multiplyMatrices(this, m);
|
|
}
|
|
premultiply(m) {
|
|
return this.multiplyMatrices(m, this);
|
|
}
|
|
multiplyMatrices(a2, b2) {
|
|
const ae = a2.elements;
|
|
const be = b2.elements;
|
|
const te = this.elements;
|
|
const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
|
|
const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
|
|
const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
|
|
const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
|
|
const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
|
|
const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
|
|
const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
|
|
const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
|
|
te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
|
|
te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
|
|
te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
|
|
te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
|
|
te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
|
|
te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
|
|
te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
|
|
te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
|
|
te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
|
|
te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
|
|
te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
|
|
te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
|
|
te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
|
|
te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
|
|
te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
|
|
te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
|
|
return this;
|
|
}
|
|
multiplyScalar(s) {
|
|
const te = this.elements;
|
|
te[0] *= s;
|
|
te[4] *= s;
|
|
te[8] *= s;
|
|
te[12] *= s;
|
|
te[1] *= s;
|
|
te[5] *= s;
|
|
te[9] *= s;
|
|
te[13] *= s;
|
|
te[2] *= s;
|
|
te[6] *= s;
|
|
te[10] *= s;
|
|
te[14] *= s;
|
|
te[3] *= s;
|
|
te[7] *= s;
|
|
te[11] *= s;
|
|
te[15] *= s;
|
|
return this;
|
|
}
|
|
determinant() {
|
|
const te = this.elements;
|
|
const n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12];
|
|
const n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13];
|
|
const n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14];
|
|
const n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15];
|
|
return n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31);
|
|
}
|
|
transpose() {
|
|
const te = this.elements;
|
|
let tmp3;
|
|
tmp3 = te[1];
|
|
te[1] = te[4];
|
|
te[4] = tmp3;
|
|
tmp3 = te[2];
|
|
te[2] = te[8];
|
|
te[8] = tmp3;
|
|
tmp3 = te[6];
|
|
te[6] = te[9];
|
|
te[9] = tmp3;
|
|
tmp3 = te[3];
|
|
te[3] = te[12];
|
|
te[12] = tmp3;
|
|
tmp3 = te[7];
|
|
te[7] = te[13];
|
|
te[13] = tmp3;
|
|
tmp3 = te[11];
|
|
te[11] = te[14];
|
|
te[14] = tmp3;
|
|
return this;
|
|
}
|
|
setPosition(x, y, z) {
|
|
const te = this.elements;
|
|
if (x.isVector3) {
|
|
te[12] = x.x;
|
|
te[13] = x.y;
|
|
te[14] = x.z;
|
|
} else {
|
|
te[12] = x;
|
|
te[13] = y;
|
|
te[14] = z;
|
|
}
|
|
return this;
|
|
}
|
|
invert() {
|
|
const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n41 = te[3], n12 = te[4], n22 = te[5], n32 = te[6], n42 = te[7], n13 = te[8], n23 = te[9], n33 = te[10], n43 = te[11], n14 = te[12], n24 = te[13], n34 = te[14], n44 = te[15], t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
|
|
const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
|
|
if (det === 0)
|
|
return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
const detInv = 1 / det;
|
|
te[0] = t11 * detInv;
|
|
te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
|
|
te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
|
|
te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
|
|
te[4] = t12 * detInv;
|
|
te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
|
|
te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
|
|
te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
|
|
te[8] = t13 * detInv;
|
|
te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
|
|
te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
|
|
te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
|
|
te[12] = t14 * detInv;
|
|
te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
|
|
te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
|
|
te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
|
|
return this;
|
|
}
|
|
scale(v) {
|
|
const te = this.elements;
|
|
const x = v.x, y = v.y, z = v.z;
|
|
te[0] *= x;
|
|
te[4] *= y;
|
|
te[8] *= z;
|
|
te[1] *= x;
|
|
te[5] *= y;
|
|
te[9] *= z;
|
|
te[2] *= x;
|
|
te[6] *= y;
|
|
te[10] *= z;
|
|
te[3] *= x;
|
|
te[7] *= y;
|
|
te[11] *= z;
|
|
return this;
|
|
}
|
|
getMaxScaleOnAxis() {
|
|
const te = this.elements;
|
|
const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
|
|
const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
|
|
const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
|
|
return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
|
|
}
|
|
makeTranslation(x, y, z) {
|
|
this.set(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeRotationX(theta) {
|
|
const c2 = Math.cos(theta), s = Math.sin(theta);
|
|
this.set(1, 0, 0, 0, 0, c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeRotationY(theta) {
|
|
const c2 = Math.cos(theta), s = Math.sin(theta);
|
|
this.set(c2, 0, s, 0, 0, 1, 0, 0, -s, 0, c2, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeRotationZ(theta) {
|
|
const c2 = Math.cos(theta), s = Math.sin(theta);
|
|
this.set(c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeRotationAxis(axis, angle) {
|
|
const c2 = Math.cos(angle);
|
|
const s = Math.sin(angle);
|
|
const t = 1 - c2;
|
|
const x = axis.x, y = axis.y, z = axis.z;
|
|
const tx = t * x, ty = t * y;
|
|
this.set(tx * x + c2, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c2, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c2, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeScale(x, y, z) {
|
|
this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
makeShear(xy, xz, yx, yz, zx, zy) {
|
|
this.set(1, yx, zx, 0, xy, 1, zy, 0, xz, yz, 1, 0, 0, 0, 0, 1);
|
|
return this;
|
|
}
|
|
compose(position, quaternion, scale) {
|
|
const te = this.elements;
|
|
const x = quaternion._x, y = quaternion._y, z = quaternion._z, w2 = quaternion._w;
|
|
const x2 = x + x, y2 = y + y, z2 = z + z;
|
|
const xx = x * x2, xy = x * y2, xz = x * z2;
|
|
const yy = y * y2, yz = y * z2, zz = z * z2;
|
|
const wx = w2 * x2, wy = w2 * y2, wz = w2 * z2;
|
|
const sx = scale.x, sy = scale.y, sz = scale.z;
|
|
te[0] = (1 - (yy + zz)) * sx;
|
|
te[1] = (xy + wz) * sx;
|
|
te[2] = (xz - wy) * sx;
|
|
te[3] = 0;
|
|
te[4] = (xy - wz) * sy;
|
|
te[5] = (1 - (xx + zz)) * sy;
|
|
te[6] = (yz + wx) * sy;
|
|
te[7] = 0;
|
|
te[8] = (xz + wy) * sz;
|
|
te[9] = (yz - wx) * sz;
|
|
te[10] = (1 - (xx + yy)) * sz;
|
|
te[11] = 0;
|
|
te[12] = position.x;
|
|
te[13] = position.y;
|
|
te[14] = position.z;
|
|
te[15] = 1;
|
|
return this;
|
|
}
|
|
decompose(position, quaternion, scale) {
|
|
const te = this.elements;
|
|
let sx = _v1$5.set(te[0], te[1], te[2]).length();
|
|
const sy = _v1$5.set(te[4], te[5], te[6]).length();
|
|
const sz = _v1$5.set(te[8], te[9], te[10]).length();
|
|
const det = this.determinant();
|
|
if (det < 0)
|
|
sx = -sx;
|
|
position.x = te[12];
|
|
position.y = te[13];
|
|
position.z = te[14];
|
|
_m1$2.copy(this);
|
|
const invSX = 1 / sx;
|
|
const invSY = 1 / sy;
|
|
const invSZ = 1 / sz;
|
|
_m1$2.elements[0] *= invSX;
|
|
_m1$2.elements[1] *= invSX;
|
|
_m1$2.elements[2] *= invSX;
|
|
_m1$2.elements[4] *= invSY;
|
|
_m1$2.elements[5] *= invSY;
|
|
_m1$2.elements[6] *= invSY;
|
|
_m1$2.elements[8] *= invSZ;
|
|
_m1$2.elements[9] *= invSZ;
|
|
_m1$2.elements[10] *= invSZ;
|
|
quaternion.setFromRotationMatrix(_m1$2);
|
|
scale.x = sx;
|
|
scale.y = sy;
|
|
scale.z = sz;
|
|
return this;
|
|
}
|
|
makePerspective(left, right, top, bottom, near, far) {
|
|
if (far === void 0) {
|
|
console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");
|
|
}
|
|
const te = this.elements;
|
|
const x = 2 * near / (right - left);
|
|
const y = 2 * near / (top - bottom);
|
|
const a2 = (right + left) / (right - left);
|
|
const b2 = (top + bottom) / (top - bottom);
|
|
const c2 = -(far + near) / (far - near);
|
|
const d = -2 * far * near / (far - near);
|
|
te[0] = x;
|
|
te[4] = 0;
|
|
te[8] = a2;
|
|
te[12] = 0;
|
|
te[1] = 0;
|
|
te[5] = y;
|
|
te[9] = b2;
|
|
te[13] = 0;
|
|
te[2] = 0;
|
|
te[6] = 0;
|
|
te[10] = c2;
|
|
te[14] = d;
|
|
te[3] = 0;
|
|
te[7] = 0;
|
|
te[11] = -1;
|
|
te[15] = 0;
|
|
return this;
|
|
}
|
|
makeOrthographic(left, right, top, bottom, near, far) {
|
|
const te = this.elements;
|
|
const w2 = 1 / (right - left);
|
|
const h = 1 / (top - bottom);
|
|
const p2 = 1 / (far - near);
|
|
const x = (right + left) * w2;
|
|
const y = (top + bottom) * h;
|
|
const z = (far + near) * p2;
|
|
te[0] = 2 * w2;
|
|
te[4] = 0;
|
|
te[8] = 0;
|
|
te[12] = -x;
|
|
te[1] = 0;
|
|
te[5] = 2 * h;
|
|
te[9] = 0;
|
|
te[13] = -y;
|
|
te[2] = 0;
|
|
te[6] = 0;
|
|
te[10] = -2 * p2;
|
|
te[14] = -z;
|
|
te[3] = 0;
|
|
te[7] = 0;
|
|
te[11] = 0;
|
|
te[15] = 1;
|
|
return this;
|
|
}
|
|
equals(matrix) {
|
|
const te = this.elements;
|
|
const me = matrix.elements;
|
|
for (let i = 0; i < 16; i++) {
|
|
if (te[i] !== me[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
for (let i = 0; i < 16; i++) {
|
|
this.elements[i] = array[i + offset];
|
|
}
|
|
return this;
|
|
}
|
|
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];
|
|
array[offset + 9] = te[9];
|
|
array[offset + 10] = te[10];
|
|
array[offset + 11] = te[11];
|
|
array[offset + 12] = te[12];
|
|
array[offset + 13] = te[13];
|
|
array[offset + 14] = te[14];
|
|
array[offset + 15] = te[15];
|
|
return array;
|
|
}
|
|
};
|
|
Matrix4.prototype.isMatrix4 = true;
|
|
var _v1$5 = /* @__PURE__ */ new Vector3();
|
|
var _m1$2 = /* @__PURE__ */ new Matrix4();
|
|
var _zero = /* @__PURE__ */ new Vector3(0, 0, 0);
|
|
var _one = /* @__PURE__ */ new Vector3(1, 1, 1);
|
|
var _x = /* @__PURE__ */ new Vector3();
|
|
var _y = /* @__PURE__ */ new Vector3();
|
|
var _z = /* @__PURE__ */ new Vector3();
|
|
var _matrix$1 = /* @__PURE__ */ new Matrix4();
|
|
var _quaternion$3 = /* @__PURE__ */ new Quaternion();
|
|
var Euler = class {
|
|
constructor(x = 0, y = 0, z = 0, order = Euler.DefaultOrder) {
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order;
|
|
}
|
|
get x() {
|
|
return this._x;
|
|
}
|
|
set x(value) {
|
|
this._x = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get y() {
|
|
return this._y;
|
|
}
|
|
set y(value) {
|
|
this._y = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get z() {
|
|
return this._z;
|
|
}
|
|
set z(value) {
|
|
this._z = value;
|
|
this._onChangeCallback();
|
|
}
|
|
get order() {
|
|
return this._order;
|
|
}
|
|
set order(value) {
|
|
this._order = value;
|
|
this._onChangeCallback();
|
|
}
|
|
set(x, y, z, order = this._order) {
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order;
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor(this._x, this._y, this._z, this._order);
|
|
}
|
|
copy(euler) {
|
|
this._x = euler._x;
|
|
this._y = euler._y;
|
|
this._z = euler._z;
|
|
this._order = euler._order;
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
setFromRotationMatrix(m, order = this._order, update = true) {
|
|
const te = m.elements;
|
|
const m11 = te[0], m12 = te[4], m13 = te[8];
|
|
const m21 = te[1], m22 = te[5], m23 = te[9];
|
|
const m31 = te[2], m32 = te[6], m33 = te[10];
|
|
switch (order) {
|
|
case "XYZ":
|
|
this._y = Math.asin(clamp(m13, -1, 1));
|
|
if (Math.abs(m13) < 0.9999999) {
|
|
this._x = Math.atan2(-m23, m33);
|
|
this._z = Math.atan2(-m12, m11);
|
|
} else {
|
|
this._x = Math.atan2(m32, m22);
|
|
this._z = 0;
|
|
}
|
|
break;
|
|
case "YXZ":
|
|
this._x = Math.asin(-clamp(m23, -1, 1));
|
|
if (Math.abs(m23) < 0.9999999) {
|
|
this._y = Math.atan2(m13, m33);
|
|
this._z = Math.atan2(m21, m22);
|
|
} else {
|
|
this._y = Math.atan2(-m31, m11);
|
|
this._z = 0;
|
|
}
|
|
break;
|
|
case "ZXY":
|
|
this._x = Math.asin(clamp(m32, -1, 1));
|
|
if (Math.abs(m32) < 0.9999999) {
|
|
this._y = Math.atan2(-m31, m33);
|
|
this._z = Math.atan2(-m12, m22);
|
|
} else {
|
|
this._y = 0;
|
|
this._z = Math.atan2(m21, m11);
|
|
}
|
|
break;
|
|
case "ZYX":
|
|
this._y = Math.asin(-clamp(m31, -1, 1));
|
|
if (Math.abs(m31) < 0.9999999) {
|
|
this._x = Math.atan2(m32, m33);
|
|
this._z = Math.atan2(m21, m11);
|
|
} else {
|
|
this._x = 0;
|
|
this._z = Math.atan2(-m12, m22);
|
|
}
|
|
break;
|
|
case "YZX":
|
|
this._z = Math.asin(clamp(m21, -1, 1));
|
|
if (Math.abs(m21) < 0.9999999) {
|
|
this._x = Math.atan2(-m23, m22);
|
|
this._y = Math.atan2(-m31, m11);
|
|
} else {
|
|
this._x = 0;
|
|
this._y = Math.atan2(m13, m33);
|
|
}
|
|
break;
|
|
case "XZY":
|
|
this._z = Math.asin(-clamp(m12, -1, 1));
|
|
if (Math.abs(m12) < 0.9999999) {
|
|
this._x = Math.atan2(m32, m22);
|
|
this._y = Math.atan2(m13, m11);
|
|
} else {
|
|
this._x = Math.atan2(-m23, m33);
|
|
this._y = 0;
|
|
}
|
|
break;
|
|
default:
|
|
console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: " + order);
|
|
}
|
|
this._order = order;
|
|
if (update === true)
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
setFromQuaternion(q, order, update) {
|
|
_matrix$1.makeRotationFromQuaternion(q);
|
|
return this.setFromRotationMatrix(_matrix$1, order, update);
|
|
}
|
|
setFromVector3(v, order = this._order) {
|
|
return this.set(v.x, v.y, v.z, order);
|
|
}
|
|
reorder(newOrder) {
|
|
_quaternion$3.setFromEuler(this);
|
|
return this.setFromQuaternion(_quaternion$3, newOrder);
|
|
}
|
|
equals(euler) {
|
|
return euler._x === this._x && euler._y === this._y && euler._z === this._z && euler._order === this._order;
|
|
}
|
|
fromArray(array) {
|
|
this._x = array[0];
|
|
this._y = array[1];
|
|
this._z = array[2];
|
|
if (array[3] !== void 0)
|
|
this._order = array[3];
|
|
this._onChangeCallback();
|
|
return this;
|
|
}
|
|
toArray(array = [], offset = 0) {
|
|
array[offset] = this._x;
|
|
array[offset + 1] = this._y;
|
|
array[offset + 2] = this._z;
|
|
array[offset + 3] = this._order;
|
|
return array;
|
|
}
|
|
toVector3(optionalResult) {
|
|
if (optionalResult) {
|
|
return optionalResult.set(this._x, this._y, this._z);
|
|
} else {
|
|
return new Vector3(this._x, this._y, this._z);
|
|
}
|
|
}
|
|
_onChange(callback) {
|
|
this._onChangeCallback = callback;
|
|
return this;
|
|
}
|
|
_onChangeCallback() {
|
|
}
|
|
};
|
|
Euler.prototype.isEuler = true;
|
|
Euler.DefaultOrder = "XYZ";
|
|
Euler.RotationOrders = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"];
|
|
var Layers = class {
|
|
constructor() {
|
|
this.mask = 1 | 0;
|
|
}
|
|
set(channel) {
|
|
this.mask = 1 << channel | 0;
|
|
}
|
|
enable(channel) {
|
|
this.mask |= 1 << channel | 0;
|
|
}
|
|
enableAll() {
|
|
this.mask = 4294967295 | 0;
|
|
}
|
|
toggle(channel) {
|
|
this.mask ^= 1 << channel | 0;
|
|
}
|
|
disable(channel) {
|
|
this.mask &= ~(1 << channel | 0);
|
|
}
|
|
disableAll() {
|
|
this.mask = 0;
|
|
}
|
|
test(layers) {
|
|
return (this.mask & layers.mask) !== 0;
|
|
}
|
|
};
|
|
var _object3DId = 0;
|
|
var _v1$4 = /* @__PURE__ */ new Vector3();
|
|
var _q1 = /* @__PURE__ */ new Quaternion();
|
|
var _m1$1 = /* @__PURE__ */ new Matrix4();
|
|
var _target = /* @__PURE__ */ new Vector3();
|
|
var _position$3 = /* @__PURE__ */ new Vector3();
|
|
var _scale$2 = /* @__PURE__ */ new Vector3();
|
|
var _quaternion$2 = /* @__PURE__ */ new Quaternion();
|
|
var _xAxis = /* @__PURE__ */ new Vector3(1, 0, 0);
|
|
var _yAxis = /* @__PURE__ */ new Vector3(0, 1, 0);
|
|
var _zAxis = /* @__PURE__ */ new Vector3(0, 0, 1);
|
|
var _addedEvent = { type: "added" };
|
|
var _removedEvent = { type: "removed" };
|
|
var Object3D = class extends EventDispatcher {
|
|
constructor() {
|
|
super();
|
|
Object.defineProperty(this, "id", { value: _object3DId++ });
|
|
this.uuid = generateUUID();
|
|
this.name = "";
|
|
this.type = "Object3D";
|
|
this.parent = null;
|
|
this.children = [];
|
|
this.up = Object3D.DefaultUp.clone();
|
|
const position = new Vector3();
|
|
const rotation = new Euler();
|
|
const quaternion = new Quaternion();
|
|
const scale = new Vector3(1, 1, 1);
|
|
function onRotationChange() {
|
|
quaternion.setFromEuler(rotation, false);
|
|
}
|
|
function onQuaternionChange() {
|
|
rotation.setFromQuaternion(quaternion, void 0, false);
|
|
}
|
|
rotation._onChange(onRotationChange);
|
|
quaternion._onChange(onQuaternionChange);
|
|
Object.defineProperties(this, {
|
|
position: {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: position
|
|
},
|
|
rotation: {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: rotation
|
|
},
|
|
quaternion: {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: quaternion
|
|
},
|
|
scale: {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: scale
|
|
},
|
|
modelViewMatrix: {
|
|
value: new Matrix4()
|
|
},
|
|
normalMatrix: {
|
|
value: new Matrix3()
|
|
}
|
|
});
|
|
this.matrix = new Matrix4();
|
|
this.matrixWorld = new Matrix4();
|
|
this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
|
|
this.matrixWorldNeedsUpdate = false;
|
|
this.layers = new Layers();
|
|
this.visible = true;
|
|
this.castShadow = false;
|
|
this.receiveShadow = false;
|
|
this.frustumCulled = true;
|
|
this.renderOrder = 0;
|
|
this.animations = [];
|
|
this.userData = {};
|
|
}
|
|
onBeforeRender() {
|
|
}
|
|
onAfterRender() {
|
|
}
|
|
applyMatrix4(matrix) {
|
|
if (this.matrixAutoUpdate)
|
|
this.updateMatrix();
|
|
this.matrix.premultiply(matrix);
|
|
this.matrix.decompose(this.position, this.quaternion, this.scale);
|
|
}
|
|
applyQuaternion(q) {
|
|
this.quaternion.premultiply(q);
|
|
return this;
|
|
}
|
|
setRotationFromAxisAngle(axis, angle) {
|
|
this.quaternion.setFromAxisAngle(axis, angle);
|
|
}
|
|
setRotationFromEuler(euler) {
|
|
this.quaternion.setFromEuler(euler, true);
|
|
}
|
|
setRotationFromMatrix(m) {
|
|
this.quaternion.setFromRotationMatrix(m);
|
|
}
|
|
setRotationFromQuaternion(q) {
|
|
this.quaternion.copy(q);
|
|
}
|
|
rotateOnAxis(axis, angle) {
|
|
_q1.setFromAxisAngle(axis, angle);
|
|
this.quaternion.multiply(_q1);
|
|
return this;
|
|
}
|
|
rotateOnWorldAxis(axis, angle) {
|
|
_q1.setFromAxisAngle(axis, angle);
|
|
this.quaternion.premultiply(_q1);
|
|
return this;
|
|
}
|
|
rotateX(angle) {
|
|
return this.rotateOnAxis(_xAxis, angle);
|
|
}
|
|
rotateY(angle) {
|
|
return this.rotateOnAxis(_yAxis, angle);
|
|
}
|
|
rotateZ(angle) {
|
|
return this.rotateOnAxis(_zAxis, angle);
|
|
}
|
|
translateOnAxis(axis, distance) {
|
|
_v1$4.copy(axis).applyQuaternion(this.quaternion);
|
|
this.position.add(_v1$4.multiplyScalar(distance));
|
|
return this;
|
|
}
|
|
translateX(distance) {
|
|
return this.translateOnAxis(_xAxis, distance);
|
|
}
|
|
translateY(distance) {
|
|
return this.translateOnAxis(_yAxis, distance);
|
|
}
|
|
translateZ(distance) {
|
|
return this.translateOnAxis(_zAxis, distance);
|
|
}
|
|
localToWorld(vector) {
|
|
return vector.applyMatrix4(this.matrixWorld);
|
|
}
|
|
worldToLocal(vector) {
|
|
return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert());
|
|
}
|
|
lookAt(x, y, z) {
|
|
if (x.isVector3) {
|
|
_target.copy(x);
|
|
} else {
|
|
_target.set(x, y, z);
|
|
}
|
|
const parent = this.parent;
|
|
this.updateWorldMatrix(true, false);
|
|
_position$3.setFromMatrixPosition(this.matrixWorld);
|
|
if (this.isCamera || this.isLight) {
|
|
_m1$1.lookAt(_position$3, _target, this.up);
|
|
} else {
|
|
_m1$1.lookAt(_target, _position$3, this.up);
|
|
}
|
|
this.quaternion.setFromRotationMatrix(_m1$1);
|
|
if (parent) {
|
|
_m1$1.extractRotation(parent.matrixWorld);
|
|
_q1.setFromRotationMatrix(_m1$1);
|
|
this.quaternion.premultiply(_q1.invert());
|
|
}
|
|
}
|
|
add(object) {
|
|
if (arguments.length > 1) {
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
this.add(arguments[i]);
|
|
}
|
|
return this;
|
|
}
|
|
if (object === this) {
|
|
console.error("THREE.Object3D.add: object can't be added as a child of itself.", object);
|
|
return this;
|
|
}
|
|
if (object && object.isObject3D) {
|
|
if (object.parent !== null) {
|
|
object.parent.remove(object);
|
|
}
|
|
object.parent = this;
|
|
this.children.push(object);
|
|
object.dispatchEvent(_addedEvent);
|
|
} else {
|
|
console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object);
|
|
}
|
|
return this;
|
|
}
|
|
remove(object) {
|
|
if (arguments.length > 1) {
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
this.remove(arguments[i]);
|
|
}
|
|
return this;
|
|
}
|
|
const index = this.children.indexOf(object);
|
|
if (index !== -1) {
|
|
object.parent = null;
|
|
this.children.splice(index, 1);
|
|
object.dispatchEvent(_removedEvent);
|
|
}
|
|
return this;
|
|
}
|
|
removeFromParent() {
|
|
const parent = this.parent;
|
|
if (parent !== null) {
|
|
parent.remove(this);
|
|
}
|
|
return this;
|
|
}
|
|
clear() {
|
|
for (let i = 0; i < this.children.length; i++) {
|
|
const object = this.children[i];
|
|
object.parent = null;
|
|
object.dispatchEvent(_removedEvent);
|
|
}
|
|
this.children.length = 0;
|
|
return this;
|
|
}
|
|
attach(object) {
|
|
this.updateWorldMatrix(true, false);
|
|
_m1$1.copy(this.matrixWorld).invert();
|
|
if (object.parent !== null) {
|
|
object.parent.updateWorldMatrix(true, false);
|
|
_m1$1.multiply(object.parent.matrixWorld);
|
|
}
|
|
object.applyMatrix4(_m1$1);
|
|
this.add(object);
|
|
object.updateWorldMatrix(false, true);
|
|
return this;
|
|
}
|
|
getObjectById(id) {
|
|
return this.getObjectByProperty("id", id);
|
|
}
|
|
getObjectByName(name) {
|
|
return this.getObjectByProperty("name", name);
|
|
}
|
|
getObjectByProperty(name, value) {
|
|
if (this[name] === value)
|
|
return this;
|
|
for (let i = 0, l = this.children.length; i < l; i++) {
|
|
const child = this.children[i];
|
|
const object = child.getObjectByProperty(name, value);
|
|
if (object !== void 0) {
|
|
return object;
|
|
}
|
|
}
|
|
return void 0;
|
|
}
|
|
getWorldPosition(target) {
|
|
this.updateWorldMatrix(true, false);
|
|
return target.setFromMatrixPosition(this.matrixWorld);
|
|
}
|
|
getWorldQuaternion(target) {
|
|
this.updateWorldMatrix(true, false);
|
|
this.matrixWorld.decompose(_position$3, target, _scale$2);
|
|
return target;
|
|
}
|
|
getWorldScale(target) {
|
|
this.updateWorldMatrix(true, false);
|
|
this.matrixWorld.decompose(_position$3, _quaternion$2, target);
|
|
return target;
|
|
}
|
|
getWorldDirection(target) {
|
|
this.updateWorldMatrix(true, false);
|
|
const e = this.matrixWorld.elements;
|
|
return target.set(e[8], e[9], e[10]).normalize();
|
|
}
|
|
raycast() {
|
|
}
|
|
traverse(callback) {
|
|
callback(this);
|
|
const children = this.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
children[i].traverse(callback);
|
|
}
|
|
}
|
|
traverseVisible(callback) {
|
|
if (this.visible === false)
|
|
return;
|
|
callback(this);
|
|
const children = this.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
children[i].traverseVisible(callback);
|
|
}
|
|
}
|
|
traverseAncestors(callback) {
|
|
const parent = this.parent;
|
|
if (parent !== null) {
|
|
callback(parent);
|
|
parent.traverseAncestors(callback);
|
|
}
|
|
}
|
|
updateMatrix() {
|
|
this.matrix.compose(this.position, this.quaternion, this.scale);
|
|
this.matrixWorldNeedsUpdate = true;
|
|
}
|
|
updateMatrixWorld(force) {
|
|
if (this.matrixAutoUpdate)
|
|
this.updateMatrix();
|
|
if (this.matrixWorldNeedsUpdate || force) {
|
|
if (this.parent === null) {
|
|
this.matrixWorld.copy(this.matrix);
|
|
} else {
|
|
this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
|
|
}
|
|
this.matrixWorldNeedsUpdate = false;
|
|
force = true;
|
|
}
|
|
const children = this.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
children[i].updateMatrixWorld(force);
|
|
}
|
|
}
|
|
updateWorldMatrix(updateParents, updateChildren) {
|
|
const parent = this.parent;
|
|
if (updateParents === true && parent !== null) {
|
|
parent.updateWorldMatrix(true, false);
|
|
}
|
|
if (this.matrixAutoUpdate)
|
|
this.updateMatrix();
|
|
if (this.parent === null) {
|
|
this.matrixWorld.copy(this.matrix);
|
|
} else {
|
|
this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
|
|
}
|
|
if (updateChildren === true) {
|
|
const children = this.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
children[i].updateWorldMatrix(false, true);
|
|
}
|
|
}
|
|
}
|
|
toJSON(meta) {
|
|
const isRootObject = meta === void 0 || typeof meta === "string";
|
|
const output = {};
|
|
if (isRootObject) {
|
|
meta = {
|
|
geometries: {},
|
|
materials: {},
|
|
textures: {},
|
|
images: {},
|
|
shapes: {},
|
|
skeletons: {},
|
|
animations: {}
|
|
};
|
|
output.metadata = {
|
|
version: 4.5,
|
|
type: "Object",
|
|
generator: "Object3D.toJSON"
|
|
};
|
|
}
|
|
const object = {};
|
|
object.uuid = this.uuid;
|
|
object.type = this.type;
|
|
if (this.name !== "")
|
|
object.name = this.name;
|
|
if (this.castShadow === true)
|
|
object.castShadow = true;
|
|
if (this.receiveShadow === true)
|
|
object.receiveShadow = true;
|
|
if (this.visible === false)
|
|
object.visible = false;
|
|
if (this.frustumCulled === false)
|
|
object.frustumCulled = false;
|
|
if (this.renderOrder !== 0)
|
|
object.renderOrder = this.renderOrder;
|
|
if (JSON.stringify(this.userData) !== "{}")
|
|
object.userData = this.userData;
|
|
object.layers = this.layers.mask;
|
|
object.matrix = this.matrix.toArray();
|
|
if (this.matrixAutoUpdate === false)
|
|
object.matrixAutoUpdate = false;
|
|
if (this.isInstancedMesh) {
|
|
object.type = "InstancedMesh";
|
|
object.count = this.count;
|
|
object.instanceMatrix = this.instanceMatrix.toJSON();
|
|
if (this.instanceColor !== null)
|
|
object.instanceColor = this.instanceColor.toJSON();
|
|
}
|
|
function serialize(library2, element) {
|
|
if (library2[element.uuid] === void 0) {
|
|
library2[element.uuid] = element.toJSON(meta);
|
|
}
|
|
return element.uuid;
|
|
}
|
|
if (this.isScene) {
|
|
if (this.background) {
|
|
if (this.background.isColor) {
|
|
object.background = this.background.toJSON();
|
|
} else if (this.background.isTexture) {
|
|
object.background = this.background.toJSON(meta).uuid;
|
|
}
|
|
}
|
|
if (this.environment && this.environment.isTexture) {
|
|
object.environment = this.environment.toJSON(meta).uuid;
|
|
}
|
|
} else if (this.isMesh || this.isLine || this.isPoints) {
|
|
object.geometry = serialize(meta.geometries, this.geometry);
|
|
const parameters = this.geometry.parameters;
|
|
if (parameters !== void 0 && parameters.shapes !== void 0) {
|
|
const shapes = parameters.shapes;
|
|
if (Array.isArray(shapes)) {
|
|
for (let i = 0, l = shapes.length; i < l; i++) {
|
|
const shape = shapes[i];
|
|
serialize(meta.shapes, shape);
|
|
}
|
|
} else {
|
|
serialize(meta.shapes, shapes);
|
|
}
|
|
}
|
|
}
|
|
if (this.isSkinnedMesh) {
|
|
object.bindMode = this.bindMode;
|
|
object.bindMatrix = this.bindMatrix.toArray();
|
|
if (this.skeleton !== void 0) {
|
|
serialize(meta.skeletons, this.skeleton);
|
|
object.skeleton = this.skeleton.uuid;
|
|
}
|
|
}
|
|
if (this.material !== void 0) {
|
|
if (Array.isArray(this.material)) {
|
|
const uuids = [];
|
|
for (let i = 0, l = this.material.length; i < l; i++) {
|
|
uuids.push(serialize(meta.materials, this.material[i]));
|
|
}
|
|
object.material = uuids;
|
|
} else {
|
|
object.material = serialize(meta.materials, this.material);
|
|
}
|
|
}
|
|
if (this.children.length > 0) {
|
|
object.children = [];
|
|
for (let i = 0; i < this.children.length; i++) {
|
|
object.children.push(this.children[i].toJSON(meta).object);
|
|
}
|
|
}
|
|
if (this.animations.length > 0) {
|
|
object.animations = [];
|
|
for (let i = 0; i < this.animations.length; i++) {
|
|
const animation = this.animations[i];
|
|
object.animations.push(serialize(meta.animations, animation));
|
|
}
|
|
}
|
|
if (isRootObject) {
|
|
const geometries = extractFromCache(meta.geometries);
|
|
const materials = extractFromCache(meta.materials);
|
|
const textures = extractFromCache(meta.textures);
|
|
const images = extractFromCache(meta.images);
|
|
const shapes = extractFromCache(meta.shapes);
|
|
const skeletons = extractFromCache(meta.skeletons);
|
|
const animations = extractFromCache(meta.animations);
|
|
if (geometries.length > 0)
|
|
output.geometries = geometries;
|
|
if (materials.length > 0)
|
|
output.materials = materials;
|
|
if (textures.length > 0)
|
|
output.textures = textures;
|
|
if (images.length > 0)
|
|
output.images = images;
|
|
if (shapes.length > 0)
|
|
output.shapes = shapes;
|
|
if (skeletons.length > 0)
|
|
output.skeletons = skeletons;
|
|
if (animations.length > 0)
|
|
output.animations = animations;
|
|
}
|
|
output.object = object;
|
|
return output;
|
|
function extractFromCache(cache) {
|
|
const values = [];
|
|
for (const key in cache) {
|
|
const data = cache[key];
|
|
delete data.metadata;
|
|
values.push(data);
|
|
}
|
|
return values;
|
|
}
|
|
}
|
|
clone(recursive) {
|
|
return new this.constructor().copy(this, recursive);
|
|
}
|
|
copy(source, recursive = true) {
|
|
this.name = source.name;
|
|
this.up.copy(source.up);
|
|
this.position.copy(source.position);
|
|
this.rotation.order = source.rotation.order;
|
|
this.quaternion.copy(source.quaternion);
|
|
this.scale.copy(source.scale);
|
|
this.matrix.copy(source.matrix);
|
|
this.matrixWorld.copy(source.matrixWorld);
|
|
this.matrixAutoUpdate = source.matrixAutoUpdate;
|
|
this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
|
|
this.layers.mask = source.layers.mask;
|
|
this.visible = source.visible;
|
|
this.castShadow = source.castShadow;
|
|
this.receiveShadow = source.receiveShadow;
|
|
this.frustumCulled = source.frustumCulled;
|
|
this.renderOrder = source.renderOrder;
|
|
this.userData = JSON.parse(JSON.stringify(source.userData));
|
|
if (recursive === true) {
|
|
for (let i = 0; i < source.children.length; i++) {
|
|
const child = source.children[i];
|
|
this.add(child.clone());
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
Object3D.DefaultUp = new Vector3(0, 1, 0);
|
|
Object3D.DefaultMatrixAutoUpdate = true;
|
|
Object3D.prototype.isObject3D = true;
|
|
var _v0$1 = /* @__PURE__ */ new Vector3();
|
|
var _v1$3 = /* @__PURE__ */ new Vector3();
|
|
var _v2$2 = /* @__PURE__ */ new Vector3();
|
|
var _v3$1 = /* @__PURE__ */ new Vector3();
|
|
var _vab = /* @__PURE__ */ new Vector3();
|
|
var _vac = /* @__PURE__ */ new Vector3();
|
|
var _vbc = /* @__PURE__ */ new Vector3();
|
|
var _vap = /* @__PURE__ */ new Vector3();
|
|
var _vbp = /* @__PURE__ */ new Vector3();
|
|
var _vcp = /* @__PURE__ */ new Vector3();
|
|
var Triangle = class {
|
|
constructor(a2 = new Vector3(), b2 = new Vector3(), c2 = new Vector3()) {
|
|
this.a = a2;
|
|
this.b = b2;
|
|
this.c = c2;
|
|
}
|
|
static getNormal(a2, b2, c2, target) {
|
|
target.subVectors(c2, b2);
|
|
_v0$1.subVectors(a2, b2);
|
|
target.cross(_v0$1);
|
|
const targetLengthSq = target.lengthSq();
|
|
if (targetLengthSq > 0) {
|
|
return target.multiplyScalar(1 / Math.sqrt(targetLengthSq));
|
|
}
|
|
return target.set(0, 0, 0);
|
|
}
|
|
static getBarycoord(point, a2, b2, c2, target) {
|
|
_v0$1.subVectors(c2, a2);
|
|
_v1$3.subVectors(b2, a2);
|
|
_v2$2.subVectors(point, a2);
|
|
const dot00 = _v0$1.dot(_v0$1);
|
|
const dot01 = _v0$1.dot(_v1$3);
|
|
const dot02 = _v0$1.dot(_v2$2);
|
|
const dot11 = _v1$3.dot(_v1$3);
|
|
const dot12 = _v1$3.dot(_v2$2);
|
|
const denom = dot00 * dot11 - dot01 * dot01;
|
|
if (denom === 0) {
|
|
return target.set(-2, -1, -1);
|
|
}
|
|
const invDenom = 1 / denom;
|
|
const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
|
const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
|
return target.set(1 - u - v, v, u);
|
|
}
|
|
static containsPoint(point, a2, b2, c2) {
|
|
this.getBarycoord(point, a2, b2, c2, _v3$1);
|
|
return _v3$1.x >= 0 && _v3$1.y >= 0 && _v3$1.x + _v3$1.y <= 1;
|
|
}
|
|
static getUV(point, p1, p2, p3, uv1, uv2, uv3, target) {
|
|
this.getBarycoord(point, p1, p2, p3, _v3$1);
|
|
target.set(0, 0);
|
|
target.addScaledVector(uv1, _v3$1.x);
|
|
target.addScaledVector(uv2, _v3$1.y);
|
|
target.addScaledVector(uv3, _v3$1.z);
|
|
return target;
|
|
}
|
|
static isFrontFacing(a2, b2, c2, direction) {
|
|
_v0$1.subVectors(c2, b2);
|
|
_v1$3.subVectors(a2, b2);
|
|
return _v0$1.cross(_v1$3).dot(direction) < 0 ? true : false;
|
|
}
|
|
set(a2, b2, c2) {
|
|
this.a.copy(a2);
|
|
this.b.copy(b2);
|
|
this.c.copy(c2);
|
|
return this;
|
|
}
|
|
setFromPointsAndIndices(points, i0, i1, i2) {
|
|
this.a.copy(points[i0]);
|
|
this.b.copy(points[i1]);
|
|
this.c.copy(points[i2]);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(triangle) {
|
|
this.a.copy(triangle.a);
|
|
this.b.copy(triangle.b);
|
|
this.c.copy(triangle.c);
|
|
return this;
|
|
}
|
|
getArea() {
|
|
_v0$1.subVectors(this.c, this.b);
|
|
_v1$3.subVectors(this.a, this.b);
|
|
return _v0$1.cross(_v1$3).length() * 0.5;
|
|
}
|
|
getMidpoint(target) {
|
|
return target.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3);
|
|
}
|
|
getNormal(target) {
|
|
return Triangle.getNormal(this.a, this.b, this.c, target);
|
|
}
|
|
getPlane(target) {
|
|
return target.setFromCoplanarPoints(this.a, this.b, this.c);
|
|
}
|
|
getBarycoord(point, target) {
|
|
return Triangle.getBarycoord(point, this.a, this.b, this.c, target);
|
|
}
|
|
getUV(point, uv1, uv2, uv3, target) {
|
|
return Triangle.getUV(point, this.a, this.b, this.c, uv1, uv2, uv3, target);
|
|
}
|
|
containsPoint(point) {
|
|
return Triangle.containsPoint(point, this.a, this.b, this.c);
|
|
}
|
|
isFrontFacing(direction) {
|
|
return Triangle.isFrontFacing(this.a, this.b, this.c, direction);
|
|
}
|
|
intersectsBox(box) {
|
|
return box.intersectsTriangle(this);
|
|
}
|
|
closestPointToPoint(p2, target) {
|
|
const a2 = this.a, b2 = this.b, c2 = this.c;
|
|
let v, w2;
|
|
_vab.subVectors(b2, a2);
|
|
_vac.subVectors(c2, a2);
|
|
_vap.subVectors(p2, a2);
|
|
const d1 = _vab.dot(_vap);
|
|
const d2 = _vac.dot(_vap);
|
|
if (d1 <= 0 && d2 <= 0) {
|
|
return target.copy(a2);
|
|
}
|
|
_vbp.subVectors(p2, b2);
|
|
const d3 = _vab.dot(_vbp);
|
|
const d4 = _vac.dot(_vbp);
|
|
if (d3 >= 0 && d4 <= d3) {
|
|
return target.copy(b2);
|
|
}
|
|
const vc2 = d1 * d4 - d3 * d2;
|
|
if (vc2 <= 0 && d1 >= 0 && d3 <= 0) {
|
|
v = d1 / (d1 - d3);
|
|
return target.copy(a2).addScaledVector(_vab, v);
|
|
}
|
|
_vcp.subVectors(p2, c2);
|
|
const d5 = _vab.dot(_vcp);
|
|
const d6 = _vac.dot(_vcp);
|
|
if (d6 >= 0 && d5 <= d6) {
|
|
return target.copy(c2);
|
|
}
|
|
const vb2 = d5 * d2 - d1 * d6;
|
|
if (vb2 <= 0 && d2 >= 0 && d6 <= 0) {
|
|
w2 = d2 / (d2 - d6);
|
|
return target.copy(a2).addScaledVector(_vac, w2);
|
|
}
|
|
const va2 = d3 * d6 - d5 * d4;
|
|
if (va2 <= 0 && d4 - d3 >= 0 && d5 - d6 >= 0) {
|
|
_vbc.subVectors(c2, b2);
|
|
w2 = (d4 - d3) / (d4 - d3 + (d5 - d6));
|
|
return target.copy(b2).addScaledVector(_vbc, w2);
|
|
}
|
|
const denom = 1 / (va2 + vb2 + vc2);
|
|
v = vb2 * denom;
|
|
w2 = vc2 * denom;
|
|
return target.copy(a2).addScaledVector(_vab, v).addScaledVector(_vac, w2);
|
|
}
|
|
equals(triangle) {
|
|
return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c);
|
|
}
|
|
};
|
|
var materialId = 0;
|
|
var Material = class extends EventDispatcher {
|
|
constructor() {
|
|
super();
|
|
Object.defineProperty(this, "id", { value: materialId++ });
|
|
this.uuid = generateUUID();
|
|
this.name = "";
|
|
this.type = "Material";
|
|
this.fog = true;
|
|
this.blending = NormalBlending;
|
|
this.side = FrontSide;
|
|
this.vertexColors = false;
|
|
this.opacity = 1;
|
|
this.format = RGBAFormat;
|
|
this.transparent = false;
|
|
this.blendSrc = SrcAlphaFactor;
|
|
this.blendDst = OneMinusSrcAlphaFactor;
|
|
this.blendEquation = AddEquation;
|
|
this.blendSrcAlpha = null;
|
|
this.blendDstAlpha = null;
|
|
this.blendEquationAlpha = null;
|
|
this.depthFunc = LessEqualDepth;
|
|
this.depthTest = true;
|
|
this.depthWrite = true;
|
|
this.stencilWriteMask = 255;
|
|
this.stencilFunc = AlwaysStencilFunc;
|
|
this.stencilRef = 0;
|
|
this.stencilFuncMask = 255;
|
|
this.stencilFail = KeepStencilOp;
|
|
this.stencilZFail = KeepStencilOp;
|
|
this.stencilZPass = KeepStencilOp;
|
|
this.stencilWrite = false;
|
|
this.clippingPlanes = null;
|
|
this.clipIntersection = false;
|
|
this.clipShadows = false;
|
|
this.shadowSide = null;
|
|
this.colorWrite = true;
|
|
this.precision = null;
|
|
this.polygonOffset = false;
|
|
this.polygonOffsetFactor = 0;
|
|
this.polygonOffsetUnits = 0;
|
|
this.dithering = false;
|
|
this.alphaToCoverage = false;
|
|
this.premultipliedAlpha = false;
|
|
this.visible = true;
|
|
this.toneMapped = true;
|
|
this.userData = {};
|
|
this.version = 0;
|
|
this._alphaTest = 0;
|
|
}
|
|
get alphaTest() {
|
|
return this._alphaTest;
|
|
}
|
|
set alphaTest(value) {
|
|
if (this._alphaTest > 0 !== value > 0) {
|
|
this.version++;
|
|
}
|
|
this._alphaTest = value;
|
|
}
|
|
onBuild() {
|
|
}
|
|
onBeforeCompile() {
|
|
}
|
|
customProgramCacheKey() {
|
|
return this.onBeforeCompile.toString();
|
|
}
|
|
setValues(values) {
|
|
if (values === void 0)
|
|
return;
|
|
for (const key in values) {
|
|
const newValue = values[key];
|
|
if (newValue === void 0) {
|
|
console.warn("THREE.Material: '" + key + "' parameter is undefined.");
|
|
continue;
|
|
}
|
|
if (key === "shading") {
|
|
console.warn("THREE." + this.type + ": .shading has been removed. Use the boolean .flatShading instead.");
|
|
this.flatShading = newValue === FlatShading ? true : false;
|
|
continue;
|
|
}
|
|
const currentValue = this[key];
|
|
if (currentValue === void 0) {
|
|
console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material.");
|
|
continue;
|
|
}
|
|
if (currentValue && currentValue.isColor) {
|
|
currentValue.set(newValue);
|
|
} else if (currentValue && currentValue.isVector3 && (newValue && newValue.isVector3)) {
|
|
currentValue.copy(newValue);
|
|
} else {
|
|
this[key] = newValue;
|
|
}
|
|
}
|
|
}
|
|
toJSON(meta) {
|
|
const isRoot = meta === void 0 || typeof meta === "string";
|
|
if (isRoot) {
|
|
meta = {
|
|
textures: {},
|
|
images: {}
|
|
};
|
|
}
|
|
const data = {
|
|
metadata: {
|
|
version: 4.5,
|
|
type: "Material",
|
|
generator: "Material.toJSON"
|
|
}
|
|
};
|
|
data.uuid = this.uuid;
|
|
data.type = this.type;
|
|
if (this.name !== "")
|
|
data.name = this.name;
|
|
if (this.color && this.color.isColor)
|
|
data.color = this.color.getHex();
|
|
if (this.roughness !== void 0)
|
|
data.roughness = this.roughness;
|
|
if (this.metalness !== void 0)
|
|
data.metalness = this.metalness;
|
|
if (this.sheenTint && this.sheenTint.isColor)
|
|
data.sheenTint = this.sheenTint.getHex();
|
|
if (this.emissive && this.emissive.isColor)
|
|
data.emissive = this.emissive.getHex();
|
|
if (this.emissiveIntensity && this.emissiveIntensity !== 1)
|
|
data.emissiveIntensity = this.emissiveIntensity;
|
|
if (this.specular && this.specular.isColor)
|
|
data.specular = this.specular.getHex();
|
|
if (this.specularIntensity !== void 0)
|
|
data.specularIntensity = this.specularIntensity;
|
|
if (this.specularTint && this.specularTint.isColor)
|
|
data.specularTint = this.specularTint.getHex();
|
|
if (this.shininess !== void 0)
|
|
data.shininess = this.shininess;
|
|
if (this.clearcoat !== void 0)
|
|
data.clearcoat = this.clearcoat;
|
|
if (this.clearcoatRoughness !== void 0)
|
|
data.clearcoatRoughness = this.clearcoatRoughness;
|
|
if (this.clearcoatMap && this.clearcoatMap.isTexture) {
|
|
data.clearcoatMap = this.clearcoatMap.toJSON(meta).uuid;
|
|
}
|
|
if (this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture) {
|
|
data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON(meta).uuid;
|
|
}
|
|
if (this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture) {
|
|
data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON(meta).uuid;
|
|
data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
|
|
}
|
|
if (this.map && this.map.isTexture)
|
|
data.map = this.map.toJSON(meta).uuid;
|
|
if (this.matcap && this.matcap.isTexture)
|
|
data.matcap = this.matcap.toJSON(meta).uuid;
|
|
if (this.alphaMap && this.alphaMap.isTexture)
|
|
data.alphaMap = this.alphaMap.toJSON(meta).uuid;
|
|
if (this.lightMap && this.lightMap.isTexture) {
|
|
data.lightMap = this.lightMap.toJSON(meta).uuid;
|
|
data.lightMapIntensity = this.lightMapIntensity;
|
|
}
|
|
if (this.aoMap && this.aoMap.isTexture) {
|
|
data.aoMap = this.aoMap.toJSON(meta).uuid;
|
|
data.aoMapIntensity = this.aoMapIntensity;
|
|
}
|
|
if (this.bumpMap && this.bumpMap.isTexture) {
|
|
data.bumpMap = this.bumpMap.toJSON(meta).uuid;
|
|
data.bumpScale = this.bumpScale;
|
|
}
|
|
if (this.normalMap && this.normalMap.isTexture) {
|
|
data.normalMap = this.normalMap.toJSON(meta).uuid;
|
|
data.normalMapType = this.normalMapType;
|
|
data.normalScale = this.normalScale.toArray();
|
|
}
|
|
if (this.displacementMap && this.displacementMap.isTexture) {
|
|
data.displacementMap = this.displacementMap.toJSON(meta).uuid;
|
|
data.displacementScale = this.displacementScale;
|
|
data.displacementBias = this.displacementBias;
|
|
}
|
|
if (this.roughnessMap && this.roughnessMap.isTexture)
|
|
data.roughnessMap = this.roughnessMap.toJSON(meta).uuid;
|
|
if (this.metalnessMap && this.metalnessMap.isTexture)
|
|
data.metalnessMap = this.metalnessMap.toJSON(meta).uuid;
|
|
if (this.emissiveMap && this.emissiveMap.isTexture)
|
|
data.emissiveMap = this.emissiveMap.toJSON(meta).uuid;
|
|
if (this.specularMap && this.specularMap.isTexture)
|
|
data.specularMap = this.specularMap.toJSON(meta).uuid;
|
|
if (this.specularIntensityMap && this.specularIntensityMap.isTexture)
|
|
data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid;
|
|
if (this.specularTintMap && this.specularTintMap.isTexture)
|
|
data.specularTintMap = this.specularTintMap.toJSON(meta).uuid;
|
|
if (this.envMap && this.envMap.isTexture) {
|
|
data.envMap = this.envMap.toJSON(meta).uuid;
|
|
if (this.combine !== void 0)
|
|
data.combine = this.combine;
|
|
}
|
|
if (this.envMapIntensity !== void 0)
|
|
data.envMapIntensity = this.envMapIntensity;
|
|
if (this.reflectivity !== void 0)
|
|
data.reflectivity = this.reflectivity;
|
|
if (this.refractionRatio !== void 0)
|
|
data.refractionRatio = this.refractionRatio;
|
|
if (this.gradientMap && this.gradientMap.isTexture) {
|
|
data.gradientMap = this.gradientMap.toJSON(meta).uuid;
|
|
}
|
|
if (this.transmission !== void 0)
|
|
data.transmission = this.transmission;
|
|
if (this.transmissionMap && this.transmissionMap.isTexture)
|
|
data.transmissionMap = this.transmissionMap.toJSON(meta).uuid;
|
|
if (this.thickness !== void 0)
|
|
data.thickness = this.thickness;
|
|
if (this.thicknessMap && this.thicknessMap.isTexture)
|
|
data.thicknessMap = this.thicknessMap.toJSON(meta).uuid;
|
|
if (this.attenuationDistance !== void 0)
|
|
data.attenuationDistance = this.attenuationDistance;
|
|
if (this.attenuationTint !== void 0)
|
|
data.attenuationTint = this.attenuationTint.getHex();
|
|
if (this.size !== void 0)
|
|
data.size = this.size;
|
|
if (this.shadowSide !== null)
|
|
data.shadowSide = this.shadowSide;
|
|
if (this.sizeAttenuation !== void 0)
|
|
data.sizeAttenuation = this.sizeAttenuation;
|
|
if (this.blending !== NormalBlending)
|
|
data.blending = this.blending;
|
|
if (this.side !== FrontSide)
|
|
data.side = this.side;
|
|
if (this.vertexColors)
|
|
data.vertexColors = true;
|
|
if (this.opacity < 1)
|
|
data.opacity = this.opacity;
|
|
if (this.format !== RGBAFormat)
|
|
data.format = this.format;
|
|
if (this.transparent === true)
|
|
data.transparent = this.transparent;
|
|
data.depthFunc = this.depthFunc;
|
|
data.depthTest = this.depthTest;
|
|
data.depthWrite = this.depthWrite;
|
|
data.colorWrite = this.colorWrite;
|
|
data.stencilWrite = this.stencilWrite;
|
|
data.stencilWriteMask = this.stencilWriteMask;
|
|
data.stencilFunc = this.stencilFunc;
|
|
data.stencilRef = this.stencilRef;
|
|
data.stencilFuncMask = this.stencilFuncMask;
|
|
data.stencilFail = this.stencilFail;
|
|
data.stencilZFail = this.stencilZFail;
|
|
data.stencilZPass = this.stencilZPass;
|
|
if (this.rotation && this.rotation !== 0)
|
|
data.rotation = this.rotation;
|
|
if (this.polygonOffset === true)
|
|
data.polygonOffset = true;
|
|
if (this.polygonOffsetFactor !== 0)
|
|
data.polygonOffsetFactor = this.polygonOffsetFactor;
|
|
if (this.polygonOffsetUnits !== 0)
|
|
data.polygonOffsetUnits = this.polygonOffsetUnits;
|
|
if (this.linewidth && this.linewidth !== 1)
|
|
data.linewidth = this.linewidth;
|
|
if (this.dashSize !== void 0)
|
|
data.dashSize = this.dashSize;
|
|
if (this.gapSize !== void 0)
|
|
data.gapSize = this.gapSize;
|
|
if (this.scale !== void 0)
|
|
data.scale = this.scale;
|
|
if (this.dithering === true)
|
|
data.dithering = true;
|
|
if (this.alphaTest > 0)
|
|
data.alphaTest = this.alphaTest;
|
|
if (this.alphaToCoverage === true)
|
|
data.alphaToCoverage = this.alphaToCoverage;
|
|
if (this.premultipliedAlpha === true)
|
|
data.premultipliedAlpha = this.premultipliedAlpha;
|
|
if (this.wireframe === true)
|
|
data.wireframe = this.wireframe;
|
|
if (this.wireframeLinewidth > 1)
|
|
data.wireframeLinewidth = this.wireframeLinewidth;
|
|
if (this.wireframeLinecap !== "round")
|
|
data.wireframeLinecap = this.wireframeLinecap;
|
|
if (this.wireframeLinejoin !== "round")
|
|
data.wireframeLinejoin = this.wireframeLinejoin;
|
|
if (this.flatShading === true)
|
|
data.flatShading = this.flatShading;
|
|
if (this.visible === false)
|
|
data.visible = false;
|
|
if (this.toneMapped === false)
|
|
data.toneMapped = false;
|
|
if (JSON.stringify(this.userData) !== "{}")
|
|
data.userData = this.userData;
|
|
function extractFromCache(cache) {
|
|
const values = [];
|
|
for (const key in cache) {
|
|
const data2 = cache[key];
|
|
delete data2.metadata;
|
|
values.push(data2);
|
|
}
|
|
return values;
|
|
}
|
|
if (isRoot) {
|
|
const textures = extractFromCache(meta.textures);
|
|
const images = extractFromCache(meta.images);
|
|
if (textures.length > 0)
|
|
data.textures = textures;
|
|
if (images.length > 0)
|
|
data.images = images;
|
|
}
|
|
return data;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(source) {
|
|
this.name = source.name;
|
|
this.fog = source.fog;
|
|
this.blending = source.blending;
|
|
this.side = source.side;
|
|
this.vertexColors = source.vertexColors;
|
|
this.opacity = source.opacity;
|
|
this.format = source.format;
|
|
this.transparent = source.transparent;
|
|
this.blendSrc = source.blendSrc;
|
|
this.blendDst = source.blendDst;
|
|
this.blendEquation = source.blendEquation;
|
|
this.blendSrcAlpha = source.blendSrcAlpha;
|
|
this.blendDstAlpha = source.blendDstAlpha;
|
|
this.blendEquationAlpha = source.blendEquationAlpha;
|
|
this.depthFunc = source.depthFunc;
|
|
this.depthTest = source.depthTest;
|
|
this.depthWrite = source.depthWrite;
|
|
this.stencilWriteMask = source.stencilWriteMask;
|
|
this.stencilFunc = source.stencilFunc;
|
|
this.stencilRef = source.stencilRef;
|
|
this.stencilFuncMask = source.stencilFuncMask;
|
|
this.stencilFail = source.stencilFail;
|
|
this.stencilZFail = source.stencilZFail;
|
|
this.stencilZPass = source.stencilZPass;
|
|
this.stencilWrite = source.stencilWrite;
|
|
const srcPlanes = source.clippingPlanes;
|
|
let dstPlanes = null;
|
|
if (srcPlanes !== null) {
|
|
const n = srcPlanes.length;
|
|
dstPlanes = new Array(n);
|
|
for (let i = 0; i !== n; ++i) {
|
|
dstPlanes[i] = srcPlanes[i].clone();
|
|
}
|
|
}
|
|
this.clippingPlanes = dstPlanes;
|
|
this.clipIntersection = source.clipIntersection;
|
|
this.clipShadows = source.clipShadows;
|
|
this.shadowSide = source.shadowSide;
|
|
this.colorWrite = source.colorWrite;
|
|
this.precision = source.precision;
|
|
this.polygonOffset = source.polygonOffset;
|
|
this.polygonOffsetFactor = source.polygonOffsetFactor;
|
|
this.polygonOffsetUnits = source.polygonOffsetUnits;
|
|
this.dithering = source.dithering;
|
|
this.alphaTest = source.alphaTest;
|
|
this.alphaToCoverage = source.alphaToCoverage;
|
|
this.premultipliedAlpha = source.premultipliedAlpha;
|
|
this.visible = source.visible;
|
|
this.toneMapped = source.toneMapped;
|
|
this.userData = JSON.parse(JSON.stringify(source.userData));
|
|
return this;
|
|
}
|
|
dispose() {
|
|
this.dispatchEvent({ type: "dispose" });
|
|
}
|
|
set needsUpdate(value) {
|
|
if (value === true)
|
|
this.version++;
|
|
}
|
|
};
|
|
Material.prototype.isMaterial = true;
|
|
var _colorKeywords = {
|
|
"aliceblue": 15792383,
|
|
"antiquewhite": 16444375,
|
|
"aqua": 65535,
|
|
"aquamarine": 8388564,
|
|
"azure": 15794175,
|
|
"beige": 16119260,
|
|
"bisque": 16770244,
|
|
"black": 0,
|
|
"blanchedalmond": 16772045,
|
|
"blue": 255,
|
|
"blueviolet": 9055202,
|
|
"brown": 10824234,
|
|
"burlywood": 14596231,
|
|
"cadetblue": 6266528,
|
|
"chartreuse": 8388352,
|
|
"chocolate": 13789470,
|
|
"coral": 16744272,
|
|
"cornflowerblue": 6591981,
|
|
"cornsilk": 16775388,
|
|
"crimson": 14423100,
|
|
"cyan": 65535,
|
|
"darkblue": 139,
|
|
"darkcyan": 35723,
|
|
"darkgoldenrod": 12092939,
|
|
"darkgray": 11119017,
|
|
"darkgreen": 25600,
|
|
"darkgrey": 11119017,
|
|
"darkkhaki": 12433259,
|
|
"darkmagenta": 9109643,
|
|
"darkolivegreen": 5597999,
|
|
"darkorange": 16747520,
|
|
"darkorchid": 10040012,
|
|
"darkred": 9109504,
|
|
"darksalmon": 15308410,
|
|
"darkseagreen": 9419919,
|
|
"darkslateblue": 4734347,
|
|
"darkslategray": 3100495,
|
|
"darkslategrey": 3100495,
|
|
"darkturquoise": 52945,
|
|
"darkviolet": 9699539,
|
|
"deeppink": 16716947,
|
|
"deepskyblue": 49151,
|
|
"dimgray": 6908265,
|
|
"dimgrey": 6908265,
|
|
"dodgerblue": 2003199,
|
|
"firebrick": 11674146,
|
|
"floralwhite": 16775920,
|
|
"forestgreen": 2263842,
|
|
"fuchsia": 16711935,
|
|
"gainsboro": 14474460,
|
|
"ghostwhite": 16316671,
|
|
"gold": 16766720,
|
|
"goldenrod": 14329120,
|
|
"gray": 8421504,
|
|
"green": 32768,
|
|
"greenyellow": 11403055,
|
|
"grey": 8421504,
|
|
"honeydew": 15794160,
|
|
"hotpink": 16738740,
|
|
"indianred": 13458524,
|
|
"indigo": 4915330,
|
|
"ivory": 16777200,
|
|
"khaki": 15787660,
|
|
"lavender": 15132410,
|
|
"lavenderblush": 16773365,
|
|
"lawngreen": 8190976,
|
|
"lemonchiffon": 16775885,
|
|
"lightblue": 11393254,
|
|
"lightcoral": 15761536,
|
|
"lightcyan": 14745599,
|
|
"lightgoldenrodyellow": 16448210,
|
|
"lightgray": 13882323,
|
|
"lightgreen": 9498256,
|
|
"lightgrey": 13882323,
|
|
"lightpink": 16758465,
|
|
"lightsalmon": 16752762,
|
|
"lightseagreen": 2142890,
|
|
"lightskyblue": 8900346,
|
|
"lightslategray": 7833753,
|
|
"lightslategrey": 7833753,
|
|
"lightsteelblue": 11584734,
|
|
"lightyellow": 16777184,
|
|
"lime": 65280,
|
|
"limegreen": 3329330,
|
|
"linen": 16445670,
|
|
"magenta": 16711935,
|
|
"maroon": 8388608,
|
|
"mediumaquamarine": 6737322,
|
|
"mediumblue": 205,
|
|
"mediumorchid": 12211667,
|
|
"mediumpurple": 9662683,
|
|
"mediumseagreen": 3978097,
|
|
"mediumslateblue": 8087790,
|
|
"mediumspringgreen": 64154,
|
|
"mediumturquoise": 4772300,
|
|
"mediumvioletred": 13047173,
|
|
"midnightblue": 1644912,
|
|
"mintcream": 16121850,
|
|
"mistyrose": 16770273,
|
|
"moccasin": 16770229,
|
|
"navajowhite": 16768685,
|
|
"navy": 128,
|
|
"oldlace": 16643558,
|
|
"olive": 8421376,
|
|
"olivedrab": 7048739,
|
|
"orange": 16753920,
|
|
"orangered": 16729344,
|
|
"orchid": 14315734,
|
|
"palegoldenrod": 15657130,
|
|
"palegreen": 10025880,
|
|
"paleturquoise": 11529966,
|
|
"palevioletred": 14381203,
|
|
"papayawhip": 16773077,
|
|
"peachpuff": 16767673,
|
|
"peru": 13468991,
|
|
"pink": 16761035,
|
|
"plum": 14524637,
|
|
"powderblue": 11591910,
|
|
"purple": 8388736,
|
|
"rebeccapurple": 6697881,
|
|
"red": 16711680,
|
|
"rosybrown": 12357519,
|
|
"royalblue": 4286945,
|
|
"saddlebrown": 9127187,
|
|
"salmon": 16416882,
|
|
"sandybrown": 16032864,
|
|
"seagreen": 3050327,
|
|
"seashell": 16774638,
|
|
"sienna": 10506797,
|
|
"silver": 12632256,
|
|
"skyblue": 8900331,
|
|
"slateblue": 6970061,
|
|
"slategray": 7372944,
|
|
"slategrey": 7372944,
|
|
"snow": 16775930,
|
|
"springgreen": 65407,
|
|
"steelblue": 4620980,
|
|
"tan": 13808780,
|
|
"teal": 32896,
|
|
"thistle": 14204888,
|
|
"tomato": 16737095,
|
|
"turquoise": 4251856,
|
|
"violet": 15631086,
|
|
"wheat": 16113331,
|
|
"white": 16777215,
|
|
"whitesmoke": 16119285,
|
|
"yellow": 16776960,
|
|
"yellowgreen": 10145074
|
|
};
|
|
var _hslA = { h: 0, s: 0, l: 0 };
|
|
var _hslB = { h: 0, s: 0, l: 0 };
|
|
function hue2rgb(p2, q, t) {
|
|
if (t < 0)
|
|
t += 1;
|
|
if (t > 1)
|
|
t -= 1;
|
|
if (t < 1 / 6)
|
|
return p2 + (q - p2) * 6 * t;
|
|
if (t < 1 / 2)
|
|
return q;
|
|
if (t < 2 / 3)
|
|
return p2 + (q - p2) * 6 * (2 / 3 - t);
|
|
return p2;
|
|
}
|
|
function SRGBToLinear(c2) {
|
|
return c2 < 0.04045 ? c2 * 0.0773993808 : Math.pow(c2 * 0.9478672986 + 0.0521327014, 2.4);
|
|
}
|
|
function LinearToSRGB(c2) {
|
|
return c2 < 31308e-7 ? c2 * 12.92 : 1.055 * Math.pow(c2, 0.41666) - 0.055;
|
|
}
|
|
var Color = class {
|
|
constructor(r, g, b2) {
|
|
if (g === void 0 && b2 === void 0) {
|
|
return this.set(r);
|
|
}
|
|
return this.setRGB(r, g, b2);
|
|
}
|
|
set(value) {
|
|
if (value && value.isColor) {
|
|
this.copy(value);
|
|
} else if (typeof value === "number") {
|
|
this.setHex(value);
|
|
} else if (typeof value === "string") {
|
|
this.setStyle(value);
|
|
}
|
|
return this;
|
|
}
|
|
setScalar(scalar) {
|
|
this.r = scalar;
|
|
this.g = scalar;
|
|
this.b = scalar;
|
|
return this;
|
|
}
|
|
setHex(hex) {
|
|
hex = Math.floor(hex);
|
|
this.r = (hex >> 16 & 255) / 255;
|
|
this.g = (hex >> 8 & 255) / 255;
|
|
this.b = (hex & 255) / 255;
|
|
return this;
|
|
}
|
|
setRGB(r, g, b2) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b2;
|
|
return this;
|
|
}
|
|
setHSL(h, s, l) {
|
|
h = euclideanModulo(h, 1);
|
|
s = clamp(s, 0, 1);
|
|
l = clamp(l, 0, 1);
|
|
if (s === 0) {
|
|
this.r = this.g = this.b = l;
|
|
} else {
|
|
const p2 = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
const q = 2 * l - p2;
|
|
this.r = hue2rgb(q, p2, h + 1 / 3);
|
|
this.g = hue2rgb(q, p2, h);
|
|
this.b = hue2rgb(q, p2, h - 1 / 3);
|
|
}
|
|
return this;
|
|
}
|
|
setStyle(style) {
|
|
function handleAlpha(string) {
|
|
if (string === void 0)
|
|
return;
|
|
if (parseFloat(string) < 1) {
|
|
console.warn("THREE.Color: Alpha component of " + style + " will be ignored.");
|
|
}
|
|
}
|
|
let m;
|
|
if (m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) {
|
|
let color;
|
|
const name = m[1];
|
|
const components = m[2];
|
|
switch (name) {
|
|
case "rgb":
|
|
case "rgba":
|
|
if (color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
|
|
this.r = Math.min(255, parseInt(color[1], 10)) / 255;
|
|
this.g = Math.min(255, parseInt(color[2], 10)) / 255;
|
|
this.b = Math.min(255, parseInt(color[3], 10)) / 255;
|
|
handleAlpha(color[4]);
|
|
return this;
|
|
}
|
|
if (color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
|
|
this.r = Math.min(100, parseInt(color[1], 10)) / 100;
|
|
this.g = Math.min(100, parseInt(color[2], 10)) / 100;
|
|
this.b = Math.min(100, parseInt(color[3], 10)) / 100;
|
|
handleAlpha(color[4]);
|
|
return this;
|
|
}
|
|
break;
|
|
case "hsl":
|
|
case "hsla":
|
|
if (color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
|
|
const h = parseFloat(color[1]) / 360;
|
|
const s = parseInt(color[2], 10) / 100;
|
|
const l = parseInt(color[3], 10) / 100;
|
|
handleAlpha(color[4]);
|
|
return this.setHSL(h, s, l);
|
|
}
|
|
break;
|
|
}
|
|
} else if (m = /^\#([A-Fa-f\d]+)$/.exec(style)) {
|
|
const hex = m[1];
|
|
const size = hex.length;
|
|
if (size === 3) {
|
|
this.r = parseInt(hex.charAt(0) + hex.charAt(0), 16) / 255;
|
|
this.g = parseInt(hex.charAt(1) + hex.charAt(1), 16) / 255;
|
|
this.b = parseInt(hex.charAt(2) + hex.charAt(2), 16) / 255;
|
|
return this;
|
|
} else if (size === 6) {
|
|
this.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255;
|
|
this.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255;
|
|
this.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255;
|
|
return this;
|
|
}
|
|
}
|
|
if (style && style.length > 0) {
|
|
return this.setColorName(style);
|
|
}
|
|
return this;
|
|
}
|
|
setColorName(style) {
|
|
const hex = _colorKeywords[style.toLowerCase()];
|
|
if (hex !== void 0) {
|
|
this.setHex(hex);
|
|
} else {
|
|
console.warn("THREE.Color: Unknown color " + style);
|
|
}
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.r, this.g, this.b);
|
|
}
|
|
copy(color) {
|
|
this.r = color.r;
|
|
this.g = color.g;
|
|
this.b = color.b;
|
|
return this;
|
|
}
|
|
copyGammaToLinear(color, gammaFactor = 2) {
|
|
this.r = Math.pow(color.r, gammaFactor);
|
|
this.g = Math.pow(color.g, gammaFactor);
|
|
this.b = Math.pow(color.b, gammaFactor);
|
|
return this;
|
|
}
|
|
copyLinearToGamma(color, gammaFactor = 2) {
|
|
const safeInverse = gammaFactor > 0 ? 1 / gammaFactor : 1;
|
|
this.r = Math.pow(color.r, safeInverse);
|
|
this.g = Math.pow(color.g, safeInverse);
|
|
this.b = Math.pow(color.b, safeInverse);
|
|
return this;
|
|
}
|
|
convertGammaToLinear(gammaFactor) {
|
|
this.copyGammaToLinear(this, gammaFactor);
|
|
return this;
|
|
}
|
|
convertLinearToGamma(gammaFactor) {
|
|
this.copyLinearToGamma(this, gammaFactor);
|
|
return this;
|
|
}
|
|
copySRGBToLinear(color) {
|
|
this.r = SRGBToLinear(color.r);
|
|
this.g = SRGBToLinear(color.g);
|
|
this.b = SRGBToLinear(color.b);
|
|
return this;
|
|
}
|
|
copyLinearToSRGB(color) {
|
|
this.r = LinearToSRGB(color.r);
|
|
this.g = LinearToSRGB(color.g);
|
|
this.b = LinearToSRGB(color.b);
|
|
return this;
|
|
}
|
|
convertSRGBToLinear() {
|
|
this.copySRGBToLinear(this);
|
|
return this;
|
|
}
|
|
convertLinearToSRGB() {
|
|
this.copyLinearToSRGB(this);
|
|
return this;
|
|
}
|
|
getHex() {
|
|
return this.r * 255 << 16 ^ this.g * 255 << 8 ^ this.b * 255 << 0;
|
|
}
|
|
getHexString() {
|
|
return ("000000" + this.getHex().toString(16)).slice(-6);
|
|
}
|
|
getHSL(target) {
|
|
const r = this.r, g = this.g, b2 = this.b;
|
|
const max = Math.max(r, g, b2);
|
|
const min = Math.min(r, g, b2);
|
|
let hue, saturation;
|
|
const lightness = (min + max) / 2;
|
|
if (min === max) {
|
|
hue = 0;
|
|
saturation = 0;
|
|
} else {
|
|
const delta = max - min;
|
|
saturation = lightness <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
|
|
switch (max) {
|
|
case r:
|
|
hue = (g - b2) / delta + (g < b2 ? 6 : 0);
|
|
break;
|
|
case g:
|
|
hue = (b2 - r) / delta + 2;
|
|
break;
|
|
case b2:
|
|
hue = (r - g) / delta + 4;
|
|
break;
|
|
}
|
|
hue /= 6;
|
|
}
|
|
target.h = hue;
|
|
target.s = saturation;
|
|
target.l = lightness;
|
|
return target;
|
|
}
|
|
getStyle() {
|
|
return "rgb(" + (this.r * 255 | 0) + "," + (this.g * 255 | 0) + "," + (this.b * 255 | 0) + ")";
|
|
}
|
|
offsetHSL(h, s, l) {
|
|
this.getHSL(_hslA);
|
|
_hslA.h += h;
|
|
_hslA.s += s;
|
|
_hslA.l += l;
|
|
this.setHSL(_hslA.h, _hslA.s, _hslA.l);
|
|
return this;
|
|
}
|
|
add(color) {
|
|
this.r += color.r;
|
|
this.g += color.g;
|
|
this.b += color.b;
|
|
return this;
|
|
}
|
|
addColors(color1, color2) {
|
|
this.r = color1.r + color2.r;
|
|
this.g = color1.g + color2.g;
|
|
this.b = color1.b + color2.b;
|
|
return this;
|
|
}
|
|
addScalar(s) {
|
|
this.r += s;
|
|
this.g += s;
|
|
this.b += s;
|
|
return this;
|
|
}
|
|
sub(color) {
|
|
this.r = Math.max(0, this.r - color.r);
|
|
this.g = Math.max(0, this.g - color.g);
|
|
this.b = Math.max(0, this.b - color.b);
|
|
return this;
|
|
}
|
|
multiply(color) {
|
|
this.r *= color.r;
|
|
this.g *= color.g;
|
|
this.b *= color.b;
|
|
return this;
|
|
}
|
|
multiplyScalar(s) {
|
|
this.r *= s;
|
|
this.g *= s;
|
|
this.b *= s;
|
|
return this;
|
|
}
|
|
lerp(color, alpha) {
|
|
this.r += (color.r - this.r) * alpha;
|
|
this.g += (color.g - this.g) * alpha;
|
|
this.b += (color.b - this.b) * alpha;
|
|
return this;
|
|
}
|
|
lerpColors(color1, color2, alpha) {
|
|
this.r = color1.r + (color2.r - color1.r) * alpha;
|
|
this.g = color1.g + (color2.g - color1.g) * alpha;
|
|
this.b = color1.b + (color2.b - color1.b) * alpha;
|
|
return this;
|
|
}
|
|
lerpHSL(color, alpha) {
|
|
this.getHSL(_hslA);
|
|
color.getHSL(_hslB);
|
|
const h = lerp(_hslA.h, _hslB.h, alpha);
|
|
const s = lerp(_hslA.s, _hslB.s, alpha);
|
|
const l = lerp(_hslA.l, _hslB.l, alpha);
|
|
this.setHSL(h, s, l);
|
|
return this;
|
|
}
|
|
equals(c2) {
|
|
return c2.r === this.r && c2.g === this.g && c2.b === this.b;
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
this.r = array[offset];
|
|
this.g = array[offset + 1];
|
|
this.b = array[offset + 2];
|
|
return this;
|
|
}
|
|
toArray(array = [], offset = 0) {
|
|
array[offset] = this.r;
|
|
array[offset + 1] = this.g;
|
|
array[offset + 2] = this.b;
|
|
return array;
|
|
}
|
|
fromBufferAttribute(attribute, index) {
|
|
this.r = attribute.getX(index);
|
|
this.g = attribute.getY(index);
|
|
this.b = attribute.getZ(index);
|
|
if (attribute.normalized === true) {
|
|
this.r /= 255;
|
|
this.g /= 255;
|
|
this.b /= 255;
|
|
}
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
return this.getHex();
|
|
}
|
|
};
|
|
Color.NAMES = _colorKeywords;
|
|
Color.prototype.isColor = true;
|
|
Color.prototype.r = 1;
|
|
Color.prototype.g = 1;
|
|
Color.prototype.b = 1;
|
|
var MeshBasicMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshBasicMaterial";
|
|
this.color = new Color(16777215);
|
|
this.map = null;
|
|
this.lightMap = null;
|
|
this.lightMapIntensity = 1;
|
|
this.aoMap = null;
|
|
this.aoMapIntensity = 1;
|
|
this.specularMap = null;
|
|
this.alphaMap = null;
|
|
this.envMap = null;
|
|
this.combine = MultiplyOperation;
|
|
this.reflectivity = 1;
|
|
this.refractionRatio = 0.98;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.wireframeLinecap = "round";
|
|
this.wireframeLinejoin = "round";
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.map = source.map;
|
|
this.lightMap = source.lightMap;
|
|
this.lightMapIntensity = source.lightMapIntensity;
|
|
this.aoMap = source.aoMap;
|
|
this.aoMapIntensity = source.aoMapIntensity;
|
|
this.specularMap = source.specularMap;
|
|
this.alphaMap = source.alphaMap;
|
|
this.envMap = source.envMap;
|
|
this.combine = source.combine;
|
|
this.reflectivity = source.reflectivity;
|
|
this.refractionRatio = source.refractionRatio;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.wireframeLinecap = source.wireframeLinecap;
|
|
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
return this;
|
|
}
|
|
};
|
|
MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
|
|
var _vector$9 = /* @__PURE__ */ new Vector3();
|
|
var _vector2$1 = /* @__PURE__ */ new Vector2();
|
|
var BufferAttribute = class {
|
|
constructor(array, itemSize, normalized) {
|
|
if (Array.isArray(array)) {
|
|
throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");
|
|
}
|
|
this.name = "";
|
|
this.array = array;
|
|
this.itemSize = itemSize;
|
|
this.count = array !== void 0 ? array.length / itemSize : 0;
|
|
this.normalized = normalized === true;
|
|
this.usage = StaticDrawUsage;
|
|
this.updateRange = { offset: 0, count: -1 };
|
|
this.version = 0;
|
|
}
|
|
onUploadCallback() {
|
|
}
|
|
set needsUpdate(value) {
|
|
if (value === true)
|
|
this.version++;
|
|
}
|
|
setUsage(value) {
|
|
this.usage = value;
|
|
return this;
|
|
}
|
|
copy(source) {
|
|
this.name = source.name;
|
|
this.array = new source.array.constructor(source.array);
|
|
this.itemSize = source.itemSize;
|
|
this.count = source.count;
|
|
this.normalized = source.normalized;
|
|
this.usage = source.usage;
|
|
return this;
|
|
}
|
|
copyAt(index1, attribute, index2) {
|
|
index1 *= this.itemSize;
|
|
index2 *= attribute.itemSize;
|
|
for (let i = 0, l = this.itemSize; i < l; i++) {
|
|
this.array[index1 + i] = attribute.array[index2 + i];
|
|
}
|
|
return this;
|
|
}
|
|
copyArray(array) {
|
|
this.array.set(array);
|
|
return this;
|
|
}
|
|
copyColorsArray(colors) {
|
|
const array = this.array;
|
|
let offset = 0;
|
|
for (let i = 0, l = colors.length; i < l; i++) {
|
|
let color = colors[i];
|
|
if (color === void 0) {
|
|
console.warn("THREE.BufferAttribute.copyColorsArray(): color is undefined", i);
|
|
color = new Color();
|
|
}
|
|
array[offset++] = color.r;
|
|
array[offset++] = color.g;
|
|
array[offset++] = color.b;
|
|
}
|
|
return this;
|
|
}
|
|
copyVector2sArray(vectors) {
|
|
const array = this.array;
|
|
let offset = 0;
|
|
for (let i = 0, l = vectors.length; i < l; i++) {
|
|
let vector = vectors[i];
|
|
if (vector === void 0) {
|
|
console.warn("THREE.BufferAttribute.copyVector2sArray(): vector is undefined", i);
|
|
vector = new Vector2();
|
|
}
|
|
array[offset++] = vector.x;
|
|
array[offset++] = vector.y;
|
|
}
|
|
return this;
|
|
}
|
|
copyVector3sArray(vectors) {
|
|
const array = this.array;
|
|
let offset = 0;
|
|
for (let i = 0, l = vectors.length; i < l; i++) {
|
|
let vector = vectors[i];
|
|
if (vector === void 0) {
|
|
console.warn("THREE.BufferAttribute.copyVector3sArray(): vector is undefined", i);
|
|
vector = new Vector3();
|
|
}
|
|
array[offset++] = vector.x;
|
|
array[offset++] = vector.y;
|
|
array[offset++] = vector.z;
|
|
}
|
|
return this;
|
|
}
|
|
copyVector4sArray(vectors) {
|
|
const array = this.array;
|
|
let offset = 0;
|
|
for (let i = 0, l = vectors.length; i < l; i++) {
|
|
let vector = vectors[i];
|
|
if (vector === void 0) {
|
|
console.warn("THREE.BufferAttribute.copyVector4sArray(): vector is undefined", i);
|
|
vector = new Vector4();
|
|
}
|
|
array[offset++] = vector.x;
|
|
array[offset++] = vector.y;
|
|
array[offset++] = vector.z;
|
|
array[offset++] = vector.w;
|
|
}
|
|
return this;
|
|
}
|
|
applyMatrix3(m) {
|
|
if (this.itemSize === 2) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector2$1.fromBufferAttribute(this, i);
|
|
_vector2$1.applyMatrix3(m);
|
|
this.setXY(i, _vector2$1.x, _vector2$1.y);
|
|
}
|
|
} else if (this.itemSize === 3) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$9.fromBufferAttribute(this, i);
|
|
_vector$9.applyMatrix3(m);
|
|
this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
applyMatrix4(m) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$9.x = this.getX(i);
|
|
_vector$9.y = this.getY(i);
|
|
_vector$9.z = this.getZ(i);
|
|
_vector$9.applyMatrix4(m);
|
|
this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
|
|
}
|
|
return this;
|
|
}
|
|
applyNormalMatrix(m) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$9.x = this.getX(i);
|
|
_vector$9.y = this.getY(i);
|
|
_vector$9.z = this.getZ(i);
|
|
_vector$9.applyNormalMatrix(m);
|
|
this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
|
|
}
|
|
return this;
|
|
}
|
|
transformDirection(m) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$9.x = this.getX(i);
|
|
_vector$9.y = this.getY(i);
|
|
_vector$9.z = this.getZ(i);
|
|
_vector$9.transformDirection(m);
|
|
this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
|
|
}
|
|
return this;
|
|
}
|
|
set(value, offset = 0) {
|
|
this.array.set(value, offset);
|
|
return this;
|
|
}
|
|
getX(index) {
|
|
return this.array[index * this.itemSize];
|
|
}
|
|
setX(index, x) {
|
|
this.array[index * this.itemSize] = x;
|
|
return this;
|
|
}
|
|
getY(index) {
|
|
return this.array[index * this.itemSize + 1];
|
|
}
|
|
setY(index, y) {
|
|
this.array[index * this.itemSize + 1] = y;
|
|
return this;
|
|
}
|
|
getZ(index) {
|
|
return this.array[index * this.itemSize + 2];
|
|
}
|
|
setZ(index, z) {
|
|
this.array[index * this.itemSize + 2] = z;
|
|
return this;
|
|
}
|
|
getW(index) {
|
|
return this.array[index * this.itemSize + 3];
|
|
}
|
|
setW(index, w2) {
|
|
this.array[index * this.itemSize + 3] = w2;
|
|
return this;
|
|
}
|
|
setXY(index, x, y) {
|
|
index *= this.itemSize;
|
|
this.array[index + 0] = x;
|
|
this.array[index + 1] = y;
|
|
return this;
|
|
}
|
|
setXYZ(index, x, y, z) {
|
|
index *= this.itemSize;
|
|
this.array[index + 0] = x;
|
|
this.array[index + 1] = y;
|
|
this.array[index + 2] = z;
|
|
return this;
|
|
}
|
|
setXYZW(index, x, y, z, w2) {
|
|
index *= this.itemSize;
|
|
this.array[index + 0] = x;
|
|
this.array[index + 1] = y;
|
|
this.array[index + 2] = z;
|
|
this.array[index + 3] = w2;
|
|
return this;
|
|
}
|
|
onUpload(callback) {
|
|
this.onUploadCallback = callback;
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.array, this.itemSize).copy(this);
|
|
}
|
|
toJSON() {
|
|
const data = {
|
|
itemSize: this.itemSize,
|
|
type: this.array.constructor.name,
|
|
array: Array.prototype.slice.call(this.array),
|
|
normalized: this.normalized
|
|
};
|
|
if (this.name !== "")
|
|
data.name = this.name;
|
|
if (this.usage !== StaticDrawUsage)
|
|
data.usage = this.usage;
|
|
if (this.updateRange.offset !== 0 || this.updateRange.count !== -1)
|
|
data.updateRange = this.updateRange;
|
|
return data;
|
|
}
|
|
};
|
|
BufferAttribute.prototype.isBufferAttribute = true;
|
|
var Uint16BufferAttribute = class extends BufferAttribute {
|
|
constructor(array, itemSize, normalized) {
|
|
super(new Uint16Array(array), itemSize, normalized);
|
|
}
|
|
};
|
|
var Uint32BufferAttribute = class extends BufferAttribute {
|
|
constructor(array, itemSize, normalized) {
|
|
super(new Uint32Array(array), itemSize, normalized);
|
|
}
|
|
};
|
|
var Float16BufferAttribute = class extends BufferAttribute {
|
|
constructor(array, itemSize, normalized) {
|
|
super(new Uint16Array(array), itemSize, normalized);
|
|
}
|
|
};
|
|
Float16BufferAttribute.prototype.isFloat16BufferAttribute = true;
|
|
var Float32BufferAttribute = class extends BufferAttribute {
|
|
constructor(array, itemSize, normalized) {
|
|
super(new Float32Array(array), itemSize, normalized);
|
|
}
|
|
};
|
|
function arrayMax(array) {
|
|
if (array.length === 0)
|
|
return -Infinity;
|
|
let max = array[0];
|
|
for (let i = 1, l = array.length; i < l; ++i) {
|
|
if (array[i] > max)
|
|
max = array[i];
|
|
}
|
|
return max;
|
|
}
|
|
var _id = 0;
|
|
var _m1 = /* @__PURE__ */ new Matrix4();
|
|
var _obj = /* @__PURE__ */ new Object3D();
|
|
var _offset = /* @__PURE__ */ new Vector3();
|
|
var _box$1 = /* @__PURE__ */ new Box3();
|
|
var _boxMorphTargets = /* @__PURE__ */ new Box3();
|
|
var _vector$8 = /* @__PURE__ */ new Vector3();
|
|
var BufferGeometry = class extends EventDispatcher {
|
|
constructor() {
|
|
super();
|
|
Object.defineProperty(this, "id", { value: _id++ });
|
|
this.uuid = generateUUID();
|
|
this.name = "";
|
|
this.type = "BufferGeometry";
|
|
this.index = null;
|
|
this.attributes = {};
|
|
this.morphAttributes = {};
|
|
this.morphTargetsRelative = false;
|
|
this.groups = [];
|
|
this.boundingBox = null;
|
|
this.boundingSphere = null;
|
|
this.drawRange = { start: 0, count: Infinity };
|
|
this.userData = {};
|
|
}
|
|
getIndex() {
|
|
return this.index;
|
|
}
|
|
setIndex(index) {
|
|
if (Array.isArray(index)) {
|
|
this.index = new (arrayMax(index) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(index, 1);
|
|
} else {
|
|
this.index = index;
|
|
}
|
|
return this;
|
|
}
|
|
getAttribute(name) {
|
|
return this.attributes[name];
|
|
}
|
|
setAttribute(name, attribute) {
|
|
this.attributes[name] = attribute;
|
|
return this;
|
|
}
|
|
deleteAttribute(name) {
|
|
delete this.attributes[name];
|
|
return this;
|
|
}
|
|
hasAttribute(name) {
|
|
return this.attributes[name] !== void 0;
|
|
}
|
|
addGroup(start, count, materialIndex = 0) {
|
|
this.groups.push({
|
|
start,
|
|
count,
|
|
materialIndex
|
|
});
|
|
}
|
|
clearGroups() {
|
|
this.groups = [];
|
|
}
|
|
setDrawRange(start, count) {
|
|
this.drawRange.start = start;
|
|
this.drawRange.count = count;
|
|
}
|
|
applyMatrix4(matrix) {
|
|
const position = this.attributes.position;
|
|
if (position !== void 0) {
|
|
position.applyMatrix4(matrix);
|
|
position.needsUpdate = true;
|
|
}
|
|
const normal = this.attributes.normal;
|
|
if (normal !== void 0) {
|
|
const normalMatrix = new Matrix3().getNormalMatrix(matrix);
|
|
normal.applyNormalMatrix(normalMatrix);
|
|
normal.needsUpdate = true;
|
|
}
|
|
const tangent = this.attributes.tangent;
|
|
if (tangent !== void 0) {
|
|
tangent.transformDirection(matrix);
|
|
tangent.needsUpdate = true;
|
|
}
|
|
if (this.boundingBox !== null) {
|
|
this.computeBoundingBox();
|
|
}
|
|
if (this.boundingSphere !== null) {
|
|
this.computeBoundingSphere();
|
|
}
|
|
return this;
|
|
}
|
|
applyQuaternion(q) {
|
|
_m1.makeRotationFromQuaternion(q);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
rotateX(angle) {
|
|
_m1.makeRotationX(angle);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
rotateY(angle) {
|
|
_m1.makeRotationY(angle);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
rotateZ(angle) {
|
|
_m1.makeRotationZ(angle);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
translate(x, y, z) {
|
|
_m1.makeTranslation(x, y, z);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
scale(x, y, z) {
|
|
_m1.makeScale(x, y, z);
|
|
this.applyMatrix4(_m1);
|
|
return this;
|
|
}
|
|
lookAt(vector) {
|
|
_obj.lookAt(vector);
|
|
_obj.updateMatrix();
|
|
this.applyMatrix4(_obj.matrix);
|
|
return this;
|
|
}
|
|
center() {
|
|
this.computeBoundingBox();
|
|
this.boundingBox.getCenter(_offset).negate();
|
|
this.translate(_offset.x, _offset.y, _offset.z);
|
|
return this;
|
|
}
|
|
setFromPoints(points) {
|
|
const position = [];
|
|
for (let i = 0, l = points.length; i < l; i++) {
|
|
const point = points[i];
|
|
position.push(point.x, point.y, point.z || 0);
|
|
}
|
|
this.setAttribute("position", new Float32BufferAttribute(position, 3));
|
|
return this;
|
|
}
|
|
computeBoundingBox() {
|
|
if (this.boundingBox === null) {
|
|
this.boundingBox = new Box3();
|
|
}
|
|
const position = this.attributes.position;
|
|
const morphAttributesPosition = this.morphAttributes.position;
|
|
if (position && position.isGLBufferAttribute) {
|
|
console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this);
|
|
this.boundingBox.set(new Vector3(-Infinity, -Infinity, -Infinity), new Vector3(Infinity, Infinity, Infinity));
|
|
return;
|
|
}
|
|
if (position !== void 0) {
|
|
this.boundingBox.setFromBufferAttribute(position);
|
|
if (morphAttributesPosition) {
|
|
for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
|
|
const morphAttribute = morphAttributesPosition[i];
|
|
_box$1.setFromBufferAttribute(morphAttribute);
|
|
if (this.morphTargetsRelative) {
|
|
_vector$8.addVectors(this.boundingBox.min, _box$1.min);
|
|
this.boundingBox.expandByPoint(_vector$8);
|
|
_vector$8.addVectors(this.boundingBox.max, _box$1.max);
|
|
this.boundingBox.expandByPoint(_vector$8);
|
|
} else {
|
|
this.boundingBox.expandByPoint(_box$1.min);
|
|
this.boundingBox.expandByPoint(_box$1.max);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
this.boundingBox.makeEmpty();
|
|
}
|
|
if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
|
|
console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
|
|
}
|
|
}
|
|
computeBoundingSphere() {
|
|
if (this.boundingSphere === null) {
|
|
this.boundingSphere = new Sphere();
|
|
}
|
|
const position = this.attributes.position;
|
|
const morphAttributesPosition = this.morphAttributes.position;
|
|
if (position && position.isGLBufferAttribute) {
|
|
console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this);
|
|
this.boundingSphere.set(new Vector3(), Infinity);
|
|
return;
|
|
}
|
|
if (position) {
|
|
const center = this.boundingSphere.center;
|
|
_box$1.setFromBufferAttribute(position);
|
|
if (morphAttributesPosition) {
|
|
for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
|
|
const morphAttribute = morphAttributesPosition[i];
|
|
_boxMorphTargets.setFromBufferAttribute(morphAttribute);
|
|
if (this.morphTargetsRelative) {
|
|
_vector$8.addVectors(_box$1.min, _boxMorphTargets.min);
|
|
_box$1.expandByPoint(_vector$8);
|
|
_vector$8.addVectors(_box$1.max, _boxMorphTargets.max);
|
|
_box$1.expandByPoint(_vector$8);
|
|
} else {
|
|
_box$1.expandByPoint(_boxMorphTargets.min);
|
|
_box$1.expandByPoint(_boxMorphTargets.max);
|
|
}
|
|
}
|
|
}
|
|
_box$1.getCenter(center);
|
|
let maxRadiusSq = 0;
|
|
for (let i = 0, il = position.count; i < il; i++) {
|
|
_vector$8.fromBufferAttribute(position, i);
|
|
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8));
|
|
}
|
|
if (morphAttributesPosition) {
|
|
for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
|
|
const morphAttribute = morphAttributesPosition[i];
|
|
const morphTargetsRelative = this.morphTargetsRelative;
|
|
for (let j = 0, jl = morphAttribute.count; j < jl; j++) {
|
|
_vector$8.fromBufferAttribute(morphAttribute, j);
|
|
if (morphTargetsRelative) {
|
|
_offset.fromBufferAttribute(position, j);
|
|
_vector$8.add(_offset);
|
|
}
|
|
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8));
|
|
}
|
|
}
|
|
}
|
|
this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
|
|
if (isNaN(this.boundingSphere.radius)) {
|
|
console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this);
|
|
}
|
|
}
|
|
}
|
|
computeTangents() {
|
|
const index = this.index;
|
|
const attributes = this.attributes;
|
|
if (index === null || attributes.position === void 0 || attributes.normal === void 0 || attributes.uv === void 0) {
|
|
console.error("THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)");
|
|
return;
|
|
}
|
|
const indices = index.array;
|
|
const positions = attributes.position.array;
|
|
const normals = attributes.normal.array;
|
|
const uvs = attributes.uv.array;
|
|
const nVertices = positions.length / 3;
|
|
if (attributes.tangent === void 0) {
|
|
this.setAttribute("tangent", new BufferAttribute(new Float32Array(4 * nVertices), 4));
|
|
}
|
|
const tangents = attributes.tangent.array;
|
|
const tan1 = [], tan2 = [];
|
|
for (let i = 0; i < nVertices; i++) {
|
|
tan1[i] = new Vector3();
|
|
tan2[i] = new Vector3();
|
|
}
|
|
const vA = new Vector3(), vB = new Vector3(), vC = new Vector3(), uvA = new Vector2(), uvB = new Vector2(), uvC = new Vector2(), sdir = new Vector3(), tdir = new Vector3();
|
|
function handleTriangle(a2, b2, c2) {
|
|
vA.fromArray(positions, a2 * 3);
|
|
vB.fromArray(positions, b2 * 3);
|
|
vC.fromArray(positions, c2 * 3);
|
|
uvA.fromArray(uvs, a2 * 2);
|
|
uvB.fromArray(uvs, b2 * 2);
|
|
uvC.fromArray(uvs, c2 * 2);
|
|
vB.sub(vA);
|
|
vC.sub(vA);
|
|
uvB.sub(uvA);
|
|
uvC.sub(uvA);
|
|
const r = 1 / (uvB.x * uvC.y - uvC.x * uvB.y);
|
|
if (!isFinite(r))
|
|
return;
|
|
sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, -uvB.y).multiplyScalar(r);
|
|
tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, -uvC.x).multiplyScalar(r);
|
|
tan1[a2].add(sdir);
|
|
tan1[b2].add(sdir);
|
|
tan1[c2].add(sdir);
|
|
tan2[a2].add(tdir);
|
|
tan2[b2].add(tdir);
|
|
tan2[c2].add(tdir);
|
|
}
|
|
let groups = this.groups;
|
|
if (groups.length === 0) {
|
|
groups = [{
|
|
start: 0,
|
|
count: indices.length
|
|
}];
|
|
}
|
|
for (let i = 0, il = groups.length; i < il; ++i) {
|
|
const group = groups[i];
|
|
const start = group.start;
|
|
const count = group.count;
|
|
for (let j = start, jl = start + count; j < jl; j += 3) {
|
|
handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2]);
|
|
}
|
|
}
|
|
const tmp3 = new Vector3(), tmp22 = new Vector3();
|
|
const n = new Vector3(), n2 = new Vector3();
|
|
function handleVertex(v) {
|
|
n.fromArray(normals, v * 3);
|
|
n2.copy(n);
|
|
const t = tan1[v];
|
|
tmp3.copy(t);
|
|
tmp3.sub(n.multiplyScalar(n.dot(t))).normalize();
|
|
tmp22.crossVectors(n2, t);
|
|
const test = tmp22.dot(tan2[v]);
|
|
const w2 = test < 0 ? -1 : 1;
|
|
tangents[v * 4] = tmp3.x;
|
|
tangents[v * 4 + 1] = tmp3.y;
|
|
tangents[v * 4 + 2] = tmp3.z;
|
|
tangents[v * 4 + 3] = w2;
|
|
}
|
|
for (let i = 0, il = groups.length; i < il; ++i) {
|
|
const group = groups[i];
|
|
const start = group.start;
|
|
const count = group.count;
|
|
for (let j = start, jl = start + count; j < jl; j += 3) {
|
|
handleVertex(indices[j + 0]);
|
|
handleVertex(indices[j + 1]);
|
|
handleVertex(indices[j + 2]);
|
|
}
|
|
}
|
|
}
|
|
computeVertexNormals() {
|
|
const index = this.index;
|
|
const positionAttribute = this.getAttribute("position");
|
|
if (positionAttribute !== void 0) {
|
|
let normalAttribute = this.getAttribute("normal");
|
|
if (normalAttribute === void 0) {
|
|
normalAttribute = new BufferAttribute(new Float32Array(positionAttribute.count * 3), 3);
|
|
this.setAttribute("normal", normalAttribute);
|
|
} else {
|
|
for (let i = 0, il = normalAttribute.count; i < il; i++) {
|
|
normalAttribute.setXYZ(i, 0, 0, 0);
|
|
}
|
|
}
|
|
const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
|
|
const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
|
|
const cb2 = new Vector3(), ab2 = new Vector3();
|
|
if (index) {
|
|
for (let i = 0, il = index.count; i < il; i += 3) {
|
|
const vA = index.getX(i + 0);
|
|
const vB = index.getX(i + 1);
|
|
const vC = index.getX(i + 2);
|
|
pA.fromBufferAttribute(positionAttribute, vA);
|
|
pB.fromBufferAttribute(positionAttribute, vB);
|
|
pC.fromBufferAttribute(positionAttribute, vC);
|
|
cb2.subVectors(pC, pB);
|
|
ab2.subVectors(pA, pB);
|
|
cb2.cross(ab2);
|
|
nA.fromBufferAttribute(normalAttribute, vA);
|
|
nB.fromBufferAttribute(normalAttribute, vB);
|
|
nC.fromBufferAttribute(normalAttribute, vC);
|
|
nA.add(cb2);
|
|
nB.add(cb2);
|
|
nC.add(cb2);
|
|
normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z);
|
|
normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z);
|
|
normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z);
|
|
}
|
|
} else {
|
|
for (let i = 0, il = positionAttribute.count; i < il; i += 3) {
|
|
pA.fromBufferAttribute(positionAttribute, i + 0);
|
|
pB.fromBufferAttribute(positionAttribute, i + 1);
|
|
pC.fromBufferAttribute(positionAttribute, i + 2);
|
|
cb2.subVectors(pC, pB);
|
|
ab2.subVectors(pA, pB);
|
|
cb2.cross(ab2);
|
|
normalAttribute.setXYZ(i + 0, cb2.x, cb2.y, cb2.z);
|
|
normalAttribute.setXYZ(i + 1, cb2.x, cb2.y, cb2.z);
|
|
normalAttribute.setXYZ(i + 2, cb2.x, cb2.y, cb2.z);
|
|
}
|
|
}
|
|
this.normalizeNormals();
|
|
normalAttribute.needsUpdate = true;
|
|
}
|
|
}
|
|
merge(geometry, offset) {
|
|
if (!(geometry && geometry.isBufferGeometry)) {
|
|
console.error("THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.", geometry);
|
|
return;
|
|
}
|
|
if (offset === void 0) {
|
|
offset = 0;
|
|
console.warn("THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.");
|
|
}
|
|
const attributes = this.attributes;
|
|
for (const key in attributes) {
|
|
if (geometry.attributes[key] === void 0)
|
|
continue;
|
|
const attribute1 = attributes[key];
|
|
const attributeArray1 = attribute1.array;
|
|
const attribute2 = geometry.attributes[key];
|
|
const attributeArray2 = attribute2.array;
|
|
const attributeOffset = attribute2.itemSize * offset;
|
|
const length = Math.min(attributeArray2.length, attributeArray1.length - attributeOffset);
|
|
for (let i = 0, j = attributeOffset; i < length; i++, j++) {
|
|
attributeArray1[j] = attributeArray2[i];
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
normalizeNormals() {
|
|
const normals = this.attributes.normal;
|
|
for (let i = 0, il = normals.count; i < il; i++) {
|
|
_vector$8.fromBufferAttribute(normals, i);
|
|
_vector$8.normalize();
|
|
normals.setXYZ(i, _vector$8.x, _vector$8.y, _vector$8.z);
|
|
}
|
|
}
|
|
toNonIndexed() {
|
|
function convertBufferAttribute(attribute, indices2) {
|
|
const array = attribute.array;
|
|
const itemSize = attribute.itemSize;
|
|
const normalized = attribute.normalized;
|
|
const array2 = new array.constructor(indices2.length * itemSize);
|
|
let index = 0, index2 = 0;
|
|
for (let i = 0, l = indices2.length; i < l; i++) {
|
|
if (attribute.isInterleavedBufferAttribute) {
|
|
index = indices2[i] * attribute.data.stride + attribute.offset;
|
|
} else {
|
|
index = indices2[i] * itemSize;
|
|
}
|
|
for (let j = 0; j < itemSize; j++) {
|
|
array2[index2++] = array[index++];
|
|
}
|
|
}
|
|
return new BufferAttribute(array2, itemSize, normalized);
|
|
}
|
|
if (this.index === null) {
|
|
console.warn("THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.");
|
|
return this;
|
|
}
|
|
const geometry2 = new BufferGeometry();
|
|
const indices = this.index.array;
|
|
const attributes = this.attributes;
|
|
for (const name in attributes) {
|
|
const attribute = attributes[name];
|
|
const newAttribute = convertBufferAttribute(attribute, indices);
|
|
geometry2.setAttribute(name, newAttribute);
|
|
}
|
|
const morphAttributes = this.morphAttributes;
|
|
for (const name in morphAttributes) {
|
|
const morphArray = [];
|
|
const morphAttribute = morphAttributes[name];
|
|
for (let i = 0, il = morphAttribute.length; i < il; i++) {
|
|
const attribute = morphAttribute[i];
|
|
const newAttribute = convertBufferAttribute(attribute, indices);
|
|
morphArray.push(newAttribute);
|
|
}
|
|
geometry2.morphAttributes[name] = morphArray;
|
|
}
|
|
geometry2.morphTargetsRelative = this.morphTargetsRelative;
|
|
const groups = this.groups;
|
|
for (let i = 0, l = groups.length; i < l; i++) {
|
|
const group = groups[i];
|
|
geometry2.addGroup(group.start, group.count, group.materialIndex);
|
|
}
|
|
return geometry2;
|
|
}
|
|
toJSON() {
|
|
const data = {
|
|
metadata: {
|
|
version: 4.5,
|
|
type: "BufferGeometry",
|
|
generator: "BufferGeometry.toJSON"
|
|
}
|
|
};
|
|
data.uuid = this.uuid;
|
|
data.type = this.type;
|
|
if (this.name !== "")
|
|
data.name = this.name;
|
|
if (Object.keys(this.userData).length > 0)
|
|
data.userData = this.userData;
|
|
if (this.parameters !== void 0) {
|
|
const parameters = this.parameters;
|
|
for (const key in parameters) {
|
|
if (parameters[key] !== void 0)
|
|
data[key] = parameters[key];
|
|
}
|
|
return data;
|
|
}
|
|
data.data = { attributes: {} };
|
|
const index = this.index;
|
|
if (index !== null) {
|
|
data.data.index = {
|
|
type: index.array.constructor.name,
|
|
array: Array.prototype.slice.call(index.array)
|
|
};
|
|
}
|
|
const attributes = this.attributes;
|
|
for (const key in attributes) {
|
|
const attribute = attributes[key];
|
|
data.data.attributes[key] = attribute.toJSON(data.data);
|
|
}
|
|
const morphAttributes = {};
|
|
let hasMorphAttributes = false;
|
|
for (const key in this.morphAttributes) {
|
|
const attributeArray = this.morphAttributes[key];
|
|
const array = [];
|
|
for (let i = 0, il = attributeArray.length; i < il; i++) {
|
|
const attribute = attributeArray[i];
|
|
array.push(attribute.toJSON(data.data));
|
|
}
|
|
if (array.length > 0) {
|
|
morphAttributes[key] = array;
|
|
hasMorphAttributes = true;
|
|
}
|
|
}
|
|
if (hasMorphAttributes) {
|
|
data.data.morphAttributes = morphAttributes;
|
|
data.data.morphTargetsRelative = this.morphTargetsRelative;
|
|
}
|
|
const groups = this.groups;
|
|
if (groups.length > 0) {
|
|
data.data.groups = JSON.parse(JSON.stringify(groups));
|
|
}
|
|
const boundingSphere = this.boundingSphere;
|
|
if (boundingSphere !== null) {
|
|
data.data.boundingSphere = {
|
|
center: boundingSphere.center.toArray(),
|
|
radius: boundingSphere.radius
|
|
};
|
|
}
|
|
return data;
|
|
}
|
|
clone() {
|
|
return new BufferGeometry().copy(this);
|
|
}
|
|
copy(source) {
|
|
this.index = null;
|
|
this.attributes = {};
|
|
this.morphAttributes = {};
|
|
this.groups = [];
|
|
this.boundingBox = null;
|
|
this.boundingSphere = null;
|
|
const data = {};
|
|
this.name = source.name;
|
|
const index = source.index;
|
|
if (index !== null) {
|
|
this.setIndex(index.clone(data));
|
|
}
|
|
const attributes = source.attributes;
|
|
for (const name in attributes) {
|
|
const attribute = attributes[name];
|
|
this.setAttribute(name, attribute.clone(data));
|
|
}
|
|
const morphAttributes = source.morphAttributes;
|
|
for (const name in morphAttributes) {
|
|
const array = [];
|
|
const morphAttribute = morphAttributes[name];
|
|
for (let i = 0, l = morphAttribute.length; i < l; i++) {
|
|
array.push(morphAttribute[i].clone(data));
|
|
}
|
|
this.morphAttributes[name] = array;
|
|
}
|
|
this.morphTargetsRelative = source.morphTargetsRelative;
|
|
const groups = source.groups;
|
|
for (let i = 0, l = groups.length; i < l; i++) {
|
|
const group = groups[i];
|
|
this.addGroup(group.start, group.count, group.materialIndex);
|
|
}
|
|
const boundingBox = source.boundingBox;
|
|
if (boundingBox !== null) {
|
|
this.boundingBox = boundingBox.clone();
|
|
}
|
|
const boundingSphere = source.boundingSphere;
|
|
if (boundingSphere !== null) {
|
|
this.boundingSphere = boundingSphere.clone();
|
|
}
|
|
this.drawRange.start = source.drawRange.start;
|
|
this.drawRange.count = source.drawRange.count;
|
|
this.userData = source.userData;
|
|
return this;
|
|
}
|
|
dispose() {
|
|
this.dispatchEvent({ type: "dispose" });
|
|
}
|
|
};
|
|
BufferGeometry.prototype.isBufferGeometry = true;
|
|
var _inverseMatrix$2 = /* @__PURE__ */ new Matrix4();
|
|
var _ray$2 = /* @__PURE__ */ new Ray();
|
|
var _sphere$3 = /* @__PURE__ */ new Sphere();
|
|
var _vA$1 = /* @__PURE__ */ new Vector3();
|
|
var _vB$1 = /* @__PURE__ */ new Vector3();
|
|
var _vC$1 = /* @__PURE__ */ new Vector3();
|
|
var _tempA = /* @__PURE__ */ new Vector3();
|
|
var _tempB = /* @__PURE__ */ new Vector3();
|
|
var _tempC = /* @__PURE__ */ new Vector3();
|
|
var _morphA = /* @__PURE__ */ new Vector3();
|
|
var _morphB = /* @__PURE__ */ new Vector3();
|
|
var _morphC = /* @__PURE__ */ new Vector3();
|
|
var _uvA$1 = /* @__PURE__ */ new Vector2();
|
|
var _uvB$1 = /* @__PURE__ */ new Vector2();
|
|
var _uvC$1 = /* @__PURE__ */ new Vector2();
|
|
var _intersectionPoint = /* @__PURE__ */ new Vector3();
|
|
var _intersectionPointWorld = /* @__PURE__ */ new Vector3();
|
|
var Mesh = class extends Object3D {
|
|
constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) {
|
|
super();
|
|
this.type = "Mesh";
|
|
this.geometry = geometry;
|
|
this.material = material;
|
|
this.updateMorphTargets();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
if (source.morphTargetInfluences !== void 0) {
|
|
this.morphTargetInfluences = source.morphTargetInfluences.slice();
|
|
}
|
|
if (source.morphTargetDictionary !== void 0) {
|
|
this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary);
|
|
}
|
|
this.material = source.material;
|
|
this.geometry = source.geometry;
|
|
return this;
|
|
}
|
|
updateMorphTargets() {
|
|
const geometry = this.geometry;
|
|
if (geometry.isBufferGeometry) {
|
|
const morphAttributes = geometry.morphAttributes;
|
|
const keys = Object.keys(morphAttributes);
|
|
if (keys.length > 0) {
|
|
const morphAttribute = morphAttributes[keys[0]];
|
|
if (morphAttribute !== void 0) {
|
|
this.morphTargetInfluences = [];
|
|
this.morphTargetDictionary = {};
|
|
for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
|
|
const name = morphAttribute[m].name || String(m);
|
|
this.morphTargetInfluences.push(0);
|
|
this.morphTargetDictionary[name] = m;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const morphTargets = geometry.morphTargets;
|
|
if (morphTargets !== void 0 && morphTargets.length > 0) {
|
|
console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
}
|
|
raycast(raycaster, intersects2) {
|
|
const geometry = this.geometry;
|
|
const material = this.material;
|
|
const matrixWorld = this.matrixWorld;
|
|
if (material === void 0)
|
|
return;
|
|
if (geometry.boundingSphere === null)
|
|
geometry.computeBoundingSphere();
|
|
_sphere$3.copy(geometry.boundingSphere);
|
|
_sphere$3.applyMatrix4(matrixWorld);
|
|
if (raycaster.ray.intersectsSphere(_sphere$3) === false)
|
|
return;
|
|
_inverseMatrix$2.copy(matrixWorld).invert();
|
|
_ray$2.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2);
|
|
if (geometry.boundingBox !== null) {
|
|
if (_ray$2.intersectsBox(geometry.boundingBox) === false)
|
|
return;
|
|
}
|
|
let intersection;
|
|
if (geometry.isBufferGeometry) {
|
|
const index = geometry.index;
|
|
const position = geometry.attributes.position;
|
|
const morphPosition = geometry.morphAttributes.position;
|
|
const morphTargetsRelative = geometry.morphTargetsRelative;
|
|
const uv = geometry.attributes.uv;
|
|
const uv2 = geometry.attributes.uv2;
|
|
const groups = geometry.groups;
|
|
const drawRange = geometry.drawRange;
|
|
if (index !== null) {
|
|
if (Array.isArray(material)) {
|
|
for (let i = 0, il = groups.length; i < il; i++) {
|
|
const group = groups[i];
|
|
const groupMaterial = material[group.materialIndex];
|
|
const start = Math.max(group.start, drawRange.start);
|
|
const end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
|
for (let j = start, jl = end; j < jl; j += 3) {
|
|
const a2 = index.getX(j);
|
|
const b2 = index.getX(j + 1);
|
|
const c2 = index.getX(j + 2);
|
|
intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b2, c2);
|
|
if (intersection) {
|
|
intersection.faceIndex = Math.floor(j / 3);
|
|
intersection.face.materialIndex = group.materialIndex;
|
|
intersects2.push(intersection);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(index.count, drawRange.start + drawRange.count);
|
|
for (let i = start, il = end; i < il; i += 3) {
|
|
const a2 = index.getX(i);
|
|
const b2 = index.getX(i + 1);
|
|
const c2 = index.getX(i + 2);
|
|
intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b2, c2);
|
|
if (intersection) {
|
|
intersection.faceIndex = Math.floor(i / 3);
|
|
intersects2.push(intersection);
|
|
}
|
|
}
|
|
}
|
|
} else if (position !== void 0) {
|
|
if (Array.isArray(material)) {
|
|
for (let i = 0, il = groups.length; i < il; i++) {
|
|
const group = groups[i];
|
|
const groupMaterial = material[group.materialIndex];
|
|
const start = Math.max(group.start, drawRange.start);
|
|
const end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
|
for (let j = start, jl = end; j < jl; j += 3) {
|
|
const a2 = j;
|
|
const b2 = j + 1;
|
|
const c2 = j + 2;
|
|
intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b2, c2);
|
|
if (intersection) {
|
|
intersection.faceIndex = Math.floor(j / 3);
|
|
intersection.face.materialIndex = group.materialIndex;
|
|
intersects2.push(intersection);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(position.count, drawRange.start + drawRange.count);
|
|
for (let i = start, il = end; i < il; i += 3) {
|
|
const a2 = i;
|
|
const b2 = i + 1;
|
|
const c2 = i + 2;
|
|
intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b2, c2);
|
|
if (intersection) {
|
|
intersection.faceIndex = Math.floor(i / 3);
|
|
intersects2.push(intersection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (geometry.isGeometry) {
|
|
console.error("THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
};
|
|
Mesh.prototype.isMesh = true;
|
|
function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
|
|
let intersect2;
|
|
if (material.side === BackSide) {
|
|
intersect2 = ray.intersectTriangle(pC, pB, pA, true, point);
|
|
} else {
|
|
intersect2 = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide, point);
|
|
}
|
|
if (intersect2 === null)
|
|
return null;
|
|
_intersectionPointWorld.copy(point);
|
|
_intersectionPointWorld.applyMatrix4(object.matrixWorld);
|
|
const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld);
|
|
if (distance < raycaster.near || distance > raycaster.far)
|
|
return null;
|
|
return {
|
|
distance,
|
|
point: _intersectionPointWorld.clone(),
|
|
object
|
|
};
|
|
}
|
|
function checkBufferGeometryIntersection(object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b2, c2) {
|
|
_vA$1.fromBufferAttribute(position, a2);
|
|
_vB$1.fromBufferAttribute(position, b2);
|
|
_vC$1.fromBufferAttribute(position, c2);
|
|
const morphInfluences = object.morphTargetInfluences;
|
|
if (morphPosition && morphInfluences) {
|
|
_morphA.set(0, 0, 0);
|
|
_morphB.set(0, 0, 0);
|
|
_morphC.set(0, 0, 0);
|
|
for (let i = 0, il = morphPosition.length; i < il; i++) {
|
|
const influence = morphInfluences[i];
|
|
const morphAttribute = morphPosition[i];
|
|
if (influence === 0)
|
|
continue;
|
|
_tempA.fromBufferAttribute(morphAttribute, a2);
|
|
_tempB.fromBufferAttribute(morphAttribute, b2);
|
|
_tempC.fromBufferAttribute(morphAttribute, c2);
|
|
if (morphTargetsRelative) {
|
|
_morphA.addScaledVector(_tempA, influence);
|
|
_morphB.addScaledVector(_tempB, influence);
|
|
_morphC.addScaledVector(_tempC, influence);
|
|
} else {
|
|
_morphA.addScaledVector(_tempA.sub(_vA$1), influence);
|
|
_morphB.addScaledVector(_tempB.sub(_vB$1), influence);
|
|
_morphC.addScaledVector(_tempC.sub(_vC$1), influence);
|
|
}
|
|
}
|
|
_vA$1.add(_morphA);
|
|
_vB$1.add(_morphB);
|
|
_vC$1.add(_morphC);
|
|
}
|
|
if (object.isSkinnedMesh) {
|
|
object.boneTransform(a2, _vA$1);
|
|
object.boneTransform(b2, _vB$1);
|
|
object.boneTransform(c2, _vC$1);
|
|
}
|
|
const intersection = checkIntersection(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint);
|
|
if (intersection) {
|
|
if (uv) {
|
|
_uvA$1.fromBufferAttribute(uv, a2);
|
|
_uvB$1.fromBufferAttribute(uv, b2);
|
|
_uvC$1.fromBufferAttribute(uv, c2);
|
|
intersection.uv = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
}
|
|
if (uv2) {
|
|
_uvA$1.fromBufferAttribute(uv2, a2);
|
|
_uvB$1.fromBufferAttribute(uv2, b2);
|
|
_uvC$1.fromBufferAttribute(uv2, c2);
|
|
intersection.uv2 = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
|
|
}
|
|
const face = {
|
|
a: a2,
|
|
b: b2,
|
|
c: c2,
|
|
normal: new Vector3(),
|
|
materialIndex: 0
|
|
};
|
|
Triangle.getNormal(_vA$1, _vB$1, _vC$1, face.normal);
|
|
intersection.face = face;
|
|
}
|
|
return intersection;
|
|
}
|
|
var BoxGeometry = class extends BufferGeometry {
|
|
constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
|
|
super();
|
|
this.type = "BoxGeometry";
|
|
this.parameters = {
|
|
width,
|
|
height,
|
|
depth,
|
|
widthSegments,
|
|
heightSegments,
|
|
depthSegments
|
|
};
|
|
const scope = this;
|
|
widthSegments = Math.floor(widthSegments);
|
|
heightSegments = Math.floor(heightSegments);
|
|
depthSegments = Math.floor(depthSegments);
|
|
const indices = [];
|
|
const vertices = [];
|
|
const normals = [];
|
|
const uvs = [];
|
|
let numberOfVertices = 0;
|
|
let groupStart = 0;
|
|
buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0);
|
|
buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
|
|
buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2);
|
|
buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
|
|
buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4);
|
|
buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
|
|
this.setIndex(indices);
|
|
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
|
|
this.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
function buildPlane(u, v, w2, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) {
|
|
const segmentWidth = width2 / gridX;
|
|
const segmentHeight = height2 / gridY;
|
|
const widthHalf = width2 / 2;
|
|
const heightHalf = height2 / 2;
|
|
const depthHalf = depth2 / 2;
|
|
const gridX1 = gridX + 1;
|
|
const gridY1 = gridY + 1;
|
|
let vertexCounter = 0;
|
|
let groupCount = 0;
|
|
const vector = new Vector3();
|
|
for (let iy = 0; iy < gridY1; iy++) {
|
|
const y = iy * segmentHeight - heightHalf;
|
|
for (let ix = 0; ix < gridX1; ix++) {
|
|
const x = ix * segmentWidth - widthHalf;
|
|
vector[u] = x * udir;
|
|
vector[v] = y * vdir;
|
|
vector[w2] = depthHalf;
|
|
vertices.push(vector.x, vector.y, vector.z);
|
|
vector[u] = 0;
|
|
vector[v] = 0;
|
|
vector[w2] = depth2 > 0 ? 1 : -1;
|
|
normals.push(vector.x, vector.y, vector.z);
|
|
uvs.push(ix / gridX);
|
|
uvs.push(1 - iy / gridY);
|
|
vertexCounter += 1;
|
|
}
|
|
}
|
|
for (let iy = 0; iy < gridY; iy++) {
|
|
for (let ix = 0; ix < gridX; ix++) {
|
|
const a2 = numberOfVertices + ix + gridX1 * iy;
|
|
const b2 = numberOfVertices + ix + gridX1 * (iy + 1);
|
|
const c2 = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
|
|
const d = numberOfVertices + (ix + 1) + gridX1 * iy;
|
|
indices.push(a2, b2, d);
|
|
indices.push(b2, c2, d);
|
|
groupCount += 6;
|
|
}
|
|
}
|
|
scope.addGroup(groupStart, groupCount, materialIndex);
|
|
groupStart += groupCount;
|
|
numberOfVertices += vertexCounter;
|
|
}
|
|
}
|
|
static fromJSON(data) {
|
|
return new BoxGeometry(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
|
|
}
|
|
};
|
|
function cloneUniforms(src) {
|
|
const dst = {};
|
|
for (const u in src) {
|
|
dst[u] = {};
|
|
for (const p2 in src[u]) {
|
|
const property = src[u][p2];
|
|
if (property && (property.isColor || property.isMatrix3 || property.isMatrix4 || property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion)) {
|
|
dst[u][p2] = property.clone();
|
|
} else if (Array.isArray(property)) {
|
|
dst[u][p2] = property.slice();
|
|
} else {
|
|
dst[u][p2] = property;
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
function mergeUniforms(uniforms) {
|
|
const merged = {};
|
|
for (let u = 0; u < uniforms.length; u++) {
|
|
const tmp3 = cloneUniforms(uniforms[u]);
|
|
for (const p2 in tmp3) {
|
|
merged[p2] = tmp3[p2];
|
|
}
|
|
}
|
|
return merged;
|
|
}
|
|
var UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
|
|
var default_vertex = "void main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
|
|
var default_fragment = "void main() {\n gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
|
|
var ShaderMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "ShaderMaterial";
|
|
this.defines = {};
|
|
this.uniforms = {};
|
|
this.vertexShader = default_vertex;
|
|
this.fragmentShader = default_fragment;
|
|
this.linewidth = 1;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.fog = false;
|
|
this.lights = false;
|
|
this.clipping = false;
|
|
this.extensions = {
|
|
derivatives: false,
|
|
fragDepth: false,
|
|
drawBuffers: false,
|
|
shaderTextureLOD: false
|
|
};
|
|
this.defaultAttributeValues = {
|
|
"color": [1, 1, 1],
|
|
"uv": [0, 0],
|
|
"uv2": [0, 0]
|
|
};
|
|
this.index0AttributeName = void 0;
|
|
this.uniformsNeedUpdate = false;
|
|
this.glslVersion = null;
|
|
if (parameters !== void 0) {
|
|
if (parameters.attributes !== void 0) {
|
|
console.error("THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.");
|
|
}
|
|
this.setValues(parameters);
|
|
}
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.fragmentShader = source.fragmentShader;
|
|
this.vertexShader = source.vertexShader;
|
|
this.uniforms = cloneUniforms(source.uniforms);
|
|
this.defines = Object.assign({}, source.defines);
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.lights = source.lights;
|
|
this.clipping = source.clipping;
|
|
this.extensions = Object.assign({}, source.extensions);
|
|
this.glslVersion = source.glslVersion;
|
|
return this;
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.glslVersion = this.glslVersion;
|
|
data.uniforms = {};
|
|
for (const name in this.uniforms) {
|
|
const uniform = this.uniforms[name];
|
|
const value = uniform.value;
|
|
if (value && value.isTexture) {
|
|
data.uniforms[name] = {
|
|
type: "t",
|
|
value: value.toJSON(meta).uuid
|
|
};
|
|
} else if (value && value.isColor) {
|
|
data.uniforms[name] = {
|
|
type: "c",
|
|
value: value.getHex()
|
|
};
|
|
} else if (value && value.isVector2) {
|
|
data.uniforms[name] = {
|
|
type: "v2",
|
|
value: value.toArray()
|
|
};
|
|
} else if (value && value.isVector3) {
|
|
data.uniforms[name] = {
|
|
type: "v3",
|
|
value: value.toArray()
|
|
};
|
|
} else if (value && value.isVector4) {
|
|
data.uniforms[name] = {
|
|
type: "v4",
|
|
value: value.toArray()
|
|
};
|
|
} else if (value && value.isMatrix3) {
|
|
data.uniforms[name] = {
|
|
type: "m3",
|
|
value: value.toArray()
|
|
};
|
|
} else if (value && value.isMatrix4) {
|
|
data.uniforms[name] = {
|
|
type: "m4",
|
|
value: value.toArray()
|
|
};
|
|
} else {
|
|
data.uniforms[name] = {
|
|
value
|
|
};
|
|
}
|
|
}
|
|
if (Object.keys(this.defines).length > 0)
|
|
data.defines = this.defines;
|
|
data.vertexShader = this.vertexShader;
|
|
data.fragmentShader = this.fragmentShader;
|
|
const extensions = {};
|
|
for (const key in this.extensions) {
|
|
if (this.extensions[key] === true)
|
|
extensions[key] = true;
|
|
}
|
|
if (Object.keys(extensions).length > 0)
|
|
data.extensions = extensions;
|
|
return data;
|
|
}
|
|
};
|
|
ShaderMaterial.prototype.isShaderMaterial = true;
|
|
var Camera = class extends Object3D {
|
|
constructor() {
|
|
super();
|
|
this.type = "Camera";
|
|
this.matrixWorldInverse = new Matrix4();
|
|
this.projectionMatrix = new Matrix4();
|
|
this.projectionMatrixInverse = new Matrix4();
|
|
}
|
|
copy(source, recursive) {
|
|
super.copy(source, recursive);
|
|
this.matrixWorldInverse.copy(source.matrixWorldInverse);
|
|
this.projectionMatrix.copy(source.projectionMatrix);
|
|
this.projectionMatrixInverse.copy(source.projectionMatrixInverse);
|
|
return this;
|
|
}
|
|
getWorldDirection(target) {
|
|
this.updateWorldMatrix(true, false);
|
|
const e = this.matrixWorld.elements;
|
|
return target.set(-e[8], -e[9], -e[10]).normalize();
|
|
}
|
|
updateMatrixWorld(force) {
|
|
super.updateMatrixWorld(force);
|
|
this.matrixWorldInverse.copy(this.matrixWorld).invert();
|
|
}
|
|
updateWorldMatrix(updateParents, updateChildren) {
|
|
super.updateWorldMatrix(updateParents, updateChildren);
|
|
this.matrixWorldInverse.copy(this.matrixWorld).invert();
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
Camera.prototype.isCamera = true;
|
|
var PerspectiveCamera = class extends Camera {
|
|
constructor(fov2 = 50, aspect2 = 1, near = 0.1, far = 2e3) {
|
|
super();
|
|
this.type = "PerspectiveCamera";
|
|
this.fov = fov2;
|
|
this.zoom = 1;
|
|
this.near = near;
|
|
this.far = far;
|
|
this.focus = 10;
|
|
this.aspect = aspect2;
|
|
this.view = null;
|
|
this.filmGauge = 35;
|
|
this.filmOffset = 0;
|
|
this.updateProjectionMatrix();
|
|
}
|
|
copy(source, recursive) {
|
|
super.copy(source, recursive);
|
|
this.fov = source.fov;
|
|
this.zoom = source.zoom;
|
|
this.near = source.near;
|
|
this.far = source.far;
|
|
this.focus = source.focus;
|
|
this.aspect = source.aspect;
|
|
this.view = source.view === null ? null : Object.assign({}, source.view);
|
|
this.filmGauge = source.filmGauge;
|
|
this.filmOffset = source.filmOffset;
|
|
return this;
|
|
}
|
|
setFocalLength(focalLength) {
|
|
const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
|
|
this.fov = RAD2DEG * 2 * Math.atan(vExtentSlope);
|
|
this.updateProjectionMatrix();
|
|
}
|
|
getFocalLength() {
|
|
const vExtentSlope = Math.tan(DEG2RAD * 0.5 * this.fov);
|
|
return 0.5 * this.getFilmHeight() / vExtentSlope;
|
|
}
|
|
getEffectiveFOV() {
|
|
return RAD2DEG * 2 * Math.atan(Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom);
|
|
}
|
|
getFilmWidth() {
|
|
return this.filmGauge * Math.min(this.aspect, 1);
|
|
}
|
|
getFilmHeight() {
|
|
return this.filmGauge / Math.max(this.aspect, 1);
|
|
}
|
|
setViewOffset(fullWidth, fullHeight, x, y, width, height) {
|
|
this.aspect = fullWidth / fullHeight;
|
|
if (this.view === null) {
|
|
this.view = {
|
|
enabled: true,
|
|
fullWidth: 1,
|
|
fullHeight: 1,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
width: 1,
|
|
height: 1
|
|
};
|
|
}
|
|
this.view.enabled = true;
|
|
this.view.fullWidth = fullWidth;
|
|
this.view.fullHeight = fullHeight;
|
|
this.view.offsetX = x;
|
|
this.view.offsetY = y;
|
|
this.view.width = width;
|
|
this.view.height = height;
|
|
this.updateProjectionMatrix();
|
|
}
|
|
clearViewOffset() {
|
|
if (this.view !== null) {
|
|
this.view.enabled = false;
|
|
}
|
|
this.updateProjectionMatrix();
|
|
}
|
|
updateProjectionMatrix() {
|
|
const near = this.near;
|
|
let top = near * Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom;
|
|
let height = 2 * top;
|
|
let width = this.aspect * height;
|
|
let left = -0.5 * width;
|
|
const view = this.view;
|
|
if (this.view !== null && this.view.enabled) {
|
|
const fullWidth = view.fullWidth, fullHeight = view.fullHeight;
|
|
left += view.offsetX * width / fullWidth;
|
|
top -= view.offsetY * height / fullHeight;
|
|
width *= view.width / fullWidth;
|
|
height *= view.height / fullHeight;
|
|
}
|
|
const skew = this.filmOffset;
|
|
if (skew !== 0)
|
|
left += near * skew / this.getFilmWidth();
|
|
this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far);
|
|
this.projectionMatrixInverse.copy(this.projectionMatrix).invert();
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.object.fov = this.fov;
|
|
data.object.zoom = this.zoom;
|
|
data.object.near = this.near;
|
|
data.object.far = this.far;
|
|
data.object.focus = this.focus;
|
|
data.object.aspect = this.aspect;
|
|
if (this.view !== null)
|
|
data.object.view = Object.assign({}, this.view);
|
|
data.object.filmGauge = this.filmGauge;
|
|
data.object.filmOffset = this.filmOffset;
|
|
return data;
|
|
}
|
|
};
|
|
PerspectiveCamera.prototype.isPerspectiveCamera = true;
|
|
var fov = 90;
|
|
var aspect = 1;
|
|
var CubeCamera = class extends Object3D {
|
|
constructor(near, far, renderTarget) {
|
|
super();
|
|
this.type = "CubeCamera";
|
|
if (renderTarget.isWebGLCubeRenderTarget !== true) {
|
|
console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.");
|
|
return;
|
|
}
|
|
this.renderTarget = renderTarget;
|
|
const cameraPX = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraPX.layers = this.layers;
|
|
cameraPX.up.set(0, -1, 0);
|
|
cameraPX.lookAt(new Vector3(1, 0, 0));
|
|
this.add(cameraPX);
|
|
const cameraNX = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraNX.layers = this.layers;
|
|
cameraNX.up.set(0, -1, 0);
|
|
cameraNX.lookAt(new Vector3(-1, 0, 0));
|
|
this.add(cameraNX);
|
|
const cameraPY = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraPY.layers = this.layers;
|
|
cameraPY.up.set(0, 0, 1);
|
|
cameraPY.lookAt(new Vector3(0, 1, 0));
|
|
this.add(cameraPY);
|
|
const cameraNY = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraNY.layers = this.layers;
|
|
cameraNY.up.set(0, 0, -1);
|
|
cameraNY.lookAt(new Vector3(0, -1, 0));
|
|
this.add(cameraNY);
|
|
const cameraPZ = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraPZ.layers = this.layers;
|
|
cameraPZ.up.set(0, -1, 0);
|
|
cameraPZ.lookAt(new Vector3(0, 0, 1));
|
|
this.add(cameraPZ);
|
|
const cameraNZ = new PerspectiveCamera(fov, aspect, near, far);
|
|
cameraNZ.layers = this.layers;
|
|
cameraNZ.up.set(0, -1, 0);
|
|
cameraNZ.lookAt(new Vector3(0, 0, -1));
|
|
this.add(cameraNZ);
|
|
}
|
|
update(renderer, scene) {
|
|
if (this.parent === null)
|
|
this.updateMatrixWorld();
|
|
const renderTarget = this.renderTarget;
|
|
const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = this.children;
|
|
const currentXrEnabled = renderer.xr.enabled;
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
renderer.xr.enabled = false;
|
|
const generateMipmaps = renderTarget.texture.generateMipmaps;
|
|
renderTarget.texture.generateMipmaps = false;
|
|
renderer.setRenderTarget(renderTarget, 0);
|
|
renderer.render(scene, cameraPX);
|
|
renderer.setRenderTarget(renderTarget, 1);
|
|
renderer.render(scene, cameraNX);
|
|
renderer.setRenderTarget(renderTarget, 2);
|
|
renderer.render(scene, cameraPY);
|
|
renderer.setRenderTarget(renderTarget, 3);
|
|
renderer.render(scene, cameraNY);
|
|
renderer.setRenderTarget(renderTarget, 4);
|
|
renderer.render(scene, cameraPZ);
|
|
renderTarget.texture.generateMipmaps = generateMipmaps;
|
|
renderer.setRenderTarget(renderTarget, 5);
|
|
renderer.render(scene, cameraNZ);
|
|
renderer.setRenderTarget(currentRenderTarget);
|
|
renderer.xr.enabled = currentXrEnabled;
|
|
}
|
|
};
|
|
var CubeTexture = class extends Texture {
|
|
constructor(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
|
|
images = images !== void 0 ? images : [];
|
|
mapping = mapping !== void 0 ? mapping : CubeReflectionMapping;
|
|
format = format !== void 0 ? format : RGBFormat;
|
|
super(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
|
|
this.flipY = false;
|
|
}
|
|
get images() {
|
|
return this.image;
|
|
}
|
|
set images(value) {
|
|
this.image = value;
|
|
}
|
|
};
|
|
CubeTexture.prototype.isCubeTexture = true;
|
|
var WebGLCubeRenderTarget = class extends WebGLRenderTarget {
|
|
constructor(size, options, dummy) {
|
|
if (Number.isInteger(options)) {
|
|
console.warn("THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )");
|
|
options = dummy;
|
|
}
|
|
super(size, size, options);
|
|
options = options || {};
|
|
this.texture = new CubeTexture(void 0, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
|
|
this.texture.isRenderTargetTexture = true;
|
|
this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false;
|
|
this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter;
|
|
this.texture._needsFlipEnvMap = false;
|
|
}
|
|
fromEquirectangularTexture(renderer, texture) {
|
|
this.texture.type = texture.type;
|
|
this.texture.format = RGBAFormat;
|
|
this.texture.encoding = texture.encoding;
|
|
this.texture.generateMipmaps = texture.generateMipmaps;
|
|
this.texture.minFilter = texture.minFilter;
|
|
this.texture.magFilter = texture.magFilter;
|
|
const shader = {
|
|
uniforms: {
|
|
tEquirect: { value: null }
|
|
},
|
|
vertexShader: `
|
|
|
|
varying vec3 vWorldDirection;
|
|
|
|
vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
|
|
|
|
return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
|
|
|
|
}
|
|
|
|
void main() {
|
|
|
|
vWorldDirection = transformDirection( position, modelMatrix );
|
|
|
|
#include <begin_vertex>
|
|
#include <project_vertex>
|
|
|
|
}
|
|
`,
|
|
fragmentShader: `
|
|
|
|
uniform sampler2D tEquirect;
|
|
|
|
varying vec3 vWorldDirection;
|
|
|
|
#include <common>
|
|
|
|
void main() {
|
|
|
|
vec3 direction = normalize( vWorldDirection );
|
|
|
|
vec2 sampleUV = equirectUv( direction );
|
|
|
|
gl_FragColor = texture2D( tEquirect, sampleUV );
|
|
|
|
}
|
|
`
|
|
};
|
|
const geometry = new BoxGeometry(5, 5, 5);
|
|
const material = new ShaderMaterial({
|
|
name: "CubemapFromEquirect",
|
|
uniforms: cloneUniforms(shader.uniforms),
|
|
vertexShader: shader.vertexShader,
|
|
fragmentShader: shader.fragmentShader,
|
|
side: BackSide,
|
|
blending: NoBlending
|
|
});
|
|
material.uniforms.tEquirect.value = texture;
|
|
const mesh = new Mesh(geometry, material);
|
|
const currentMinFilter = texture.minFilter;
|
|
if (texture.minFilter === LinearMipmapLinearFilter)
|
|
texture.minFilter = LinearFilter;
|
|
const camera = new CubeCamera(1, 10, this);
|
|
camera.update(renderer, mesh);
|
|
texture.minFilter = currentMinFilter;
|
|
mesh.geometry.dispose();
|
|
mesh.material.dispose();
|
|
return this;
|
|
}
|
|
clear(renderer, color, depth, stencil) {
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
for (let i = 0; i < 6; i++) {
|
|
renderer.setRenderTarget(this, i);
|
|
renderer.clear(color, depth, stencil);
|
|
}
|
|
renderer.setRenderTarget(currentRenderTarget);
|
|
}
|
|
};
|
|
WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
|
|
var _vector1 = /* @__PURE__ */ new Vector3();
|
|
var _vector2 = /* @__PURE__ */ new Vector3();
|
|
var _normalMatrix = /* @__PURE__ */ new Matrix3();
|
|
var Plane = class {
|
|
constructor(normal = new Vector3(1, 0, 0), constant = 0) {
|
|
this.normal = normal;
|
|
this.constant = constant;
|
|
}
|
|
set(normal, constant) {
|
|
this.normal.copy(normal);
|
|
this.constant = constant;
|
|
return this;
|
|
}
|
|
setComponents(x, y, z, w2) {
|
|
this.normal.set(x, y, z);
|
|
this.constant = w2;
|
|
return this;
|
|
}
|
|
setFromNormalAndCoplanarPoint(normal, point) {
|
|
this.normal.copy(normal);
|
|
this.constant = -point.dot(this.normal);
|
|
return this;
|
|
}
|
|
setFromCoplanarPoints(a2, b2, c2) {
|
|
const normal = _vector1.subVectors(c2, b2).cross(_vector2.subVectors(a2, b2)).normalize();
|
|
this.setFromNormalAndCoplanarPoint(normal, a2);
|
|
return this;
|
|
}
|
|
copy(plane) {
|
|
this.normal.copy(plane.normal);
|
|
this.constant = plane.constant;
|
|
return this;
|
|
}
|
|
normalize() {
|
|
const inverseNormalLength = 1 / this.normal.length();
|
|
this.normal.multiplyScalar(inverseNormalLength);
|
|
this.constant *= inverseNormalLength;
|
|
return this;
|
|
}
|
|
negate() {
|
|
this.constant *= -1;
|
|
this.normal.negate();
|
|
return this;
|
|
}
|
|
distanceToPoint(point) {
|
|
return this.normal.dot(point) + this.constant;
|
|
}
|
|
distanceToSphere(sphere) {
|
|
return this.distanceToPoint(sphere.center) - sphere.radius;
|
|
}
|
|
projectPoint(point, target) {
|
|
return target.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point);
|
|
}
|
|
intersectLine(line, target) {
|
|
const direction = line.delta(_vector1);
|
|
const denominator = this.normal.dot(direction);
|
|
if (denominator === 0) {
|
|
if (this.distanceToPoint(line.start) === 0) {
|
|
return target.copy(line.start);
|
|
}
|
|
return null;
|
|
}
|
|
const t = -(line.start.dot(this.normal) + this.constant) / denominator;
|
|
if (t < 0 || t > 1) {
|
|
return null;
|
|
}
|
|
return target.copy(direction).multiplyScalar(t).add(line.start);
|
|
}
|
|
intersectsLine(line) {
|
|
const startSign = this.distanceToPoint(line.start);
|
|
const endSign = this.distanceToPoint(line.end);
|
|
return startSign < 0 && endSign > 0 || endSign < 0 && startSign > 0;
|
|
}
|
|
intersectsBox(box) {
|
|
return box.intersectsPlane(this);
|
|
}
|
|
intersectsSphere(sphere) {
|
|
return sphere.intersectsPlane(this);
|
|
}
|
|
coplanarPoint(target) {
|
|
return target.copy(this.normal).multiplyScalar(-this.constant);
|
|
}
|
|
applyMatrix4(matrix, optionalNormalMatrix) {
|
|
const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix(matrix);
|
|
const referencePoint = this.coplanarPoint(_vector1).applyMatrix4(matrix);
|
|
const normal = this.normal.applyMatrix3(normalMatrix).normalize();
|
|
this.constant = -referencePoint.dot(normal);
|
|
return this;
|
|
}
|
|
translate(offset) {
|
|
this.constant -= offset.dot(this.normal);
|
|
return this;
|
|
}
|
|
equals(plane) {
|
|
return plane.normal.equals(this.normal) && plane.constant === this.constant;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
Plane.prototype.isPlane = true;
|
|
var _sphere$2 = /* @__PURE__ */ new Sphere();
|
|
var _vector$7 = /* @__PURE__ */ new Vector3();
|
|
var Frustum = class {
|
|
constructor(p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane()) {
|
|
this.planes = [p0, p1, p2, p3, p4, p5];
|
|
}
|
|
set(p0, p1, p2, p3, p4, p5) {
|
|
const planes = this.planes;
|
|
planes[0].copy(p0);
|
|
planes[1].copy(p1);
|
|
planes[2].copy(p2);
|
|
planes[3].copy(p3);
|
|
planes[4].copy(p4);
|
|
planes[5].copy(p5);
|
|
return this;
|
|
}
|
|
copy(frustum) {
|
|
const planes = this.planes;
|
|
for (let i = 0; i < 6; i++) {
|
|
planes[i].copy(frustum.planes[i]);
|
|
}
|
|
return this;
|
|
}
|
|
setFromProjectionMatrix(m) {
|
|
const planes = this.planes;
|
|
const me = m.elements;
|
|
const me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
|
|
const me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
|
|
const me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
|
|
const me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
|
|
planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize();
|
|
planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize();
|
|
planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize();
|
|
planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize();
|
|
planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize();
|
|
planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize();
|
|
return this;
|
|
}
|
|
intersectsObject(object) {
|
|
const geometry = object.geometry;
|
|
if (geometry.boundingSphere === null)
|
|
geometry.computeBoundingSphere();
|
|
_sphere$2.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
|
|
return this.intersectsSphere(_sphere$2);
|
|
}
|
|
intersectsSprite(sprite) {
|
|
_sphere$2.center.set(0, 0, 0);
|
|
_sphere$2.radius = 0.7071067811865476;
|
|
_sphere$2.applyMatrix4(sprite.matrixWorld);
|
|
return this.intersectsSphere(_sphere$2);
|
|
}
|
|
intersectsSphere(sphere) {
|
|
const planes = this.planes;
|
|
const center = sphere.center;
|
|
const negRadius = -sphere.radius;
|
|
for (let i = 0; i < 6; i++) {
|
|
const distance = planes[i].distanceToPoint(center);
|
|
if (distance < negRadius) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
intersectsBox(box) {
|
|
const planes = this.planes;
|
|
for (let i = 0; i < 6; i++) {
|
|
const plane = planes[i];
|
|
_vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
|
|
_vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
|
|
_vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
|
|
if (plane.distanceToPoint(_vector$7) < 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
containsPoint(point) {
|
|
const planes = this.planes;
|
|
for (let i = 0; i < 6; i++) {
|
|
if (planes[i].distanceToPoint(point) < 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
function WebGLAnimation() {
|
|
let context = null;
|
|
let isAnimating = false;
|
|
let animationLoop = null;
|
|
let requestId = null;
|
|
function onAnimationFrame(time, frame) {
|
|
animationLoop(time, frame);
|
|
requestId = context.requestAnimationFrame(onAnimationFrame);
|
|
}
|
|
return {
|
|
start: function() {
|
|
if (isAnimating === true)
|
|
return;
|
|
if (animationLoop === null)
|
|
return;
|
|
requestId = context.requestAnimationFrame(onAnimationFrame);
|
|
isAnimating = true;
|
|
},
|
|
stop: function() {
|
|
context.cancelAnimationFrame(requestId);
|
|
isAnimating = false;
|
|
},
|
|
setAnimationLoop: function(callback) {
|
|
animationLoop = callback;
|
|
},
|
|
setContext: function(value) {
|
|
context = value;
|
|
}
|
|
};
|
|
}
|
|
function WebGLAttributes(gl, capabilities) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
const buffers = new WeakMap();
|
|
function createBuffer(attribute, bufferType) {
|
|
const array = attribute.array;
|
|
const usage = attribute.usage;
|
|
const buffer = gl.createBuffer();
|
|
gl.bindBuffer(bufferType, buffer);
|
|
gl.bufferData(bufferType, array, usage);
|
|
attribute.onUploadCallback();
|
|
let type = 5126;
|
|
if (array instanceof Float32Array) {
|
|
type = 5126;
|
|
} else if (array instanceof Float64Array) {
|
|
console.warn("THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.");
|
|
} else if (array instanceof Uint16Array) {
|
|
if (attribute.isFloat16BufferAttribute) {
|
|
if (isWebGL2) {
|
|
type = 5131;
|
|
} else {
|
|
console.warn("THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.");
|
|
}
|
|
} else {
|
|
type = 5123;
|
|
}
|
|
} else if (array instanceof Int16Array) {
|
|
type = 5122;
|
|
} else if (array instanceof Uint32Array) {
|
|
type = 5125;
|
|
} else if (array instanceof Int32Array) {
|
|
type = 5124;
|
|
} else if (array instanceof Int8Array) {
|
|
type = 5120;
|
|
} else if (array instanceof Uint8Array) {
|
|
type = 5121;
|
|
} else if (array instanceof Uint8ClampedArray) {
|
|
type = 5121;
|
|
}
|
|
return {
|
|
buffer,
|
|
type,
|
|
bytesPerElement: array.BYTES_PER_ELEMENT,
|
|
version: attribute.version
|
|
};
|
|
}
|
|
function updateBuffer(buffer, attribute, bufferType) {
|
|
const array = attribute.array;
|
|
const updateRange = attribute.updateRange;
|
|
gl.bindBuffer(bufferType, buffer);
|
|
if (updateRange.count === -1) {
|
|
gl.bufferSubData(bufferType, 0, array);
|
|
} else {
|
|
if (isWebGL2) {
|
|
gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, array, updateRange.offset, updateRange.count);
|
|
} else {
|
|
gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, array.subarray(updateRange.offset, updateRange.offset + updateRange.count));
|
|
}
|
|
updateRange.count = -1;
|
|
}
|
|
}
|
|
function get(attribute) {
|
|
if (attribute.isInterleavedBufferAttribute)
|
|
attribute = attribute.data;
|
|
return buffers.get(attribute);
|
|
}
|
|
function remove(attribute) {
|
|
if (attribute.isInterleavedBufferAttribute)
|
|
attribute = attribute.data;
|
|
const data = buffers.get(attribute);
|
|
if (data) {
|
|
gl.deleteBuffer(data.buffer);
|
|
buffers.delete(attribute);
|
|
}
|
|
}
|
|
function update(attribute, bufferType) {
|
|
if (attribute.isGLBufferAttribute) {
|
|
const cached = buffers.get(attribute);
|
|
if (!cached || cached.version < attribute.version) {
|
|
buffers.set(attribute, {
|
|
buffer: attribute.buffer,
|
|
type: attribute.type,
|
|
bytesPerElement: attribute.elementSize,
|
|
version: attribute.version
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
if (attribute.isInterleavedBufferAttribute)
|
|
attribute = attribute.data;
|
|
const data = buffers.get(attribute);
|
|
if (data === void 0) {
|
|
buffers.set(attribute, createBuffer(attribute, bufferType));
|
|
} else if (data.version < attribute.version) {
|
|
updateBuffer(data.buffer, attribute, bufferType);
|
|
data.version = attribute.version;
|
|
}
|
|
}
|
|
return {
|
|
get,
|
|
remove,
|
|
update
|
|
};
|
|
}
|
|
var PlaneGeometry = class extends BufferGeometry {
|
|
constructor(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
|
|
super();
|
|
this.type = "PlaneGeometry";
|
|
this.parameters = {
|
|
width,
|
|
height,
|
|
widthSegments,
|
|
heightSegments
|
|
};
|
|
const width_half = width / 2;
|
|
const height_half = height / 2;
|
|
const gridX = Math.floor(widthSegments);
|
|
const gridY = Math.floor(heightSegments);
|
|
const gridX1 = gridX + 1;
|
|
const gridY1 = gridY + 1;
|
|
const segment_width = width / gridX;
|
|
const segment_height = height / gridY;
|
|
const indices = [];
|
|
const vertices = [];
|
|
const normals = [];
|
|
const uvs = [];
|
|
for (let iy = 0; iy < gridY1; iy++) {
|
|
const y = iy * segment_height - height_half;
|
|
for (let ix = 0; ix < gridX1; ix++) {
|
|
const x = ix * segment_width - width_half;
|
|
vertices.push(x, -y, 0);
|
|
normals.push(0, 0, 1);
|
|
uvs.push(ix / gridX);
|
|
uvs.push(1 - iy / gridY);
|
|
}
|
|
}
|
|
for (let iy = 0; iy < gridY; iy++) {
|
|
for (let ix = 0; ix < gridX; ix++) {
|
|
const a2 = ix + gridX1 * iy;
|
|
const b2 = ix + gridX1 * (iy + 1);
|
|
const c2 = ix + 1 + gridX1 * (iy + 1);
|
|
const d = ix + 1 + gridX1 * iy;
|
|
indices.push(a2, b2, d);
|
|
indices.push(b2, c2, d);
|
|
}
|
|
}
|
|
this.setIndex(indices);
|
|
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
|
|
this.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
}
|
|
static fromJSON(data) {
|
|
return new PlaneGeometry(data.width, data.height, data.widthSegments, data.heightSegments);
|
|
}
|
|
};
|
|
var alphamap_fragment = "#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
|
|
var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif";
|
|
var alphatest_fragment = "#ifdef USE_ALPHATEST\n if ( diffuseColor.a < alphaTest ) discard;\n#endif";
|
|
var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n uniform float alphaTest;\n#endif";
|
|
var aomap_fragment = "#ifdef USE_AOMAP\n float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n reflectedLight.indirectDiffuse *= ambientOcclusion;\n #if defined( USE_ENVMAP ) && defined( STANDARD )\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n #endif\n#endif";
|
|
var aomap_pars_fragment = "#ifdef USE_AOMAP\n uniform sampler2D aoMap;\n uniform float aoMapIntensity;\n#endif";
|
|
var begin_vertex = "vec3 transformed = vec3( position );";
|
|
var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n vec3 objectTangent = vec3( tangent.xyz );\n#endif";
|
|
var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n float a2 = pow2( alpha );\n float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n float a2 = pow2( alpha );\n float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( incidentLight.direction + viewDir );\n float dotNL = saturate( dot( normal, incidentLight.direction ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = F_Schlick( f0, f90, dotVH );\n float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n const float LUT_SIZE = 64.0;\n const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n const float LUT_BIAS = 0.5 / LUT_SIZE;\n float dotNV = saturate( dot( N, V ) );\n vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n uv = uv * LUT_SCALE + LUT_BIAS;\n return uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n float l = length( f );\n return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n float x = dot( v1, v2 );\n float y = abs( x );\n float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n float b = 3.4175940 + ( 4.1616724 + y ) * y;\n float v = a / b;\n float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n return cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n vec3 lightNormal = cross( v1, v2 );\n if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n vec3 T1, T2;\n T1 = normalize( V - N * dot( V, N ) );\n T2 = - cross( N, T1 );\n mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n vec3 coords[ 4 ];\n coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n coords[ 0 ] = normalize( coords[ 0 ] );\n coords[ 1 ] = normalize( coords[ 1 ] );\n coords[ 2 ] = normalize( coords[ 2 ] );\n coords[ 3 ] = normalize( coords[ 3 ] );\n vec3 vectorFormFactor = vec3( 0.0 );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n float result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n return vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n float dotNH = saturate( dot( geometry.normal, halfDir ) );\n float dotVH = saturate( dot( geometry.viewDir, halfDir ) );\n vec3 F = F_Schlick( specularColor, 1.0, dotVH );\n float G = G_BlinnPhong_Implicit( );\n float D = D_BlinnPhong( shininess, dotNH );\n return F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float NoH ) {\n float invAlpha = 1.0 / roughness;\n float cos2h = NoH * NoH;\n float sin2h = max( 1.0 - cos2h, 0.0078125 );\n return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float NoV, float NoL ) {\n return saturate( 1.0 / ( 4.0 * ( NoL + NoV - NoL * NoV ) ) );\n}\nvec3 BRDF_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n vec3 N = geometry.normal;\n vec3 V = geometry.viewDir;\n vec3 H = normalize( V + L );\n float dotNH = saturate( dot( N, H ) );\n return specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif";
|
|
var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n vec2 dHdxy_fwd() {\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n return vec2( dBx, dBy );\n }\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n vec3 vN = surf_norm;\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n float fDet = dot( vSigmaX, R1 ) * faceDirection;\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n }\n#endif";
|
|
var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n vec4 plane;\n #pragma unroll_loop_start\n for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n }\n #pragma unroll_loop_end\n #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n bool clipped = true;\n #pragma unroll_loop_start\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n }\n #pragma unroll_loop_end\n if ( clipped ) discard;\n #endif\n#endif";
|
|
var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
|
|
var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n#endif";
|
|
var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n vClipPosition = - mvPosition.xyz;\n#endif";
|
|
var color_fragment = "#if defined( USE_COLOR_ALPHA )\n diffuseColor *= vColor;\n#elif defined( USE_COLOR )\n diffuseColor.rgb *= vColor;\n#endif";
|
|
var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR )\n varying vec3 vColor;\n#endif";
|
|
var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n varying vec3 vColor;\n#endif";
|
|
var color_vertex = "#if defined( USE_COLOR_ALPHA )\n vColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n vColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n vColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n vColor.xyz *= instanceColor.xyz;\n#endif";
|
|
var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n return fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n float precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n float precisionSafeLength( vec3 v ) {\n float maxComponent = max3( abs( v ) );\n return length( v / maxComponent ) * maxComponent;\n }\n#endif\nstruct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n};\nstruct ReflectedLight {\n vec3 directDiffuse;\n vec3 directSpecular;\n vec3 indirectDiffuse;\n vec3 indirectSpecular;\n};\nstruct GeometricContext {\n vec3 position;\n vec3 normal;\n vec3 viewDir;\n#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n mat3 tmp;\n tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n return tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n vec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n return dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n return vec2( u, v );\n}";
|
|
var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n #define cubeUV_maxMipLevel 8.0\n #define cubeUV_minMipLevel 4.0\n #define cubeUV_maxTileSize 256.0\n #define cubeUV_minTileSize 16.0\n float getFace( vec3 direction ) {\n vec3 absDirection = abs( direction );\n float face = - 1.0;\n if ( absDirection.x > absDirection.z ) {\n if ( absDirection.x > absDirection.y )\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if ( absDirection.z > absDirection.y )\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n }\n vec2 getUV( vec3 direction, float face ) {\n vec2 uv;\n if ( face == 0.0 ) {\n uv = vec2( direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 1.0 ) {\n uv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n } else if ( face == 2.0 ) {\n uv = vec2( - direction.x, direction.y ) / abs( direction.z );\n } else if ( face == 3.0 ) {\n uv = vec2( - direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 4.0 ) {\n uv = vec2( - direction.x, direction.z ) / abs( direction.y );\n } else {\n uv = vec2( direction.x, direction.y ) / abs( direction.z );\n }\n return 0.5 * ( uv + 1.0 );\n }\n vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n float face = getFace( direction );\n float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n mipInt = max( mipInt, cubeUV_minMipLevel );\n float faceSize = exp2( mipInt );\n float texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n vec2 f = fract( uv );\n uv += 0.5 - f;\n if ( face > 2.0 ) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n if ( mipInt < cubeUV_maxMipLevel ) {\n uv.y += 2.0 * cubeUV_maxTileSize;\n }\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n uv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n uv *= texelSize;\n vec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n uv.x += texelSize;\n vec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n uv.y += texelSize;\n vec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n uv.x -= texelSize;\n vec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n vec3 tm = mix( tl, tr, f.x );\n vec3 bm = mix( bl, br, f.x );\n return mix( tm, bm, f.y );\n }\n #define r0 1.0\n #define v0 0.339\n #define m0 - 2.0\n #define r1 0.8\n #define v1 0.276\n #define m1 - 1.0\n #define r4 0.4\n #define v4 0.046\n #define m4 2.0\n #define r5 0.305\n #define v5 0.016\n #define m5 3.0\n #define r6 0.21\n #define v6 0.0038\n #define m6 4.0\n float roughnessToMip( float roughness ) {\n float mip = 0.0;\n if ( roughness >= r1 ) {\n mip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n } else if ( roughness >= r4 ) {\n mip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n } else if ( roughness >= r5 ) {\n mip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n } else if ( roughness >= r6 ) {\n mip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n } else {\n mip = - 2.0 * log2( 1.16 * roughness ); }\n return mip;\n }\n vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n float mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n float mipF = fract( mip );\n float mipInt = floor( mip );\n vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n if ( mipF == 0.0 ) {\n return vec4( color0, 1.0 );\n } else {\n vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n return vec4( mix( color0, color1, mipF ), 1.0 );\n }\n }\n#endif";
|
|
var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n mat3 m = mat3( instanceMatrix );\n transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n transformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n transformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #ifdef FLIP_SIDED\n transformedTangent = - transformedTangent;\n #endif\n#endif";
|
|
var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n uniform sampler2D displacementMap;\n uniform float displacementScale;\n uniform float displacementBias;\n#endif";
|
|
var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
|
|
var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n vec4 emissiveColor = texture2D( emissiveMap, vUv );\n emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n totalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
|
|
var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n uniform sampler2D emissiveMap;\n#endif";
|
|
var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
|
|
var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n return value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n return vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n return vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n float maxComponent = max( max( value.r, value.g ), value.b );\n float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n return vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n float maxRGB = max( value.r, max( value.g, value.b ) );\n float M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n M = ceil( M * 255.0 ) / 255.0;\n return vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n float maxRGB = max( value.r, max( value.g, value.b ) );\n float D = max( maxRange / maxRGB, 1.0 );\n D = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n vec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n Xp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n vec4 vResult;\n vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n vResult.w = fract( Le );\n vResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n return vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n float Le = value.z * 255.0 + value.w;\n vec3 Xp_Y_XYZp;\n Xp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n return vec4( max( vRGB, 0.0 ), 1.0 );\n}";
|
|
var envmap_fragment = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vec3 cameraToFrag;\n if ( isOrthographic ) {\n cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToFrag = normalize( vWorldPosition - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vec3 reflectVec = reflect( cameraToFrag, worldNormal );\n #else\n vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n #endif\n #else\n vec3 reflectVec = vReflect;\n #endif\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n envColor = envMapTexelToLinear( envColor );\n #elif defined( ENVMAP_TYPE_CUBE_UV )\n vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n #else\n vec4 envColor = vec4( 0.0 );\n #endif\n #ifdef ENVMAP_BLENDING_MULTIPLY\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_MIX )\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_ADD )\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n #endif\n#endif";
|
|
var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n uniform float envMapIntensity;\n uniform float flipEnvMap;\n uniform int maxMipLevel;\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n \n#endif";
|
|
var envmap_pars_fragment = "#ifdef USE_ENVMAP\n uniform float reflectivity;\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n varying vec3 vWorldPosition;\n uniform float refractionRatio;\n #else\n varying vec3 vReflect;\n #endif\n#endif";
|
|
var envmap_pars_vertex = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n \n varying vec3 vWorldPosition;\n #else\n varying vec3 vReflect;\n uniform float refractionRatio;\n #endif\n#endif";
|
|
var envmap_vertex = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vWorldPosition = worldPosition.xyz;\n #else\n vec3 cameraToVertex;\n if ( isOrthographic ) {\n cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vReflect = reflect( cameraToVertex, worldNormal );\n #else\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n #endif\n #endif\n#endif";
|
|
var fog_vertex = "#ifdef USE_FOG\n vFogDepth = - mvPosition.z;\n#endif";
|
|
var fog_pars_vertex = "#ifdef USE_FOG\n varying float vFogDepth;\n#endif";
|
|
var fog_fragment = "#ifdef USE_FOG\n #ifdef FOG_EXP2\n float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n #else\n float fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n #endif\n gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
|
|
var fog_pars_fragment = "#ifdef USE_FOG\n uniform vec3 fogColor;\n varying float vFogDepth;\n #ifdef FOG_EXP2\n uniform float fogDensity;\n #else\n uniform float fogNear;\n uniform float fogFar;\n #endif\n#endif";
|
|
var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n uniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n float dotNL = dot( normal, lightDirection );\n vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n #ifdef USE_GRADIENTMAP\n return texture2D( gradientMap, coord ).rgb;\n #else\n return ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n #endif\n}";
|
|
var lightmap_fragment = "#ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n lightMapIrradiance *= PI;\n #endif\n reflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
|
|
var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n uniform sampler2D lightMap;\n uniform float lightMapIntensity;\n#endif";
|
|
var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n vLightBack = vec3( 0.0 );\n vIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n vIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n vIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n getPointLightInfo( pointLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n getSpotLightInfo( spotLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n getDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n vIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n #ifdef DOUBLE_SIDED\n vIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n #endif\n }\n #pragma unroll_loop_end\n#endif";
|
|
var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n float x = normal.x, y = normal.y, z = normal.z;\n vec3 result = shCoefficients[ 0 ] * 0.886227;\n result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n return result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n return irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n vec3 irradiance = ambientLightColor;\n return irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n #if defined ( PHYSICALLY_CORRECT_LIGHTS )\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n if ( cutoffDistance > 0.0 ) {\n distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n }\n return distanceFalloff;\n #else\n if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n }\n return 1.0;\n #endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n return smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n struct DirectionalLight {\n vec3 direction;\n vec3 color;\n };\n uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n void getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n light.color = directionalLight.color;\n light.direction = directionalLight.direction;\n light.visible = true;\n }\n#endif\n#if NUM_POINT_LIGHTS > 0\n struct PointLight {\n vec3 position;\n vec3 color;\n float distance;\n float decay;\n };\n uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = pointLight.position - geometry.position;\n light.direction = normalize( lVector );\n float lightDistance = length( lVector );\n light.color = pointLight.color;\n light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n }\n#endif\n#if NUM_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n };\n uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = spotLight.position - geometry.position;\n light.direction = normalize( lVector );\n float angleCos = dot( light.direction, spotLight.direction );\n float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n if ( spotAttenuation > 0.0 ) {\n float lightDistance = length( lVector );\n light.color = spotLight.color * spotAttenuation;\n light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n } else {\n light.color = vec3( 0.0 );\n light.visible = false;\n }\n }\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n struct RectAreaLight {\n vec3 color;\n vec3 position;\n vec3 halfWidth;\n vec3 halfHeight;\n };\n uniform sampler2D ltc_1; uniform sampler2D ltc_2;\n uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n struct HemisphereLight {\n vec3 direction;\n vec3 skyColor;\n vec3 groundColor;\n };\n uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n float dotNL = dot( geometry.normal, hemiLight.direction );\n float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n return irradiance;\n }\n#endif";
|
|
var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n #ifdef ENVMAP_MODE_REFRACTION\n uniform float refractionRatio;\n #endif\n vec3 getIBLIrradiance( const in GeometricContext geometry ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n return PI * envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 reflectVec;\n #ifdef ENVMAP_MODE_REFLECTION\n reflectVec = reflect( - viewDir, normal );\n reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n #else\n reflectVec = refract( - viewDir, normal, refractionRatio );\n #endif\n reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n return envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n#endif";
|
|
var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
|
|
var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n vec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_Toon\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material ) (0)";
|
|
var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
|
|
var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n vec3 diffuseColor;\n vec3 specularColor;\n float specularShininess;\n float specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material ) (0)";
|
|
var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n #ifdef SPECULAR\n float specularIntensityFactor = specularIntensity;\n vec3 specularTintFactor = specularTint;\n #ifdef USE_SPECULARINTENSITYMAP\n specularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n #endif\n #ifdef USE_SPECULARTINTMAP\n specularTintFactor *= specularTintMapTexelToLinear( texture2D( specularTintMap, vUv ) ).rgb;\n #endif\n material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n #else\n float specularIntensityFactor = 1.0;\n vec3 specularTintFactor = vec3( 1.0 );\n material.specularF90 = 1.0;\n #endif\n material.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularTintFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n material.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n material.clearcoat = clearcoat;\n material.clearcoatRoughness = clearcoatRoughness;\n material.clearcoatF0 = vec3( 0.04 );\n material.clearcoatF90 = 1.0;\n #ifdef USE_CLEARCOATMAP\n material.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n #endif\n #ifdef USE_CLEARCOAT_ROUGHNESSMAP\n material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n #endif\n material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n material.clearcoatRoughness += geometryRoughness;\n material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n material.sheenTint = sheenTint;\n#endif";
|
|
var lights_physical_pars_fragment = "struct PhysicalMaterial {\n vec3 diffuseColor;\n float roughness;\n vec3 specularColor;\n float specularF90;\n #ifdef USE_CLEARCOAT\n float clearcoat;\n float clearcoatRoughness;\n vec3 clearcoatF0;\n float clearcoatF90;\n #endif\n #ifdef USE_SHEEN\n vec3 sheenTint;\n #endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n float dotNV = saturate( dot( normal, viewDir ) );\n const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n vec4 r = roughness * c0 + c1;\n float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n return fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n return specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n vec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n float Ess = fab.x + fab.y;\n float Ems = 1.0 - Ess;\n vec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n singleScatter += FssEss;\n multiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 normal = geometry.normal;\n vec3 viewDir = geometry.viewDir;\n vec3 position = geometry.position;\n vec3 lightPos = rectAreaLight.position;\n vec3 halfWidth = rectAreaLight.halfWidth;\n vec3 halfHeight = rectAreaLight.halfHeight;\n vec3 lightColor = rectAreaLight.color;\n float roughness = material.roughness;\n vec3 rectCoords[ 4 ];\n rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n rectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n rectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n vec2 uv = LTC_Uv( normal, viewDir, roughness );\n vec4 t1 = texture2D( ltc_1, uv );\n vec4 t2 = texture2D( ltc_2, uv );\n mat3 mInv = mat3(\n vec3( t1.x, 0, t1.y ),\n vec3( 0, 1, 0 ),\n vec3( t1.z, 0, t1.w )\n );\n vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n }\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n #ifdef USE_CLEARCOAT\n float dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n vec3 ccIrradiance = dotNLcc * directLight.color;\n clearcoatSpecular += ccIrradiance * BRDF_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n #ifdef USE_SHEEN\n reflectedLight.directSpecular += irradiance * BRDF_Sheen( material.roughness, directLight.direction, geometry, material.sheenTint );\n #else\n reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n #endif\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n #ifdef USE_CLEARCOAT\n clearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n vec3 singleScattering = vec3( 0.0 );\n vec3 multiScattering = vec3( 0.0 );\n vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n computeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n vec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n reflectedLight.indirectSpecular += radiance * singleScattering;\n reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct RE_Direct_Physical\n#define RE_Direct_RectArea RE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular RE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
|
|
var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n geometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n PointLight pointLight;\n #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n getPointLightInfo( pointLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n pointLightShadow = pointLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n SpotLight spotLight;\n #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n spotLight = spotLights[ i ];\n getSpotLightInfo( spotLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n spotLightShadow = spotLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n DirectionalLight directionalLight;\n #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n directionalLight = directionalLights[ i ];\n getDirectionalLightInfo( directionalLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n directionalLightShadow = directionalLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n RectAreaLight rectAreaLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n rectAreaLight = rectAreaLights[ i ];\n RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n vec3 iblIrradiance = vec3( 0.0 );\n vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n irradiance += getLightProbeIrradiance( lightProbe, geometry );\n #if ( NUM_HEMI_LIGHTS > 0 )\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n }\n #pragma unroll_loop_end\n #endif\n#endif\n#if defined( RE_IndirectSpecular )\n vec3 radiance = vec3( 0.0 );\n vec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
|
|
var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n lightMapIrradiance *= PI;\n #endif\n irradiance += lightMapIrradiance;\n #endif\n #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n iblIrradiance += getIBLIrradiance( geometry );\n #endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n radiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n #ifdef USE_CLEARCOAT\n clearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n #endif\n#endif";
|
|
var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif";
|
|
var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n gl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
|
|
var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n uniform float logDepthBufFC;\n varying float vFragDepth;\n varying float vIsPerspective;\n#endif";
|
|
var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n varying float vFragDepth;\n varying float vIsPerspective;\n #else\n uniform float logDepthBufFC;\n #endif\n#endif";
|
|
var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n vFragDepth = 1.0 + gl_Position.w;\n vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n #else\n if ( isPerspectiveMatrix( projectionMatrix ) ) {\n gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n gl_Position.z *= gl_Position.w;\n }\n #endif\n#endif";
|
|
var map_fragment = "#ifdef USE_MAP\n vec4 texelColor = texture2D( map, vUv );\n texelColor = mapTexelToLinear( texelColor );\n diffuseColor *= texelColor;\n#endif";
|
|
var map_pars_fragment = "#ifdef USE_MAP\n uniform sampler2D map;\n#endif";
|
|
var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n vec4 mapTexel = texture2D( map, uv );\n diffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
|
|
var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n uniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n uniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif";
|
|
var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n vec4 texelMetalness = texture2D( metalnessMap, vUv );\n metalnessFactor *= texelMetalness.b;\n#endif";
|
|
var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n uniform sampler2D metalnessMap;\n#endif";
|
|
var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n objectNormal *= morphTargetBaseInfluence;\n objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
|
|
var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n uniform float morphTargetBaseInfluence;\n #ifndef USE_MORPHNORMALS\n uniform float morphTargetInfluences[ 8 ];\n #else\n uniform float morphTargetInfluences[ 4 ];\n #endif\n#endif";
|
|
var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n transformed *= morphTargetBaseInfluence;\n transformed += morphTarget0 * morphTargetInfluences[ 0 ];\n transformed += morphTarget1 * morphTargetInfluences[ 1 ];\n transformed += morphTarget2 * morphTargetInfluences[ 2 ];\n transformed += morphTarget3 * morphTargetInfluences[ 3 ];\n #ifndef USE_MORPHNORMALS\n transformed += morphTarget4 * morphTargetInfluences[ 4 ];\n transformed += morphTarget5 * morphTargetInfluences[ 5 ];\n transformed += morphTarget6 * morphTargetInfluences[ 6 ];\n transformed += morphTarget7 * morphTargetInfluences[ 7 ];\n #endif\n#endif";
|
|
var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n vec3 normal = normalize( vNormal );\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n #ifdef USE_TANGENT\n vec3 tangent = normalize( vTangent );\n vec3 bitangent = normalize( vBitangent );\n #ifdef DOUBLE_SIDED\n tangent = tangent * faceDirection;\n bitangent = bitangent * faceDirection;\n #endif\n #if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n mat3 vTBN = mat3( tangent, bitangent, normal );\n #endif\n #endif\n#endif\nvec3 geometryNormal = normal;";
|
|
var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n #ifdef FLIP_SIDED\n normal = - normal;\n #endif\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n normal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy *= normalScale;\n #ifdef USE_TANGENT\n normal = normalize( vTBN * mapN );\n #else\n normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n #endif\n#elif defined( USE_BUMPMAP )\n normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
|
|
var normal_pars_fragment = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif";
|
|
var normal_pars_vertex = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif";
|
|
var normal_vertex = "#ifndef FLAT_SHADED\n vNormal = normalize( transformedNormal );\n #ifdef USE_TANGENT\n vTangent = normalize( transformedTangent );\n vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n #endif\n#endif";
|
|
var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n uniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n vec3 N = surf_norm;\n vec3 q1perp = cross( q1, N );\n vec3 q0perp = cross( N, q0 );\n vec3 T = q1perp * st0.x + q0perp * st1.x;\n vec3 B = q1perp * st0.y + q0perp * st1.y;\n float det = max( dot( T, T ), dot( B, B ) );\n float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n }\n#endif";
|
|
var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal = geometryNormal;\n#endif";
|
|
var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n clearcoatMapN.xy *= clearcoatNormalScale;\n #ifdef USE_TANGENT\n clearcoatNormal = normalize( vTBN * clearcoatMapN );\n #else\n clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n #endif\n#endif";
|
|
var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n uniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n uniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n uniform sampler2D clearcoatNormalMap;\n uniform vec2 clearcoatNormalScale;\n#endif";
|
|
var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
|
|
var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n return 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n vec4 r = vec4( fract( v * PackFactors ), v );\n r.yzw -= r.xyz * ShiftRight8; return r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n return dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n return ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}";
|
|
var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif";
|
|
var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
|
|
var dithering_fragment = "#ifdef DITHERING\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
|
|
var dithering_pars_fragment = "#ifdef DITHERING\n vec3 dithering( vec3 color ) {\n float grid_position = rand( gl_FragCoord.xy );\n vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n return color + dither_shift_RGB;\n }\n#endif";
|
|
var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n vec4 texelRoughness = texture2D( roughnessMap, vUv );\n roughnessFactor *= texelRoughness.g;\n#endif";
|
|
var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n uniform sampler2D roughnessMap;\n#endif";
|
|
var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n return unpackRGBATo2Half( texture2D( shadow, uv ) );\n }\n float VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n float occlusion = 1.0;\n vec2 distribution = texture2DDistribution( shadow, uv );\n float hard_shadow = step( compare , distribution.x );\n if (hard_shadow != 1.0 ) {\n float distance = compare - distribution.x ;\n float variance = max( 0.00000, distribution.y * distribution.y );\n float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n }\n return occlusion;\n }\n float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n float shadow = 1.0;\n shadowCoord.xyz /= shadowCoord.w;\n shadowCoord.z += shadowBias;\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n bool frustumTest = all( frustumTestVec );\n if ( frustumTest ) {\n #if defined( SHADOWMAP_TYPE_PCF )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx0 = - texelSize.x * shadowRadius;\n float dy0 = - texelSize.y * shadowRadius;\n float dx1 = + texelSize.x * shadowRadius;\n float dy1 = + texelSize.y * shadowRadius;\n float dx2 = dx0 / 2.0;\n float dy2 = dy0 / 2.0;\n float dx3 = dx1 / 2.0;\n float dy3 = dy1 / 2.0;\n shadow = (\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n ) * ( 1.0 / 17.0 );\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx = texelSize.x;\n float dy = texelSize.y;\n vec2 uv = shadowCoord.xy;\n vec2 f = fract( uv * shadowMapSize + 0.5 );\n uv -= f * texelSize;\n shadow = (\n texture2DCompare( shadowMap, uv, shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n f.x ),\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n f.x ),\n f.y )\n ) * ( 1.0 / 9.0 );\n #elif defined( SHADOWMAP_TYPE_VSM )\n shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n #else\n shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n #endif\n }\n return shadow;\n }\n vec2 cubeToUV( vec3 v, float texelSizeY ) {\n vec3 absV = abs( v );\n float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n absV *= scaleToCube;\n v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n vec2 planar = v.xy;\n float almostATexel = 1.5 * texelSizeY;\n float almostOne = 1.0 - almostATexel;\n if ( absV.z >= almostOne ) {\n if ( v.z > 0.0 )\n planar.x = 4.0 - v.x;\n } else if ( absV.x >= almostOne ) {\n float signX = sign( v.x );\n planar.x = v.z * signX + 2.0 * signX;\n } else if ( absV.y >= almostOne ) {\n float signY = sign( v.y );\n planar.x = v.x + 2.0 * signY + 2.0;\n planar.y = v.z * signY - 2.0;\n }\n return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n }\n float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n vec3 lightToPosition = shadowCoord.xyz;\n float dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias;\n vec3 bd3D = normalize( lightToPosition );\n #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n return (\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n ) * ( 1.0 / 9.0 );\n #else\n return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n #endif\n }\n#endif";
|
|
var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n#endif";
|
|
var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n vec4 shadowWorldPosition;\n #endif\n #if NUM_DIR_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n#endif";
|
|
var shadowmask_pars_fragment = "float getShadowMask() {\n float shadow = 1.0;\n #ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n directionalLight = directionalLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n spotLight = spotLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n pointLight = pointLightShadows[ i ];\n shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #endif\n return shadow;\n}";
|
|
var skinbase_vertex = "#ifdef USE_SKINNING\n mat4 boneMatX = getBoneMatrix( skinIndex.x );\n mat4 boneMatY = getBoneMatrix( skinIndex.y );\n mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n mat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
|
|
var skinning_pars_vertex = "#ifdef USE_SKINNING\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n #ifdef BONE_TEXTURE\n uniform highp sampler2D boneTexture;\n uniform int boneTextureSize;\n mat4 getBoneMatrix( const in float i ) {\n float j = i * 4.0;\n float x = mod( j, float( boneTextureSize ) );\n float y = floor( j / float( boneTextureSize ) );\n float dx = 1.0 / float( boneTextureSize );\n float dy = 1.0 / float( boneTextureSize );\n y = dy * ( y + 0.5 );\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n mat4 bone = mat4( v1, v2, v3, v4 );\n return bone;\n }\n #else\n uniform mat4 boneMatrices[ MAX_BONES ];\n mat4 getBoneMatrix( const in float i ) {\n mat4 bone = boneMatrices[ int(i) ];\n return bone;\n }\n #endif\n#endif";
|
|
var skinning_vertex = "#ifdef USE_SKINNING\n vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n transformed = ( bindMatrixInverse * skinned ).xyz;\n#endif";
|
|
var skinnormal_vertex = "#ifdef USE_SKINNING\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n #ifdef USE_TANGENT\n objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #endif\n#endif";
|
|
var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n vec4 texelSpecular = texture2D( specularMap, vUv );\n specularStrength = texelSpecular.r;\n#else\n specularStrength = 1.0;\n#endif";
|
|
var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n uniform sampler2D specularMap;\n#endif";
|
|
var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
|
|
var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n return saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n color = max( vec3( 0.0 ), color - 0.004 );\n return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n vec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n return a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n const mat3 ACESInputMat = mat3(\n vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ),\n vec3( 0.04823, 0.01566, 0.83777 )\n );\n const mat3 ACESOutputMat = mat3(\n vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ),\n vec3( -0.07367, -0.00605, 1.07602 )\n );\n color *= toneMappingExposure / 0.6;\n color = ACESInputMat * color;\n color = RRTAndODTFit( color );\n color = ACESOutputMat * color;\n return saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
|
|
var transmission_fragment = "#ifdef USE_TRANSMISSION\n float transmissionAlpha = 1.0;\n float transmissionFactor = transmission;\n float thicknessFactor = thickness;\n #ifdef USE_TRANSMISSIONMAP\n transmissionFactor *= texture2D( transmissionMap, vUv ).r;\n #endif\n #ifdef USE_THICKNESSMAP\n thicknessFactor *= texture2D( thicknessMap, vUv ).g;\n #endif\n vec3 pos = vWorldPosition;\n vec3 v = normalize( cameraPosition - pos );\n vec3 n = inverseTransformDirection( normal, viewMatrix );\n vec4 transmission = getIBLVolumeRefraction(\n n, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n attenuationTint, attenuationDistance );\n totalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n transmissionAlpha = transmission.a;\n#endif";
|
|
var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n uniform float transmission;\n uniform float thickness;\n uniform float attenuationDistance;\n uniform vec3 attenuationTint;\n #ifdef USE_TRANSMISSIONMAP\n uniform sampler2D transmissionMap;\n #endif\n #ifdef USE_THICKNESSMAP\n uniform sampler2D thicknessMap;\n #endif\n uniform vec2 transmissionSamplerSize;\n uniform sampler2D transmissionSamplerMap;\n uniform mat4 modelMatrix;\n uniform mat4 projectionMatrix;\n varying vec3 vWorldPosition;\n vec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {\n vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n vec3 modelScale;\n modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n return normalize( refractionVector ) * thickness * modelScale;\n }\n float applyIorToRoughness( float roughness, float ior ) {\n return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n }\n vec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {\n float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n #ifdef TEXTURE_LOD_EXT\n return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #else\n return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #endif\n }\n vec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {\n if ( attenuationDistance == 0.0 ) {\n return radiance;\n } else {\n vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance * radiance;\n }\n }\n vec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,\n vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,\n vec3 attenuationColor, float attenuationDistance ) {\n vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n vec3 refractedRayExit = position + transmissionRay;\n vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n vec2 refractionCoords = ndcPos.xy / ndcPos.w;\n refractionCoords += 1.0;\n refractionCoords /= 2.0;\n vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n return vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n }\n#endif";
|
|
var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n varying vec2 vUv;\n#endif";
|
|
var uv_pars_vertex = "#ifdef USE_UV\n #ifdef UVS_VERTEX_ONLY\n vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n uniform mat3 uvTransform;\n#endif";
|
|
var uv_vertex = "#ifdef USE_UV\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
|
|
var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n varying vec2 vUv2;\n#endif";
|
|
var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n attribute vec2 uv2;\n varying vec2 vUv2;\n uniform mat3 uv2Transform;\n#endif";
|
|
var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
|
|
var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n vec4 worldPosition = vec4( transformed, 1.0 );\n #ifdef USE_INSTANCING\n worldPosition = instanceMatrix * worldPosition;\n #endif\n worldPosition = modelMatrix * worldPosition;\n#endif";
|
|
var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n vec4 texColor = texture2D( t2D, vUv );\n gl_FragColor = mapTexelToLinear( texColor );\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n}";
|
|
var background_vert = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n gl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
|
|
var cube_frag = "#include <envmap_common_pars_fragment>\nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n vec3 vReflect = vWorldDirection;\n #include <envmap_fragment>\n gl_FragColor = envColor;\n gl_FragColor.a *= opacity;\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n}";
|
|
var cube_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include <begin_vertex>\n #include <project_vertex>\n gl_Position.z = gl_Position.w;\n}";
|
|
var depth_frag = "#if DEPTH_PACKING == 3200\n uniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( 1.0 );\n #if DEPTH_PACKING == 3200\n diffuseColor.a = opacity;\n #endif\n #include <map_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <logdepthbuf_fragment>\n float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n #if DEPTH_PACKING == 3200\n gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n #elif DEPTH_PACKING == 3201\n gl_FragColor = packDepthToRGBA( fragCoordZ );\n #endif\n}";
|
|
var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include <uv_vertex>\n #include <skinbase_vertex>\n #ifdef USE_DISPLACEMENTMAP\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinnormal_vertex>\n #endif\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n vHighPrecisionZW = gl_Position.zw;\n}";
|
|
var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( 1.0 );\n #include <map_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n float dist = length( vWorldPosition - referencePosition );\n dist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n dist = saturate( dist );\n gl_FragColor = packDepthToRGBA( dist );\n}";
|
|
var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <skinbase_vertex>\n #ifdef USE_DISPLACEMENTMAP\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinnormal_vertex>\n #endif\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <worldpos_vertex>\n #include <clipping_planes_vertex>\n vWorldPosition = worldPosition.xyz;\n}";
|
|
var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n vec3 direction = normalize( vWorldDirection );\n vec2 sampleUV = equirectUv( direction );\n vec4 texColor = texture2D( tEquirect, sampleUV );\n gl_FragColor = mapTexelToLinear( texColor );\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n}";
|
|
var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include <begin_vertex>\n #include <project_vertex>\n}";
|
|
var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n if ( mod( vLineDistance, totalSize ) > dashSize ) {\n discard;\n }\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include <logdepthbuf_fragment>\n #include <color_fragment>\n outgoingLight = diffuseColor.rgb;\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n}";
|
|
var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n vLineDistance = scale * lineDistance;\n #include <color_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <fog_vertex>\n}";
|
|
var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <specularmap_fragment>\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel= texture2D( lightMap, vUv2 );\n reflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n #else\n reflectedLight.indirectDiffuse += vec3( 1.0 );\n #endif\n #include <aomap_fragment>\n reflectedLight.indirectDiffuse *= diffuseColor.rgb;\n vec3 outgoingLight = reflectedLight.indirectDiffuse;\n #include <envmap_fragment>\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <uv2_vertex>\n #include <color_vertex>\n #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #endif\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <worldpos_vertex>\n #include <envmap_vertex>\n #include <fog_vertex>\n}";
|
|
var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <specularmap_fragment>\n #include <emissivemap_fragment>\n #ifdef DOUBLE_SIDED\n reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n #else\n reflectedLight.indirectDiffuse += vIndirectFront;\n #endif\n #include <lightmap_fragment>\n reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n #ifdef DOUBLE_SIDED\n reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n #else\n reflectedLight.directDiffuse = vLightFront;\n #endif\n reflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n #include <aomap_fragment>\n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include <envmap_fragment>\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <uv2_vertex>\n #include <color_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <worldpos_vertex>\n #include <envmap_vertex>\n #include <lights_lambert_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n}";
|
|
var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <normal_fragment_begin>\n #include <normal_fragment_maps>\n vec3 viewDir = normalize( vViewPosition );\n vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n vec3 y = cross( viewDir, x );\n vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n #ifdef USE_MATCAP\n vec4 matcapColor = texture2D( matcap, uv );\n matcapColor = matcapTexelToLinear( matcapColor );\n #else\n vec4 matcapColor = vec4( 1.0 );\n #endif\n vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <color_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <normal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <fog_vertex>\n vViewPosition = - mvPosition.xyz;\n}";
|
|
var meshnormal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n #include <logdepthbuf_fragment>\n #include <normal_fragment_begin>\n #include <normal_fragment_maps>\n gl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}";
|
|
var meshnormal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <normal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n vViewPosition = - mvPosition.xyz;\n#endif\n}";
|
|
var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <specularmap_fragment>\n #include <normal_fragment_begin>\n #include <normal_fragment_maps>\n #include <emissivemap_fragment>\n #include <lights_phong_fragment>\n #include <lights_fragment_begin>\n #include <lights_fragment_maps>\n #include <lights_fragment_end>\n #include <aomap_fragment>\n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n #include <envmap_fragment>\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <uv2_vertex>\n #include <color_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <normal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n vViewPosition = - mvPosition.xyz;\n #include <worldpos_vertex>\n #include <envmap_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n}";
|
|
var meshphysical_frag = "#define STANDARD\n#ifdef PHYSICAL\n #define IOR\n #define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n uniform float ior;\n#endif\n#ifdef SPECULAR\n uniform float specularIntensity;\n uniform vec3 specularTint;\n #ifdef USE_SPECULARINTENSITYMAP\n uniform sampler2D specularIntensityMap;\n #endif\n #ifdef USE_SPECULARTINTMAP\n uniform sampler2D specularTintMap;\n #endif\n#endif\n#ifdef USE_CLEARCOAT\n uniform float clearcoat;\n uniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n uniform vec3 sheenTint;\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <roughnessmap_fragment>\n #include <metalnessmap_fragment>\n #include <normal_fragment_begin>\n #include <normal_fragment_maps>\n #include <clearcoat_normal_fragment_begin>\n #include <clearcoat_normal_fragment_maps>\n #include <emissivemap_fragment>\n #include <lights_physical_fragment>\n #include <lights_fragment_begin>\n #include <lights_fragment_maps>\n #include <lights_fragment_end>\n #include <aomap_fragment>\n vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n #include <transmission_fragment>\n vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n #ifdef USE_CLEARCOAT\n float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n outgoingLight = outgoingLight * ( 1.0 - clearcoat * Fcc ) + clearcoatSpecular * clearcoat;\n #endif\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshphysical_vert = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n varying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <uv2_vertex>\n #include <color_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <normal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n vViewPosition = - mvPosition.xyz;\n #include <worldpos_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n#ifdef USE_TRANSMISSION\n vWorldPosition = worldPosition.xyz;\n#endif\n}";
|
|
var meshtoon_frag = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <color_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n #include <normal_fragment_begin>\n #include <normal_fragment_maps>\n #include <emissivemap_fragment>\n #include <lights_toon_fragment>\n #include <lights_fragment_begin>\n #include <lights_fragment_maps>\n #include <lights_fragment_end>\n #include <aomap_fragment>\n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}";
|
|
var meshtoon_vert = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n #include <uv2_vertex>\n #include <color_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <normal_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n vViewPosition = - mvPosition.xyz;\n #include <worldpos_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n}";
|
|
var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include <logdepthbuf_fragment>\n #include <map_particle_fragment>\n #include <color_fragment>\n #include <alphatest_fragment>\n outgoingLight = diffuseColor.rgb;\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n}";
|
|
var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <color_vertex>\n #include <begin_vertex>\n #include <morphtarget_vertex>\n #include <project_vertex>\n gl_PointSize = size;\n #ifdef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n #endif\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <worldpos_vertex>\n #include <fog_vertex>\n}";
|
|
var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n}";
|
|
var shadow_vert = "#include <common>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n #include <begin_vertex>\n #include <project_vertex>\n #include <worldpos_vertex>\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n #include <defaultnormal_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n}";
|
|
var sprite_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n #include <clipping_planes_fragment>\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include <logdepthbuf_fragment>\n #include <map_fragment>\n #include <alphamap_fragment>\n #include <alphatest_fragment>\n outgoingLight = diffuseColor.rgb;\n #include <output_fragment>\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n}";
|
|
var sprite_vert = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n #include <uv_vertex>\n vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n vec2 scale;\n scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n #ifndef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) scale *= - mvPosition.z;\n #endif\n vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n vec2 rotatedPosition;\n rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n mvPosition.xy += rotatedPosition;\n gl_Position = projectionMatrix * mvPosition;\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n #include <fog_vertex>\n}";
|
|
var ShaderChunk = {
|
|
alphamap_fragment,
|
|
alphamap_pars_fragment,
|
|
alphatest_fragment,
|
|
alphatest_pars_fragment,
|
|
aomap_fragment,
|
|
aomap_pars_fragment,
|
|
begin_vertex,
|
|
beginnormal_vertex,
|
|
bsdfs,
|
|
bumpmap_pars_fragment,
|
|
clipping_planes_fragment,
|
|
clipping_planes_pars_fragment,
|
|
clipping_planes_pars_vertex,
|
|
clipping_planes_vertex,
|
|
color_fragment,
|
|
color_pars_fragment,
|
|
color_pars_vertex,
|
|
color_vertex,
|
|
common,
|
|
cube_uv_reflection_fragment,
|
|
defaultnormal_vertex,
|
|
displacementmap_pars_vertex,
|
|
displacementmap_vertex,
|
|
emissivemap_fragment,
|
|
emissivemap_pars_fragment,
|
|
encodings_fragment,
|
|
encodings_pars_fragment,
|
|
envmap_fragment,
|
|
envmap_common_pars_fragment,
|
|
envmap_pars_fragment,
|
|
envmap_pars_vertex,
|
|
envmap_physical_pars_fragment,
|
|
envmap_vertex,
|
|
fog_vertex,
|
|
fog_pars_vertex,
|
|
fog_fragment,
|
|
fog_pars_fragment,
|
|
gradientmap_pars_fragment,
|
|
lightmap_fragment,
|
|
lightmap_pars_fragment,
|
|
lights_lambert_vertex,
|
|
lights_pars_begin,
|
|
lights_toon_fragment,
|
|
lights_toon_pars_fragment,
|
|
lights_phong_fragment,
|
|
lights_phong_pars_fragment,
|
|
lights_physical_fragment,
|
|
lights_physical_pars_fragment,
|
|
lights_fragment_begin,
|
|
lights_fragment_maps,
|
|
lights_fragment_end,
|
|
logdepthbuf_fragment,
|
|
logdepthbuf_pars_fragment,
|
|
logdepthbuf_pars_vertex,
|
|
logdepthbuf_vertex,
|
|
map_fragment,
|
|
map_pars_fragment,
|
|
map_particle_fragment,
|
|
map_particle_pars_fragment,
|
|
metalnessmap_fragment,
|
|
metalnessmap_pars_fragment,
|
|
morphnormal_vertex,
|
|
morphtarget_pars_vertex,
|
|
morphtarget_vertex,
|
|
normal_fragment_begin,
|
|
normal_fragment_maps,
|
|
normal_pars_fragment,
|
|
normal_pars_vertex,
|
|
normal_vertex,
|
|
normalmap_pars_fragment,
|
|
clearcoat_normal_fragment_begin,
|
|
clearcoat_normal_fragment_maps,
|
|
clearcoat_pars_fragment,
|
|
output_fragment,
|
|
packing,
|
|
premultiplied_alpha_fragment,
|
|
project_vertex,
|
|
dithering_fragment,
|
|
dithering_pars_fragment,
|
|
roughnessmap_fragment,
|
|
roughnessmap_pars_fragment,
|
|
shadowmap_pars_fragment,
|
|
shadowmap_pars_vertex,
|
|
shadowmap_vertex,
|
|
shadowmask_pars_fragment,
|
|
skinbase_vertex,
|
|
skinning_pars_vertex,
|
|
skinning_vertex,
|
|
skinnormal_vertex,
|
|
specularmap_fragment,
|
|
specularmap_pars_fragment,
|
|
tonemapping_fragment,
|
|
tonemapping_pars_fragment,
|
|
transmission_fragment,
|
|
transmission_pars_fragment,
|
|
uv_pars_fragment,
|
|
uv_pars_vertex,
|
|
uv_vertex,
|
|
uv2_pars_fragment,
|
|
uv2_pars_vertex,
|
|
uv2_vertex,
|
|
worldpos_vertex,
|
|
background_frag,
|
|
background_vert,
|
|
cube_frag,
|
|
cube_vert,
|
|
depth_frag,
|
|
depth_vert,
|
|
distanceRGBA_frag,
|
|
distanceRGBA_vert,
|
|
equirect_frag,
|
|
equirect_vert,
|
|
linedashed_frag,
|
|
linedashed_vert,
|
|
meshbasic_frag,
|
|
meshbasic_vert,
|
|
meshlambert_frag,
|
|
meshlambert_vert,
|
|
meshmatcap_frag,
|
|
meshmatcap_vert,
|
|
meshnormal_frag,
|
|
meshnormal_vert,
|
|
meshphong_frag,
|
|
meshphong_vert,
|
|
meshphysical_frag,
|
|
meshphysical_vert,
|
|
meshtoon_frag,
|
|
meshtoon_vert,
|
|
points_frag,
|
|
points_vert,
|
|
shadow_frag,
|
|
shadow_vert,
|
|
sprite_frag,
|
|
sprite_vert
|
|
};
|
|
var UniformsLib = {
|
|
common: {
|
|
diffuse: { value: new Color(16777215) },
|
|
opacity: { value: 1 },
|
|
map: { value: null },
|
|
uvTransform: { value: new Matrix3() },
|
|
uv2Transform: { value: new Matrix3() },
|
|
alphaMap: { value: null },
|
|
alphaTest: { value: 0 }
|
|
},
|
|
specularmap: {
|
|
specularMap: { value: null }
|
|
},
|
|
envmap: {
|
|
envMap: { value: null },
|
|
flipEnvMap: { value: -1 },
|
|
reflectivity: { value: 1 },
|
|
ior: { value: 1.5 },
|
|
refractionRatio: { value: 0.98 },
|
|
maxMipLevel: { value: 0 }
|
|
},
|
|
aomap: {
|
|
aoMap: { value: null },
|
|
aoMapIntensity: { value: 1 }
|
|
},
|
|
lightmap: {
|
|
lightMap: { value: null },
|
|
lightMapIntensity: { value: 1 }
|
|
},
|
|
emissivemap: {
|
|
emissiveMap: { value: null }
|
|
},
|
|
bumpmap: {
|
|
bumpMap: { value: null },
|
|
bumpScale: { value: 1 }
|
|
},
|
|
normalmap: {
|
|
normalMap: { value: null },
|
|
normalScale: { value: new Vector2(1, 1) }
|
|
},
|
|
displacementmap: {
|
|
displacementMap: { value: null },
|
|
displacementScale: { value: 1 },
|
|
displacementBias: { value: 0 }
|
|
},
|
|
roughnessmap: {
|
|
roughnessMap: { value: null }
|
|
},
|
|
metalnessmap: {
|
|
metalnessMap: { value: null }
|
|
},
|
|
gradientmap: {
|
|
gradientMap: { value: null }
|
|
},
|
|
fog: {
|
|
fogDensity: { value: 25e-5 },
|
|
fogNear: { value: 1 },
|
|
fogFar: { value: 2e3 },
|
|
fogColor: { value: new Color(16777215) }
|
|
},
|
|
lights: {
|
|
ambientLightColor: { value: [] },
|
|
lightProbe: { value: [] },
|
|
directionalLights: { value: [], properties: {
|
|
direction: {},
|
|
color: {}
|
|
} },
|
|
directionalLightShadows: { value: [], properties: {
|
|
shadowBias: {},
|
|
shadowNormalBias: {},
|
|
shadowRadius: {},
|
|
shadowMapSize: {}
|
|
} },
|
|
directionalShadowMap: { value: [] },
|
|
directionalShadowMatrix: { value: [] },
|
|
spotLights: { value: [], properties: {
|
|
color: {},
|
|
position: {},
|
|
direction: {},
|
|
distance: {},
|
|
coneCos: {},
|
|
penumbraCos: {},
|
|
decay: {}
|
|
} },
|
|
spotLightShadows: { value: [], properties: {
|
|
shadowBias: {},
|
|
shadowNormalBias: {},
|
|
shadowRadius: {},
|
|
shadowMapSize: {}
|
|
} },
|
|
spotShadowMap: { value: [] },
|
|
spotShadowMatrix: { value: [] },
|
|
pointLights: { value: [], properties: {
|
|
color: {},
|
|
position: {},
|
|
decay: {},
|
|
distance: {}
|
|
} },
|
|
pointLightShadows: { value: [], properties: {
|
|
shadowBias: {},
|
|
shadowNormalBias: {},
|
|
shadowRadius: {},
|
|
shadowMapSize: {},
|
|
shadowCameraNear: {},
|
|
shadowCameraFar: {}
|
|
} },
|
|
pointShadowMap: { value: [] },
|
|
pointShadowMatrix: { value: [] },
|
|
hemisphereLights: { value: [], properties: {
|
|
direction: {},
|
|
skyColor: {},
|
|
groundColor: {}
|
|
} },
|
|
rectAreaLights: { value: [], properties: {
|
|
color: {},
|
|
position: {},
|
|
width: {},
|
|
height: {}
|
|
} },
|
|
ltc_1: { value: null },
|
|
ltc_2: { value: null }
|
|
},
|
|
points: {
|
|
diffuse: { value: new Color(16777215) },
|
|
opacity: { value: 1 },
|
|
size: { value: 1 },
|
|
scale: { value: 1 },
|
|
map: { value: null },
|
|
alphaMap: { value: null },
|
|
alphaTest: { value: 0 },
|
|
uvTransform: { value: new Matrix3() }
|
|
},
|
|
sprite: {
|
|
diffuse: { value: new Color(16777215) },
|
|
opacity: { value: 1 },
|
|
center: { value: new Vector2(0.5, 0.5) },
|
|
rotation: { value: 0 },
|
|
map: { value: null },
|
|
alphaMap: { value: null },
|
|
alphaTest: { value: 0 },
|
|
uvTransform: { value: new Matrix3() }
|
|
}
|
|
};
|
|
var ShaderLib = {
|
|
basic: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.specularmap,
|
|
UniformsLib.envmap,
|
|
UniformsLib.aomap,
|
|
UniformsLib.lightmap,
|
|
UniformsLib.fog
|
|
]),
|
|
vertexShader: ShaderChunk.meshbasic_vert,
|
|
fragmentShader: ShaderChunk.meshbasic_frag
|
|
},
|
|
lambert: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.specularmap,
|
|
UniformsLib.envmap,
|
|
UniformsLib.aomap,
|
|
UniformsLib.lightmap,
|
|
UniformsLib.emissivemap,
|
|
UniformsLib.fog,
|
|
UniformsLib.lights,
|
|
{
|
|
emissive: { value: new Color(0) }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshlambert_vert,
|
|
fragmentShader: ShaderChunk.meshlambert_frag
|
|
},
|
|
phong: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.specularmap,
|
|
UniformsLib.envmap,
|
|
UniformsLib.aomap,
|
|
UniformsLib.lightmap,
|
|
UniformsLib.emissivemap,
|
|
UniformsLib.bumpmap,
|
|
UniformsLib.normalmap,
|
|
UniformsLib.displacementmap,
|
|
UniformsLib.fog,
|
|
UniformsLib.lights,
|
|
{
|
|
emissive: { value: new Color(0) },
|
|
specular: { value: new Color(1118481) },
|
|
shininess: { value: 30 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshphong_vert,
|
|
fragmentShader: ShaderChunk.meshphong_frag
|
|
},
|
|
standard: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.envmap,
|
|
UniformsLib.aomap,
|
|
UniformsLib.lightmap,
|
|
UniformsLib.emissivemap,
|
|
UniformsLib.bumpmap,
|
|
UniformsLib.normalmap,
|
|
UniformsLib.displacementmap,
|
|
UniformsLib.roughnessmap,
|
|
UniformsLib.metalnessmap,
|
|
UniformsLib.fog,
|
|
UniformsLib.lights,
|
|
{
|
|
emissive: { value: new Color(0) },
|
|
roughness: { value: 1 },
|
|
metalness: { value: 0 },
|
|
envMapIntensity: { value: 1 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshphysical_vert,
|
|
fragmentShader: ShaderChunk.meshphysical_frag
|
|
},
|
|
toon: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.aomap,
|
|
UniformsLib.lightmap,
|
|
UniformsLib.emissivemap,
|
|
UniformsLib.bumpmap,
|
|
UniformsLib.normalmap,
|
|
UniformsLib.displacementmap,
|
|
UniformsLib.gradientmap,
|
|
UniformsLib.fog,
|
|
UniformsLib.lights,
|
|
{
|
|
emissive: { value: new Color(0) }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshtoon_vert,
|
|
fragmentShader: ShaderChunk.meshtoon_frag
|
|
},
|
|
matcap: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.bumpmap,
|
|
UniformsLib.normalmap,
|
|
UniformsLib.displacementmap,
|
|
UniformsLib.fog,
|
|
{
|
|
matcap: { value: null }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshmatcap_vert,
|
|
fragmentShader: ShaderChunk.meshmatcap_frag
|
|
},
|
|
points: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.points,
|
|
UniformsLib.fog
|
|
]),
|
|
vertexShader: ShaderChunk.points_vert,
|
|
fragmentShader: ShaderChunk.points_frag
|
|
},
|
|
dashed: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.fog,
|
|
{
|
|
scale: { value: 1 },
|
|
dashSize: { value: 1 },
|
|
totalSize: { value: 2 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.linedashed_vert,
|
|
fragmentShader: ShaderChunk.linedashed_frag
|
|
},
|
|
depth: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.displacementmap
|
|
]),
|
|
vertexShader: ShaderChunk.depth_vert,
|
|
fragmentShader: ShaderChunk.depth_frag
|
|
},
|
|
normal: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.bumpmap,
|
|
UniformsLib.normalmap,
|
|
UniformsLib.displacementmap,
|
|
{
|
|
opacity: { value: 1 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshnormal_vert,
|
|
fragmentShader: ShaderChunk.meshnormal_frag
|
|
},
|
|
sprite: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.sprite,
|
|
UniformsLib.fog
|
|
]),
|
|
vertexShader: ShaderChunk.sprite_vert,
|
|
fragmentShader: ShaderChunk.sprite_frag
|
|
},
|
|
background: {
|
|
uniforms: {
|
|
uvTransform: { value: new Matrix3() },
|
|
t2D: { value: null }
|
|
},
|
|
vertexShader: ShaderChunk.background_vert,
|
|
fragmentShader: ShaderChunk.background_frag
|
|
},
|
|
cube: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.envmap,
|
|
{
|
|
opacity: { value: 1 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.cube_vert,
|
|
fragmentShader: ShaderChunk.cube_frag
|
|
},
|
|
equirect: {
|
|
uniforms: {
|
|
tEquirect: { value: null }
|
|
},
|
|
vertexShader: ShaderChunk.equirect_vert,
|
|
fragmentShader: ShaderChunk.equirect_frag
|
|
},
|
|
distanceRGBA: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.common,
|
|
UniformsLib.displacementmap,
|
|
{
|
|
referencePosition: { value: new Vector3() },
|
|
nearDistance: { value: 1 },
|
|
farDistance: { value: 1e3 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.distanceRGBA_vert,
|
|
fragmentShader: ShaderChunk.distanceRGBA_frag
|
|
},
|
|
shadow: {
|
|
uniforms: mergeUniforms([
|
|
UniformsLib.lights,
|
|
UniformsLib.fog,
|
|
{
|
|
color: { value: new Color(0) },
|
|
opacity: { value: 1 }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.shadow_vert,
|
|
fragmentShader: ShaderChunk.shadow_frag
|
|
}
|
|
};
|
|
ShaderLib.physical = {
|
|
uniforms: mergeUniforms([
|
|
ShaderLib.standard.uniforms,
|
|
{
|
|
clearcoat: { value: 0 },
|
|
clearcoatMap: { value: null },
|
|
clearcoatRoughness: { value: 0 },
|
|
clearcoatRoughnessMap: { value: null },
|
|
clearcoatNormalScale: { value: new Vector2(1, 1) },
|
|
clearcoatNormalMap: { value: null },
|
|
sheenTint: { value: new Color(0) },
|
|
transmission: { value: 0 },
|
|
transmissionMap: { value: null },
|
|
transmissionSamplerSize: { value: new Vector2() },
|
|
transmissionSamplerMap: { value: null },
|
|
thickness: { value: 0 },
|
|
thicknessMap: { value: null },
|
|
attenuationDistance: { value: 0 },
|
|
attenuationTint: { value: new Color(0) },
|
|
specularIntensity: { value: 0 },
|
|
specularIntensityMap: { value: null },
|
|
specularTint: { value: new Color(1, 1, 1) },
|
|
specularTintMap: { value: null }
|
|
}
|
|
]),
|
|
vertexShader: ShaderChunk.meshphysical_vert,
|
|
fragmentShader: ShaderChunk.meshphysical_frag
|
|
};
|
|
function WebGLBackground(renderer, cubemaps, state, objects, premultipliedAlpha) {
|
|
const clearColor = new Color(0);
|
|
let clearAlpha = 0;
|
|
let planeMesh;
|
|
let boxMesh;
|
|
let currentBackground = null;
|
|
let currentBackgroundVersion = 0;
|
|
let currentTonemapping = null;
|
|
function render(renderList, scene) {
|
|
let forceClear = false;
|
|
let background = scene.isScene === true ? scene.background : null;
|
|
if (background && background.isTexture) {
|
|
background = cubemaps.get(background);
|
|
}
|
|
const xr = renderer.xr;
|
|
const session = xr.getSession && xr.getSession();
|
|
if (session && session.environmentBlendMode === "additive") {
|
|
background = null;
|
|
}
|
|
if (background === null) {
|
|
setClear(clearColor, clearAlpha);
|
|
} else if (background && background.isColor) {
|
|
setClear(background, 1);
|
|
forceClear = true;
|
|
}
|
|
if (renderer.autoClear || forceClear) {
|
|
renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil);
|
|
}
|
|
if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) {
|
|
if (boxMesh === void 0) {
|
|
boxMesh = new Mesh(new BoxGeometry(1, 1, 1), new ShaderMaterial({
|
|
name: "BackgroundCubeMaterial",
|
|
uniforms: cloneUniforms(ShaderLib.cube.uniforms),
|
|
vertexShader: ShaderLib.cube.vertexShader,
|
|
fragmentShader: ShaderLib.cube.fragmentShader,
|
|
side: BackSide,
|
|
depthTest: false,
|
|
depthWrite: false,
|
|
fog: false
|
|
}));
|
|
boxMesh.geometry.deleteAttribute("normal");
|
|
boxMesh.geometry.deleteAttribute("uv");
|
|
boxMesh.onBeforeRender = function(renderer2, scene2, camera) {
|
|
this.matrixWorld.copyPosition(camera.matrixWorld);
|
|
};
|
|
Object.defineProperty(boxMesh.material, "envMap", {
|
|
get: function() {
|
|
return this.uniforms.envMap.value;
|
|
}
|
|
});
|
|
objects.update(boxMesh);
|
|
}
|
|
boxMesh.material.uniforms.envMap.value = background;
|
|
boxMesh.material.uniforms.flipEnvMap.value = background.isCubeTexture && background.isRenderTargetTexture === false ? -1 : 1;
|
|
if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) {
|
|
boxMesh.material.needsUpdate = true;
|
|
currentBackground = background;
|
|
currentBackgroundVersion = background.version;
|
|
currentTonemapping = renderer.toneMapping;
|
|
}
|
|
renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null);
|
|
} else if (background && background.isTexture) {
|
|
if (planeMesh === void 0) {
|
|
planeMesh = new Mesh(new PlaneGeometry(2, 2), new ShaderMaterial({
|
|
name: "BackgroundMaterial",
|
|
uniforms: cloneUniforms(ShaderLib.background.uniforms),
|
|
vertexShader: ShaderLib.background.vertexShader,
|
|
fragmentShader: ShaderLib.background.fragmentShader,
|
|
side: FrontSide,
|
|
depthTest: false,
|
|
depthWrite: false,
|
|
fog: false
|
|
}));
|
|
planeMesh.geometry.deleteAttribute("normal");
|
|
Object.defineProperty(planeMesh.material, "map", {
|
|
get: function() {
|
|
return this.uniforms.t2D.value;
|
|
}
|
|
});
|
|
objects.update(planeMesh);
|
|
}
|
|
planeMesh.material.uniforms.t2D.value = background;
|
|
if (background.matrixAutoUpdate === true) {
|
|
background.updateMatrix();
|
|
}
|
|
planeMesh.material.uniforms.uvTransform.value.copy(background.matrix);
|
|
if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) {
|
|
planeMesh.material.needsUpdate = true;
|
|
currentBackground = background;
|
|
currentBackgroundVersion = background.version;
|
|
currentTonemapping = renderer.toneMapping;
|
|
}
|
|
renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null);
|
|
}
|
|
}
|
|
function setClear(color, alpha) {
|
|
state.buffers.color.setClear(color.r, color.g, color.b, alpha, premultipliedAlpha);
|
|
}
|
|
return {
|
|
getClearColor: function() {
|
|
return clearColor;
|
|
},
|
|
setClearColor: function(color, alpha = 1) {
|
|
clearColor.set(color);
|
|
clearAlpha = alpha;
|
|
setClear(clearColor, clearAlpha);
|
|
},
|
|
getClearAlpha: function() {
|
|
return clearAlpha;
|
|
},
|
|
setClearAlpha: function(alpha) {
|
|
clearAlpha = alpha;
|
|
setClear(clearColor, clearAlpha);
|
|
},
|
|
render
|
|
};
|
|
}
|
|
function WebGLBindingStates(gl, extensions, attributes, capabilities) {
|
|
const maxVertexAttributes = gl.getParameter(34921);
|
|
const extension = capabilities.isWebGL2 ? null : extensions.get("OES_vertex_array_object");
|
|
const vaoAvailable = capabilities.isWebGL2 || extension !== null;
|
|
const bindingStates = {};
|
|
const defaultState = createBindingState(null);
|
|
let currentState = defaultState;
|
|
function setup(object, material, program, geometry, index) {
|
|
let updateBuffers = false;
|
|
if (vaoAvailable) {
|
|
const state = getBindingState(geometry, program, material);
|
|
if (currentState !== state) {
|
|
currentState = state;
|
|
bindVertexArrayObject(currentState.object);
|
|
}
|
|
updateBuffers = needsUpdate(geometry, index);
|
|
if (updateBuffers)
|
|
saveCache(geometry, index);
|
|
} else {
|
|
const wireframe = material.wireframe === true;
|
|
if (currentState.geometry !== geometry.id || currentState.program !== program.id || currentState.wireframe !== wireframe) {
|
|
currentState.geometry = geometry.id;
|
|
currentState.program = program.id;
|
|
currentState.wireframe = wireframe;
|
|
updateBuffers = true;
|
|
}
|
|
}
|
|
if (object.isInstancedMesh === true) {
|
|
updateBuffers = true;
|
|
}
|
|
if (index !== null) {
|
|
attributes.update(index, 34963);
|
|
}
|
|
if (updateBuffers) {
|
|
setupVertexAttributes(object, material, program, geometry);
|
|
if (index !== null) {
|
|
gl.bindBuffer(34963, attributes.get(index).buffer);
|
|
}
|
|
}
|
|
}
|
|
function createVertexArrayObject() {
|
|
if (capabilities.isWebGL2)
|
|
return gl.createVertexArray();
|
|
return extension.createVertexArrayOES();
|
|
}
|
|
function bindVertexArrayObject(vao) {
|
|
if (capabilities.isWebGL2)
|
|
return gl.bindVertexArray(vao);
|
|
return extension.bindVertexArrayOES(vao);
|
|
}
|
|
function deleteVertexArrayObject(vao) {
|
|
if (capabilities.isWebGL2)
|
|
return gl.deleteVertexArray(vao);
|
|
return extension.deleteVertexArrayOES(vao);
|
|
}
|
|
function getBindingState(geometry, program, material) {
|
|
const wireframe = material.wireframe === true;
|
|
let programMap = bindingStates[geometry.id];
|
|
if (programMap === void 0) {
|
|
programMap = {};
|
|
bindingStates[geometry.id] = programMap;
|
|
}
|
|
let stateMap = programMap[program.id];
|
|
if (stateMap === void 0) {
|
|
stateMap = {};
|
|
programMap[program.id] = stateMap;
|
|
}
|
|
let state = stateMap[wireframe];
|
|
if (state === void 0) {
|
|
state = createBindingState(createVertexArrayObject());
|
|
stateMap[wireframe] = state;
|
|
}
|
|
return state;
|
|
}
|
|
function createBindingState(vao) {
|
|
const newAttributes = [];
|
|
const enabledAttributes = [];
|
|
const attributeDivisors = [];
|
|
for (let i = 0; i < maxVertexAttributes; i++) {
|
|
newAttributes[i] = 0;
|
|
enabledAttributes[i] = 0;
|
|
attributeDivisors[i] = 0;
|
|
}
|
|
return {
|
|
geometry: null,
|
|
program: null,
|
|
wireframe: false,
|
|
newAttributes,
|
|
enabledAttributes,
|
|
attributeDivisors,
|
|
object: vao,
|
|
attributes: {},
|
|
index: null
|
|
};
|
|
}
|
|
function needsUpdate(geometry, index) {
|
|
const cachedAttributes = currentState.attributes;
|
|
const geometryAttributes = geometry.attributes;
|
|
let attributesNum = 0;
|
|
for (const key in geometryAttributes) {
|
|
const cachedAttribute = cachedAttributes[key];
|
|
const geometryAttribute = geometryAttributes[key];
|
|
if (cachedAttribute === void 0)
|
|
return true;
|
|
if (cachedAttribute.attribute !== geometryAttribute)
|
|
return true;
|
|
if (cachedAttribute.data !== geometryAttribute.data)
|
|
return true;
|
|
attributesNum++;
|
|
}
|
|
if (currentState.attributesNum !== attributesNum)
|
|
return true;
|
|
if (currentState.index !== index)
|
|
return true;
|
|
return false;
|
|
}
|
|
function saveCache(geometry, index) {
|
|
const cache = {};
|
|
const attributes2 = geometry.attributes;
|
|
let attributesNum = 0;
|
|
for (const key in attributes2) {
|
|
const attribute = attributes2[key];
|
|
const data = {};
|
|
data.attribute = attribute;
|
|
if (attribute.data) {
|
|
data.data = attribute.data;
|
|
}
|
|
cache[key] = data;
|
|
attributesNum++;
|
|
}
|
|
currentState.attributes = cache;
|
|
currentState.attributesNum = attributesNum;
|
|
currentState.index = index;
|
|
}
|
|
function initAttributes() {
|
|
const newAttributes = currentState.newAttributes;
|
|
for (let i = 0, il = newAttributes.length; i < il; i++) {
|
|
newAttributes[i] = 0;
|
|
}
|
|
}
|
|
function enableAttribute(attribute) {
|
|
enableAttributeAndDivisor(attribute, 0);
|
|
}
|
|
function enableAttributeAndDivisor(attribute, meshPerAttribute) {
|
|
const newAttributes = currentState.newAttributes;
|
|
const enabledAttributes = currentState.enabledAttributes;
|
|
const attributeDivisors = currentState.attributeDivisors;
|
|
newAttributes[attribute] = 1;
|
|
if (enabledAttributes[attribute] === 0) {
|
|
gl.enableVertexAttribArray(attribute);
|
|
enabledAttributes[attribute] = 1;
|
|
}
|
|
if (attributeDivisors[attribute] !== meshPerAttribute) {
|
|
const extension2 = capabilities.isWebGL2 ? gl : extensions.get("ANGLE_instanced_arrays");
|
|
extension2[capabilities.isWebGL2 ? "vertexAttribDivisor" : "vertexAttribDivisorANGLE"](attribute, meshPerAttribute);
|
|
attributeDivisors[attribute] = meshPerAttribute;
|
|
}
|
|
}
|
|
function disableUnusedAttributes() {
|
|
const newAttributes = currentState.newAttributes;
|
|
const enabledAttributes = currentState.enabledAttributes;
|
|
for (let i = 0, il = enabledAttributes.length; i < il; i++) {
|
|
if (enabledAttributes[i] !== newAttributes[i]) {
|
|
gl.disableVertexAttribArray(i);
|
|
enabledAttributes[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
function vertexAttribPointer(index, size, type, normalized, stride, offset) {
|
|
if (capabilities.isWebGL2 === true && (type === 5124 || type === 5125)) {
|
|
gl.vertexAttribIPointer(index, size, type, stride, offset);
|
|
} else {
|
|
gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
|
|
}
|
|
}
|
|
function setupVertexAttributes(object, material, program, geometry) {
|
|
if (capabilities.isWebGL2 === false && (object.isInstancedMesh || geometry.isInstancedBufferGeometry)) {
|
|
if (extensions.get("ANGLE_instanced_arrays") === null)
|
|
return;
|
|
}
|
|
initAttributes();
|
|
const geometryAttributes = geometry.attributes;
|
|
const programAttributes = program.getAttributes();
|
|
const materialDefaultAttributeValues = material.defaultAttributeValues;
|
|
for (const name in programAttributes) {
|
|
const programAttribute = programAttributes[name];
|
|
if (programAttribute.location >= 0) {
|
|
let geometryAttribute = geometryAttributes[name];
|
|
if (geometryAttribute === void 0) {
|
|
if (name === "instanceMatrix" && object.instanceMatrix)
|
|
geometryAttribute = object.instanceMatrix;
|
|
if (name === "instanceColor" && object.instanceColor)
|
|
geometryAttribute = object.instanceColor;
|
|
}
|
|
if (geometryAttribute !== void 0) {
|
|
const normalized = geometryAttribute.normalized;
|
|
const size = geometryAttribute.itemSize;
|
|
const attribute = attributes.get(geometryAttribute);
|
|
if (attribute === void 0)
|
|
continue;
|
|
const buffer = attribute.buffer;
|
|
const type = attribute.type;
|
|
const bytesPerElement = attribute.bytesPerElement;
|
|
if (geometryAttribute.isInterleavedBufferAttribute) {
|
|
const data = geometryAttribute.data;
|
|
const stride = data.stride;
|
|
const offset = geometryAttribute.offset;
|
|
if (data && data.isInstancedInterleavedBuffer) {
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
enableAttributeAndDivisor(programAttribute.location + i, data.meshPerAttribute);
|
|
}
|
|
if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) {
|
|
geometry._maxInstanceCount = data.meshPerAttribute * data.count;
|
|
}
|
|
} else {
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
enableAttribute(programAttribute.location + i);
|
|
}
|
|
}
|
|
gl.bindBuffer(34962, buffer);
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type, normalized, stride * bytesPerElement, (offset + size / programAttribute.locationSize * i) * bytesPerElement);
|
|
}
|
|
} else {
|
|
if (geometryAttribute.isInstancedBufferAttribute) {
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
enableAttributeAndDivisor(programAttribute.location + i, geometryAttribute.meshPerAttribute);
|
|
}
|
|
if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) {
|
|
geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
|
|
}
|
|
} else {
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
enableAttribute(programAttribute.location + i);
|
|
}
|
|
}
|
|
gl.bindBuffer(34962, buffer);
|
|
for (let i = 0; i < programAttribute.locationSize; i++) {
|
|
vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type, normalized, size * bytesPerElement, size / programAttribute.locationSize * i * bytesPerElement);
|
|
}
|
|
}
|
|
} else if (materialDefaultAttributeValues !== void 0) {
|
|
const value = materialDefaultAttributeValues[name];
|
|
if (value !== void 0) {
|
|
switch (value.length) {
|
|
case 2:
|
|
gl.vertexAttrib2fv(programAttribute.location, value);
|
|
break;
|
|
case 3:
|
|
gl.vertexAttrib3fv(programAttribute.location, value);
|
|
break;
|
|
case 4:
|
|
gl.vertexAttrib4fv(programAttribute.location, value);
|
|
break;
|
|
default:
|
|
gl.vertexAttrib1fv(programAttribute.location, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
disableUnusedAttributes();
|
|
}
|
|
function dispose() {
|
|
reset();
|
|
for (const geometryId in bindingStates) {
|
|
const programMap = bindingStates[geometryId];
|
|
for (const programId in programMap) {
|
|
const stateMap = programMap[programId];
|
|
for (const wireframe in stateMap) {
|
|
deleteVertexArrayObject(stateMap[wireframe].object);
|
|
delete stateMap[wireframe];
|
|
}
|
|
delete programMap[programId];
|
|
}
|
|
delete bindingStates[geometryId];
|
|
}
|
|
}
|
|
function releaseStatesOfGeometry(geometry) {
|
|
if (bindingStates[geometry.id] === void 0)
|
|
return;
|
|
const programMap = bindingStates[geometry.id];
|
|
for (const programId in programMap) {
|
|
const stateMap = programMap[programId];
|
|
for (const wireframe in stateMap) {
|
|
deleteVertexArrayObject(stateMap[wireframe].object);
|
|
delete stateMap[wireframe];
|
|
}
|
|
delete programMap[programId];
|
|
}
|
|
delete bindingStates[geometry.id];
|
|
}
|
|
function releaseStatesOfProgram(program) {
|
|
for (const geometryId in bindingStates) {
|
|
const programMap = bindingStates[geometryId];
|
|
if (programMap[program.id] === void 0)
|
|
continue;
|
|
const stateMap = programMap[program.id];
|
|
for (const wireframe in stateMap) {
|
|
deleteVertexArrayObject(stateMap[wireframe].object);
|
|
delete stateMap[wireframe];
|
|
}
|
|
delete programMap[program.id];
|
|
}
|
|
}
|
|
function reset() {
|
|
resetDefaultState();
|
|
if (currentState === defaultState)
|
|
return;
|
|
currentState = defaultState;
|
|
bindVertexArrayObject(currentState.object);
|
|
}
|
|
function resetDefaultState() {
|
|
defaultState.geometry = null;
|
|
defaultState.program = null;
|
|
defaultState.wireframe = false;
|
|
}
|
|
return {
|
|
setup,
|
|
reset,
|
|
resetDefaultState,
|
|
dispose,
|
|
releaseStatesOfGeometry,
|
|
releaseStatesOfProgram,
|
|
initAttributes,
|
|
enableAttribute,
|
|
disableUnusedAttributes
|
|
};
|
|
}
|
|
function WebGLBufferRenderer(gl, extensions, info, capabilities) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
let mode;
|
|
function setMode(value) {
|
|
mode = value;
|
|
}
|
|
function render(start, count) {
|
|
gl.drawArrays(mode, start, count);
|
|
info.update(count, mode, 1);
|
|
}
|
|
function renderInstances(start, count, primcount) {
|
|
if (primcount === 0)
|
|
return;
|
|
let extension, methodName;
|
|
if (isWebGL2) {
|
|
extension = gl;
|
|
methodName = "drawArraysInstanced";
|
|
} else {
|
|
extension = extensions.get("ANGLE_instanced_arrays");
|
|
methodName = "drawArraysInstancedANGLE";
|
|
if (extension === null) {
|
|
console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");
|
|
return;
|
|
}
|
|
}
|
|
extension[methodName](mode, start, count, primcount);
|
|
info.update(count, mode, primcount);
|
|
}
|
|
this.setMode = setMode;
|
|
this.render = render;
|
|
this.renderInstances = renderInstances;
|
|
}
|
|
function WebGLCapabilities(gl, extensions, parameters) {
|
|
let maxAnisotropy;
|
|
function getMaxAnisotropy() {
|
|
if (maxAnisotropy !== void 0)
|
|
return maxAnisotropy;
|
|
if (extensions.has("EXT_texture_filter_anisotropic") === true) {
|
|
const extension = extensions.get("EXT_texture_filter_anisotropic");
|
|
maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
|
|
} else {
|
|
maxAnisotropy = 0;
|
|
}
|
|
return maxAnisotropy;
|
|
}
|
|
function getMaxPrecision(precision2) {
|
|
if (precision2 === "highp") {
|
|
if (gl.getShaderPrecisionFormat(35633, 36338).precision > 0 && gl.getShaderPrecisionFormat(35632, 36338).precision > 0) {
|
|
return "highp";
|
|
}
|
|
precision2 = "mediump";
|
|
}
|
|
if (precision2 === "mediump") {
|
|
if (gl.getShaderPrecisionFormat(35633, 36337).precision > 0 && gl.getShaderPrecisionFormat(35632, 36337).precision > 0) {
|
|
return "mediump";
|
|
}
|
|
}
|
|
return "lowp";
|
|
}
|
|
const isWebGL2 = typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext || typeof WebGL2ComputeRenderingContext !== "undefined" && gl instanceof WebGL2ComputeRenderingContext;
|
|
let precision = parameters.precision !== void 0 ? parameters.precision : "highp";
|
|
const maxPrecision = getMaxPrecision(precision);
|
|
if (maxPrecision !== precision) {
|
|
console.warn("THREE.WebGLRenderer:", precision, "not supported, using", maxPrecision, "instead.");
|
|
precision = maxPrecision;
|
|
}
|
|
const drawBuffers = isWebGL2 || extensions.has("WEBGL_draw_buffers");
|
|
const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
|
|
const maxTextures = gl.getParameter(34930);
|
|
const maxVertexTextures = gl.getParameter(35660);
|
|
const maxTextureSize = gl.getParameter(3379);
|
|
const maxCubemapSize = gl.getParameter(34076);
|
|
const maxAttributes = gl.getParameter(34921);
|
|
const maxVertexUniforms = gl.getParameter(36347);
|
|
const maxVaryings = gl.getParameter(36348);
|
|
const maxFragmentUniforms = gl.getParameter(36349);
|
|
const vertexTextures = maxVertexTextures > 0;
|
|
const floatFragmentTextures = isWebGL2 || extensions.has("OES_texture_float");
|
|
const floatVertexTextures = vertexTextures && floatFragmentTextures;
|
|
const maxSamples = isWebGL2 ? gl.getParameter(36183) : 0;
|
|
return {
|
|
isWebGL2,
|
|
drawBuffers,
|
|
getMaxAnisotropy,
|
|
getMaxPrecision,
|
|
precision,
|
|
logarithmicDepthBuffer,
|
|
maxTextures,
|
|
maxVertexTextures,
|
|
maxTextureSize,
|
|
maxCubemapSize,
|
|
maxAttributes,
|
|
maxVertexUniforms,
|
|
maxVaryings,
|
|
maxFragmentUniforms,
|
|
vertexTextures,
|
|
floatFragmentTextures,
|
|
floatVertexTextures,
|
|
maxSamples
|
|
};
|
|
}
|
|
function WebGLClipping(properties) {
|
|
const scope = this;
|
|
let globalState = null, numGlobalPlanes = 0, localClippingEnabled = false, renderingShadows = false;
|
|
const plane = new Plane(), viewNormalMatrix = new Matrix3(), uniform = { value: null, needsUpdate: false };
|
|
this.uniform = uniform;
|
|
this.numPlanes = 0;
|
|
this.numIntersection = 0;
|
|
this.init = function(planes, enableLocalClipping, camera) {
|
|
const enabled = planes.length !== 0 || enableLocalClipping || numGlobalPlanes !== 0 || localClippingEnabled;
|
|
localClippingEnabled = enableLocalClipping;
|
|
globalState = projectPlanes(planes, camera, 0);
|
|
numGlobalPlanes = planes.length;
|
|
return enabled;
|
|
};
|
|
this.beginShadows = function() {
|
|
renderingShadows = true;
|
|
projectPlanes(null);
|
|
};
|
|
this.endShadows = function() {
|
|
renderingShadows = false;
|
|
resetGlobalState();
|
|
};
|
|
this.setState = function(material, camera, useCache) {
|
|
const planes = material.clippingPlanes, clipIntersection = material.clipIntersection, clipShadows = material.clipShadows;
|
|
const materialProperties = properties.get(material);
|
|
if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) {
|
|
if (renderingShadows) {
|
|
projectPlanes(null);
|
|
} else {
|
|
resetGlobalState();
|
|
}
|
|
} else {
|
|
const nGlobal = renderingShadows ? 0 : numGlobalPlanes, lGlobal = nGlobal * 4;
|
|
let dstArray = materialProperties.clippingState || null;
|
|
uniform.value = dstArray;
|
|
dstArray = projectPlanes(planes, camera, lGlobal, useCache);
|
|
for (let i = 0; i !== lGlobal; ++i) {
|
|
dstArray[i] = globalState[i];
|
|
}
|
|
materialProperties.clippingState = dstArray;
|
|
this.numIntersection = clipIntersection ? this.numPlanes : 0;
|
|
this.numPlanes += nGlobal;
|
|
}
|
|
};
|
|
function resetGlobalState() {
|
|
if (uniform.value !== globalState) {
|
|
uniform.value = globalState;
|
|
uniform.needsUpdate = numGlobalPlanes > 0;
|
|
}
|
|
scope.numPlanes = numGlobalPlanes;
|
|
scope.numIntersection = 0;
|
|
}
|
|
function projectPlanes(planes, camera, dstOffset, skipTransform) {
|
|
const nPlanes = planes !== null ? planes.length : 0;
|
|
let dstArray = null;
|
|
if (nPlanes !== 0) {
|
|
dstArray = uniform.value;
|
|
if (skipTransform !== true || dstArray === null) {
|
|
const flatSize = dstOffset + nPlanes * 4, viewMatrix = camera.matrixWorldInverse;
|
|
viewNormalMatrix.getNormalMatrix(viewMatrix);
|
|
if (dstArray === null || dstArray.length < flatSize) {
|
|
dstArray = new Float32Array(flatSize);
|
|
}
|
|
for (let i = 0, i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) {
|
|
plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix);
|
|
plane.normal.toArray(dstArray, i4);
|
|
dstArray[i4 + 3] = plane.constant;
|
|
}
|
|
}
|
|
uniform.value = dstArray;
|
|
uniform.needsUpdate = true;
|
|
}
|
|
scope.numPlanes = nPlanes;
|
|
scope.numIntersection = 0;
|
|
return dstArray;
|
|
}
|
|
}
|
|
function WebGLCubeMaps(renderer) {
|
|
let cubemaps = new WeakMap();
|
|
function mapTextureMapping(texture, mapping) {
|
|
if (mapping === EquirectangularReflectionMapping) {
|
|
texture.mapping = CubeReflectionMapping;
|
|
} else if (mapping === EquirectangularRefractionMapping) {
|
|
texture.mapping = CubeRefractionMapping;
|
|
}
|
|
return texture;
|
|
}
|
|
function get(texture) {
|
|
if (texture && texture.isTexture && texture.isRenderTargetTexture === false) {
|
|
const mapping = texture.mapping;
|
|
if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) {
|
|
if (cubemaps.has(texture)) {
|
|
const cubemap = cubemaps.get(texture).texture;
|
|
return mapTextureMapping(cubemap, texture.mapping);
|
|
} else {
|
|
const image = texture.image;
|
|
if (image && image.height > 0) {
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
const renderTarget = new WebGLCubeRenderTarget(image.height / 2);
|
|
renderTarget.fromEquirectangularTexture(renderer, texture);
|
|
cubemaps.set(texture, renderTarget);
|
|
renderer.setRenderTarget(currentRenderTarget);
|
|
texture.addEventListener("dispose", onTextureDispose);
|
|
return mapTextureMapping(renderTarget.texture, texture.mapping);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return texture;
|
|
}
|
|
function onTextureDispose(event) {
|
|
const texture = event.target;
|
|
texture.removeEventListener("dispose", onTextureDispose);
|
|
const cubemap = cubemaps.get(texture);
|
|
if (cubemap !== void 0) {
|
|
cubemaps.delete(texture);
|
|
cubemap.dispose();
|
|
}
|
|
}
|
|
function dispose() {
|
|
cubemaps = new WeakMap();
|
|
}
|
|
return {
|
|
get,
|
|
dispose
|
|
};
|
|
}
|
|
var OrthographicCamera = class extends Camera {
|
|
constructor(left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2e3) {
|
|
super();
|
|
this.type = "OrthographicCamera";
|
|
this.zoom = 1;
|
|
this.view = null;
|
|
this.left = left;
|
|
this.right = right;
|
|
this.top = top;
|
|
this.bottom = bottom;
|
|
this.near = near;
|
|
this.far = far;
|
|
this.updateProjectionMatrix();
|
|
}
|
|
copy(source, recursive) {
|
|
super.copy(source, recursive);
|
|
this.left = source.left;
|
|
this.right = source.right;
|
|
this.top = source.top;
|
|
this.bottom = source.bottom;
|
|
this.near = source.near;
|
|
this.far = source.far;
|
|
this.zoom = source.zoom;
|
|
this.view = source.view === null ? null : Object.assign({}, source.view);
|
|
return this;
|
|
}
|
|
setViewOffset(fullWidth, fullHeight, x, y, width, height) {
|
|
if (this.view === null) {
|
|
this.view = {
|
|
enabled: true,
|
|
fullWidth: 1,
|
|
fullHeight: 1,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
width: 1,
|
|
height: 1
|
|
};
|
|
}
|
|
this.view.enabled = true;
|
|
this.view.fullWidth = fullWidth;
|
|
this.view.fullHeight = fullHeight;
|
|
this.view.offsetX = x;
|
|
this.view.offsetY = y;
|
|
this.view.width = width;
|
|
this.view.height = height;
|
|
this.updateProjectionMatrix();
|
|
}
|
|
clearViewOffset() {
|
|
if (this.view !== null) {
|
|
this.view.enabled = false;
|
|
}
|
|
this.updateProjectionMatrix();
|
|
}
|
|
updateProjectionMatrix() {
|
|
const dx = (this.right - this.left) / (2 * this.zoom);
|
|
const dy = (this.top - this.bottom) / (2 * this.zoom);
|
|
const cx = (this.right + this.left) / 2;
|
|
const cy = (this.top + this.bottom) / 2;
|
|
let left = cx - dx;
|
|
let right = cx + dx;
|
|
let top = cy + dy;
|
|
let bottom = cy - dy;
|
|
if (this.view !== null && this.view.enabled) {
|
|
const scaleW = (this.right - this.left) / this.view.fullWidth / this.zoom;
|
|
const scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom;
|
|
left += scaleW * this.view.offsetX;
|
|
right = left + scaleW * this.view.width;
|
|
top -= scaleH * this.view.offsetY;
|
|
bottom = top - scaleH * this.view.height;
|
|
}
|
|
this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far);
|
|
this.projectionMatrixInverse.copy(this.projectionMatrix).invert();
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.object.zoom = this.zoom;
|
|
data.object.left = this.left;
|
|
data.object.right = this.right;
|
|
data.object.top = this.top;
|
|
data.object.bottom = this.bottom;
|
|
data.object.near = this.near;
|
|
data.object.far = this.far;
|
|
if (this.view !== null)
|
|
data.object.view = Object.assign({}, this.view);
|
|
return data;
|
|
}
|
|
};
|
|
OrthographicCamera.prototype.isOrthographicCamera = true;
|
|
var RawShaderMaterial = class extends ShaderMaterial {
|
|
constructor(parameters) {
|
|
super(parameters);
|
|
this.type = "RawShaderMaterial";
|
|
}
|
|
};
|
|
RawShaderMaterial.prototype.isRawShaderMaterial = true;
|
|
var LOD_MIN = 4;
|
|
var LOD_MAX = 8;
|
|
var SIZE_MAX = Math.pow(2, LOD_MAX);
|
|
var EXTRA_LOD_SIGMA = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582];
|
|
var TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
|
|
var MAX_SAMPLES = 20;
|
|
var ENCODINGS = {
|
|
[LinearEncoding]: 0,
|
|
[sRGBEncoding]: 1,
|
|
[RGBEEncoding]: 2,
|
|
[RGBM7Encoding]: 3,
|
|
[RGBM16Encoding]: 4,
|
|
[RGBDEncoding]: 5,
|
|
[GammaEncoding]: 6
|
|
};
|
|
var _flatCamera = /* @__PURE__ */ new OrthographicCamera();
|
|
var { _lodPlanes, _sizeLods, _sigmas } = /* @__PURE__ */ _createPlanes();
|
|
var _clearColor = /* @__PURE__ */ new Color();
|
|
var _oldTarget = null;
|
|
var PHI = (1 + Math.sqrt(5)) / 2;
|
|
var INV_PHI = 1 / PHI;
|
|
var _axisDirections = [
|
|
/* @__PURE__ */ new Vector3(1, 1, 1),
|
|
/* @__PURE__ */ new Vector3(-1, 1, 1),
|
|
/* @__PURE__ */ new Vector3(1, 1, -1),
|
|
/* @__PURE__ */ new Vector3(-1, 1, -1),
|
|
/* @__PURE__ */ new Vector3(0, PHI, INV_PHI),
|
|
/* @__PURE__ */ new Vector3(0, PHI, -INV_PHI),
|
|
/* @__PURE__ */ new Vector3(INV_PHI, 0, PHI),
|
|
/* @__PURE__ */ new Vector3(-INV_PHI, 0, PHI),
|
|
/* @__PURE__ */ new Vector3(PHI, INV_PHI, 0),
|
|
/* @__PURE__ */ new Vector3(-PHI, INV_PHI, 0)
|
|
];
|
|
var PMREMGenerator = class {
|
|
constructor(renderer) {
|
|
this._renderer = renderer;
|
|
this._pingPongRenderTarget = null;
|
|
this._blurMaterial = _getBlurShader(MAX_SAMPLES);
|
|
this._equirectShader = null;
|
|
this._cubemapShader = null;
|
|
this._compileMaterial(this._blurMaterial);
|
|
}
|
|
fromScene(scene, sigma = 0, near = 0.1, far = 100) {
|
|
_oldTarget = this._renderer.getRenderTarget();
|
|
const cubeUVRenderTarget = this._allocateTargets();
|
|
this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget);
|
|
if (sigma > 0) {
|
|
this._blur(cubeUVRenderTarget, 0, 0, sigma);
|
|
}
|
|
this._applyPMREM(cubeUVRenderTarget);
|
|
this._cleanup(cubeUVRenderTarget);
|
|
return cubeUVRenderTarget;
|
|
}
|
|
fromEquirectangular(equirectangular) {
|
|
return this._fromTexture(equirectangular);
|
|
}
|
|
fromCubemap(cubemap) {
|
|
return this._fromTexture(cubemap);
|
|
}
|
|
compileCubemapShader() {
|
|
if (this._cubemapShader === null) {
|
|
this._cubemapShader = _getCubemapShader();
|
|
this._compileMaterial(this._cubemapShader);
|
|
}
|
|
}
|
|
compileEquirectangularShader() {
|
|
if (this._equirectShader === null) {
|
|
this._equirectShader = _getEquirectShader();
|
|
this._compileMaterial(this._equirectShader);
|
|
}
|
|
}
|
|
dispose() {
|
|
this._blurMaterial.dispose();
|
|
if (this._cubemapShader !== null)
|
|
this._cubemapShader.dispose();
|
|
if (this._equirectShader !== null)
|
|
this._equirectShader.dispose();
|
|
for (let i = 0; i < _lodPlanes.length; i++) {
|
|
_lodPlanes[i].dispose();
|
|
}
|
|
}
|
|
_cleanup(outputTarget) {
|
|
this._pingPongRenderTarget.dispose();
|
|
this._renderer.setRenderTarget(_oldTarget);
|
|
outputTarget.scissorTest = false;
|
|
_setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height);
|
|
}
|
|
_fromTexture(texture) {
|
|
_oldTarget = this._renderer.getRenderTarget();
|
|
const cubeUVRenderTarget = this._allocateTargets(texture);
|
|
this._textureToCubeUV(texture, cubeUVRenderTarget);
|
|
this._applyPMREM(cubeUVRenderTarget);
|
|
this._cleanup(cubeUVRenderTarget);
|
|
return cubeUVRenderTarget;
|
|
}
|
|
_allocateTargets(texture) {
|
|
const params = {
|
|
magFilter: NearestFilter,
|
|
minFilter: NearestFilter,
|
|
generateMipmaps: false,
|
|
type: UnsignedByteType,
|
|
format: RGBEFormat,
|
|
encoding: _isLDR(texture) ? texture.encoding : RGBEEncoding,
|
|
depthBuffer: false
|
|
};
|
|
const cubeUVRenderTarget = _createRenderTarget(params);
|
|
cubeUVRenderTarget.depthBuffer = texture ? false : true;
|
|
this._pingPongRenderTarget = _createRenderTarget(params);
|
|
return cubeUVRenderTarget;
|
|
}
|
|
_compileMaterial(material) {
|
|
const tmpMesh = new Mesh(_lodPlanes[0], material);
|
|
this._renderer.compile(tmpMesh, _flatCamera);
|
|
}
|
|
_sceneToCubeUV(scene, near, far, cubeUVRenderTarget) {
|
|
const fov2 = 90;
|
|
const aspect2 = 1;
|
|
const cubeCamera = new PerspectiveCamera(fov2, aspect2, near, far);
|
|
const upSign = [1, -1, 1, 1, 1, 1];
|
|
const forwardSign = [1, 1, 1, -1, -1, -1];
|
|
const renderer = this._renderer;
|
|
const originalAutoClear = renderer.autoClear;
|
|
const outputEncoding = renderer.outputEncoding;
|
|
const toneMapping = renderer.toneMapping;
|
|
renderer.getClearColor(_clearColor);
|
|
renderer.toneMapping = NoToneMapping;
|
|
renderer.outputEncoding = LinearEncoding;
|
|
renderer.autoClear = false;
|
|
const backgroundMaterial = new MeshBasicMaterial({
|
|
name: "PMREM.Background",
|
|
side: BackSide,
|
|
depthWrite: false,
|
|
depthTest: false
|
|
});
|
|
const backgroundBox = new Mesh(new BoxGeometry(), backgroundMaterial);
|
|
let useSolidColor = false;
|
|
const background = scene.background;
|
|
if (background) {
|
|
if (background.isColor) {
|
|
backgroundMaterial.color.copy(background);
|
|
scene.background = null;
|
|
useSolidColor = true;
|
|
}
|
|
} else {
|
|
backgroundMaterial.color.copy(_clearColor);
|
|
useSolidColor = true;
|
|
}
|
|
for (let i = 0; i < 6; i++) {
|
|
const col = i % 3;
|
|
if (col == 0) {
|
|
cubeCamera.up.set(0, upSign[i], 0);
|
|
cubeCamera.lookAt(forwardSign[i], 0, 0);
|
|
} else if (col == 1) {
|
|
cubeCamera.up.set(0, 0, upSign[i]);
|
|
cubeCamera.lookAt(0, forwardSign[i], 0);
|
|
} else {
|
|
cubeCamera.up.set(0, upSign[i], 0);
|
|
cubeCamera.lookAt(0, 0, forwardSign[i]);
|
|
}
|
|
_setViewport(cubeUVRenderTarget, col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX);
|
|
renderer.setRenderTarget(cubeUVRenderTarget);
|
|
if (useSolidColor) {
|
|
renderer.render(backgroundBox, cubeCamera);
|
|
}
|
|
renderer.render(scene, cubeCamera);
|
|
}
|
|
backgroundBox.geometry.dispose();
|
|
backgroundBox.material.dispose();
|
|
renderer.toneMapping = toneMapping;
|
|
renderer.outputEncoding = outputEncoding;
|
|
renderer.autoClear = originalAutoClear;
|
|
scene.background = background;
|
|
}
|
|
_textureToCubeUV(texture, cubeUVRenderTarget) {
|
|
const renderer = this._renderer;
|
|
if (texture.isCubeTexture) {
|
|
if (this._cubemapShader == null) {
|
|
this._cubemapShader = _getCubemapShader();
|
|
}
|
|
} else {
|
|
if (this._equirectShader == null) {
|
|
this._equirectShader = _getEquirectShader();
|
|
}
|
|
}
|
|
const material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
|
|
const mesh = new Mesh(_lodPlanes[0], material);
|
|
const uniforms = material.uniforms;
|
|
uniforms["envMap"].value = texture;
|
|
if (!texture.isCubeTexture) {
|
|
uniforms["texelSize"].value.set(1 / texture.image.width, 1 / texture.image.height);
|
|
}
|
|
uniforms["inputEncoding"].value = ENCODINGS[texture.encoding];
|
|
uniforms["outputEncoding"].value = ENCODINGS[cubeUVRenderTarget.texture.encoding];
|
|
_setViewport(cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX);
|
|
renderer.setRenderTarget(cubeUVRenderTarget);
|
|
renderer.render(mesh, _flatCamera);
|
|
}
|
|
_applyPMREM(cubeUVRenderTarget) {
|
|
const renderer = this._renderer;
|
|
const autoClear = renderer.autoClear;
|
|
renderer.autoClear = false;
|
|
for (let i = 1; i < TOTAL_LODS; i++) {
|
|
const sigma = Math.sqrt(_sigmas[i] * _sigmas[i] - _sigmas[i - 1] * _sigmas[i - 1]);
|
|
const poleAxis = _axisDirections[(i - 1) % _axisDirections.length];
|
|
this._blur(cubeUVRenderTarget, i - 1, i, sigma, poleAxis);
|
|
}
|
|
renderer.autoClear = autoClear;
|
|
}
|
|
_blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) {
|
|
const pingPongRenderTarget = this._pingPongRenderTarget;
|
|
this._halfBlur(cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, sigma, "latitudinal", poleAxis);
|
|
this._halfBlur(pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, sigma, "longitudinal", poleAxis);
|
|
}
|
|
_halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) {
|
|
const renderer = this._renderer;
|
|
const blurMaterial = this._blurMaterial;
|
|
if (direction !== "latitudinal" && direction !== "longitudinal") {
|
|
console.error("blur direction must be either latitudinal or longitudinal!");
|
|
}
|
|
const STANDARD_DEVIATIONS = 3;
|
|
const blurMesh = new Mesh(_lodPlanes[lodOut], blurMaterial);
|
|
const blurUniforms = blurMaterial.uniforms;
|
|
const pixels = _sizeLods[lodIn] - 1;
|
|
const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : 2 * Math.PI / (2 * MAX_SAMPLES - 1);
|
|
const sigmaPixels = sigmaRadians / radiansPerPixel;
|
|
const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES;
|
|
if (samples > MAX_SAMPLES) {
|
|
console.warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES}`);
|
|
}
|
|
const weights = [];
|
|
let sum = 0;
|
|
for (let i = 0; i < MAX_SAMPLES; ++i) {
|
|
const x2 = i / sigmaPixels;
|
|
const weight = Math.exp(-x2 * x2 / 2);
|
|
weights.push(weight);
|
|
if (i == 0) {
|
|
sum += weight;
|
|
} else if (i < samples) {
|
|
sum += 2 * weight;
|
|
}
|
|
}
|
|
for (let i = 0; i < weights.length; i++) {
|
|
weights[i] = weights[i] / sum;
|
|
}
|
|
blurUniforms["envMap"].value = targetIn.texture;
|
|
blurUniforms["samples"].value = samples;
|
|
blurUniforms["weights"].value = weights;
|
|
blurUniforms["latitudinal"].value = direction === "latitudinal";
|
|
if (poleAxis) {
|
|
blurUniforms["poleAxis"].value = poleAxis;
|
|
}
|
|
blurUniforms["dTheta"].value = radiansPerPixel;
|
|
blurUniforms["mipInt"].value = LOD_MAX - lodIn;
|
|
blurUniforms["inputEncoding"].value = ENCODINGS[targetIn.texture.encoding];
|
|
blurUniforms["outputEncoding"].value = ENCODINGS[targetIn.texture.encoding];
|
|
const outputSize = _sizeLods[lodOut];
|
|
const x = 3 * Math.max(0, SIZE_MAX - 2 * outputSize);
|
|
const y = (lodOut === 0 ? 0 : 2 * SIZE_MAX) + 2 * outputSize * (lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0);
|
|
_setViewport(targetOut, x, y, 3 * outputSize, 2 * outputSize);
|
|
renderer.setRenderTarget(targetOut);
|
|
renderer.render(blurMesh, _flatCamera);
|
|
}
|
|
};
|
|
function _isLDR(texture) {
|
|
if (texture === void 0 || texture.type !== UnsignedByteType)
|
|
return false;
|
|
return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
|
|
}
|
|
function _createPlanes() {
|
|
const _lodPlanes2 = [];
|
|
const _sizeLods2 = [];
|
|
const _sigmas2 = [];
|
|
let lod = LOD_MAX;
|
|
for (let i = 0; i < TOTAL_LODS; i++) {
|
|
const sizeLod = Math.pow(2, lod);
|
|
_sizeLods2.push(sizeLod);
|
|
let sigma = 1 / sizeLod;
|
|
if (i > LOD_MAX - LOD_MIN) {
|
|
sigma = EXTRA_LOD_SIGMA[i - LOD_MAX + LOD_MIN - 1];
|
|
} else if (i == 0) {
|
|
sigma = 0;
|
|
}
|
|
_sigmas2.push(sigma);
|
|
const texelSize = 1 / (sizeLod - 1);
|
|
const min = -texelSize / 2;
|
|
const max = 1 + texelSize / 2;
|
|
const uv1 = [min, min, max, min, max, max, min, min, max, max, min, max];
|
|
const cubeFaces = 6;
|
|
const vertices = 6;
|
|
const positionSize = 3;
|
|
const uvSize = 2;
|
|
const faceIndexSize = 1;
|
|
const position = new Float32Array(positionSize * vertices * cubeFaces);
|
|
const uv = new Float32Array(uvSize * vertices * cubeFaces);
|
|
const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces);
|
|
for (let face = 0; face < cubeFaces; face++) {
|
|
const x = face % 3 * 2 / 3 - 1;
|
|
const y = face > 2 ? 0 : -1;
|
|
const coordinates = [
|
|
x,
|
|
y,
|
|
0,
|
|
x + 2 / 3,
|
|
y,
|
|
0,
|
|
x + 2 / 3,
|
|
y + 1,
|
|
0,
|
|
x,
|
|
y,
|
|
0,
|
|
x + 2 / 3,
|
|
y + 1,
|
|
0,
|
|
x,
|
|
y + 1,
|
|
0
|
|
];
|
|
position.set(coordinates, positionSize * vertices * face);
|
|
uv.set(uv1, uvSize * vertices * face);
|
|
const fill = [face, face, face, face, face, face];
|
|
faceIndex.set(fill, faceIndexSize * vertices * face);
|
|
}
|
|
const planes = new BufferGeometry();
|
|
planes.setAttribute("position", new BufferAttribute(position, positionSize));
|
|
planes.setAttribute("uv", new BufferAttribute(uv, uvSize));
|
|
planes.setAttribute("faceIndex", new BufferAttribute(faceIndex, faceIndexSize));
|
|
_lodPlanes2.push(planes);
|
|
if (lod > LOD_MIN) {
|
|
lod--;
|
|
}
|
|
}
|
|
return { _lodPlanes: _lodPlanes2, _sizeLods: _sizeLods2, _sigmas: _sigmas2 };
|
|
}
|
|
function _createRenderTarget(params) {
|
|
const cubeUVRenderTarget = new WebGLRenderTarget(3 * SIZE_MAX, 3 * SIZE_MAX, params);
|
|
cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
|
|
cubeUVRenderTarget.texture.name = "PMREM.cubeUv";
|
|
cubeUVRenderTarget.scissorTest = true;
|
|
return cubeUVRenderTarget;
|
|
}
|
|
function _setViewport(target, x, y, width, height) {
|
|
target.viewport.set(x, y, width, height);
|
|
target.scissor.set(x, y, width, height);
|
|
}
|
|
function _getBlurShader(maxSamples) {
|
|
const weights = new Float32Array(maxSamples);
|
|
const poleAxis = new Vector3(0, 1, 0);
|
|
const shaderMaterial = new RawShaderMaterial({
|
|
name: "SphericalGaussianBlur",
|
|
defines: { "n": maxSamples },
|
|
uniforms: {
|
|
"envMap": { value: null },
|
|
"samples": { value: 1 },
|
|
"weights": { value: weights },
|
|
"latitudinal": { value: false },
|
|
"dTheta": { value: 0 },
|
|
"mipInt": { value: 0 },
|
|
"poleAxis": { value: poleAxis },
|
|
"inputEncoding": { value: ENCODINGS[LinearEncoding] },
|
|
"outputEncoding": { value: ENCODINGS[LinearEncoding] }
|
|
},
|
|
vertexShader: _getCommonVertexShader(),
|
|
fragmentShader: `
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
varying vec3 vOutputDirection;
|
|
|
|
uniform sampler2D envMap;
|
|
uniform int samples;
|
|
uniform float weights[ n ];
|
|
uniform bool latitudinal;
|
|
uniform float dTheta;
|
|
uniform float mipInt;
|
|
uniform vec3 poleAxis;
|
|
|
|
${_getEncodings()}
|
|
|
|
#define ENVMAP_TYPE_CUBE_UV
|
|
#include <cube_uv_reflection_fragment>
|
|
|
|
vec3 getSample( float theta, vec3 axis ) {
|
|
|
|
float cosTheta = cos( theta );
|
|
// Rodrigues' axis-angle rotation
|
|
vec3 sampleDirection = vOutputDirection * cosTheta
|
|
+ cross( axis, vOutputDirection ) * sin( theta )
|
|
+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
|
|
|
|
return bilinearCubeUV( envMap, sampleDirection, mipInt );
|
|
|
|
}
|
|
|
|
void main() {
|
|
|
|
vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
|
|
|
|
if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
|
|
|
|
axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
|
|
|
|
}
|
|
|
|
axis = normalize( axis );
|
|
|
|
gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
|
|
|
|
for ( int i = 1; i < n; i++ ) {
|
|
|
|
if ( i >= samples ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
float theta = dTheta * float( i );
|
|
gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
|
|
gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
|
|
|
|
}
|
|
|
|
gl_FragColor = linearToOutputTexel( gl_FragColor );
|
|
|
|
}
|
|
`,
|
|
blending: NoBlending,
|
|
depthTest: false,
|
|
depthWrite: false
|
|
});
|
|
return shaderMaterial;
|
|
}
|
|
function _getEquirectShader() {
|
|
const texelSize = new Vector2(1, 1);
|
|
const shaderMaterial = new RawShaderMaterial({
|
|
name: "EquirectangularToCubeUV",
|
|
uniforms: {
|
|
"envMap": { value: null },
|
|
"texelSize": { value: texelSize },
|
|
"inputEncoding": { value: ENCODINGS[LinearEncoding] },
|
|
"outputEncoding": { value: ENCODINGS[LinearEncoding] }
|
|
},
|
|
vertexShader: _getCommonVertexShader(),
|
|
fragmentShader: `
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
varying vec3 vOutputDirection;
|
|
|
|
uniform sampler2D envMap;
|
|
uniform vec2 texelSize;
|
|
|
|
${_getEncodings()}
|
|
|
|
#include <common>
|
|
|
|
void main() {
|
|
|
|
gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
|
|
vec3 outputDirection = normalize( vOutputDirection );
|
|
vec2 uv = equirectUv( outputDirection );
|
|
|
|
vec2 f = fract( uv / texelSize - 0.5 );
|
|
uv -= f * texelSize;
|
|
vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
|
|
uv.x += texelSize.x;
|
|
vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
|
|
uv.y += texelSize.y;
|
|
vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
|
|
uv.x -= texelSize.x;
|
|
vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
|
|
|
|
vec3 tm = mix( tl, tr, f.x );
|
|
vec3 bm = mix( bl, br, f.x );
|
|
gl_FragColor.rgb = mix( tm, bm, f.y );
|
|
|
|
gl_FragColor = linearToOutputTexel( gl_FragColor );
|
|
|
|
}
|
|
`,
|
|
blending: NoBlending,
|
|
depthTest: false,
|
|
depthWrite: false
|
|
});
|
|
return shaderMaterial;
|
|
}
|
|
function _getCubemapShader() {
|
|
const shaderMaterial = new RawShaderMaterial({
|
|
name: "CubemapToCubeUV",
|
|
uniforms: {
|
|
"envMap": { value: null },
|
|
"inputEncoding": { value: ENCODINGS[LinearEncoding] },
|
|
"outputEncoding": { value: ENCODINGS[LinearEncoding] }
|
|
},
|
|
vertexShader: _getCommonVertexShader(),
|
|
fragmentShader: `
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
varying vec3 vOutputDirection;
|
|
|
|
uniform samplerCube envMap;
|
|
|
|
${_getEncodings()}
|
|
|
|
void main() {
|
|
|
|
gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
|
|
gl_FragColor = linearToOutputTexel( gl_FragColor );
|
|
|
|
}
|
|
`,
|
|
blending: NoBlending,
|
|
depthTest: false,
|
|
depthWrite: false
|
|
});
|
|
return shaderMaterial;
|
|
}
|
|
function _getCommonVertexShader() {
|
|
return `
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
attribute vec3 position;
|
|
attribute vec2 uv;
|
|
attribute float faceIndex;
|
|
|
|
varying vec3 vOutputDirection;
|
|
|
|
// RH coordinate system; PMREM face-indexing convention
|
|
vec3 getDirection( vec2 uv, float face ) {
|
|
|
|
uv = 2.0 * uv - 1.0;
|
|
|
|
vec3 direction = vec3( uv, 1.0 );
|
|
|
|
if ( face == 0.0 ) {
|
|
|
|
direction = direction.zyx; // ( 1, v, u ) pos x
|
|
|
|
} else if ( face == 1.0 ) {
|
|
|
|
direction = direction.xzy;
|
|
direction.xz *= -1.0; // ( -u, 1, -v ) pos y
|
|
|
|
} else if ( face == 2.0 ) {
|
|
|
|
direction.x *= -1.0; // ( -u, v, 1 ) pos z
|
|
|
|
} else if ( face == 3.0 ) {
|
|
|
|
direction = direction.zyx;
|
|
direction.xz *= -1.0; // ( -1, v, -u ) neg x
|
|
|
|
} else if ( face == 4.0 ) {
|
|
|
|
direction = direction.xzy;
|
|
direction.xy *= -1.0; // ( -u, -1, v ) neg y
|
|
|
|
} else if ( face == 5.0 ) {
|
|
|
|
direction.z *= -1.0; // ( u, v, -1 ) neg z
|
|
|
|
}
|
|
|
|
return direction;
|
|
|
|
}
|
|
|
|
void main() {
|
|
|
|
vOutputDirection = getDirection( uv, faceIndex );
|
|
gl_Position = vec4( position, 1.0 );
|
|
|
|
}
|
|
`;
|
|
}
|
|
function _getEncodings() {
|
|
return `
|
|
|
|
uniform int inputEncoding;
|
|
uniform int outputEncoding;
|
|
|
|
#include <encodings_pars_fragment>
|
|
|
|
vec4 inputTexelToLinear( vec4 value ) {
|
|
|
|
if ( inputEncoding == 0 ) {
|
|
|
|
return value;
|
|
|
|
} else if ( inputEncoding == 1 ) {
|
|
|
|
return sRGBToLinear( value );
|
|
|
|
} else if ( inputEncoding == 2 ) {
|
|
|
|
return RGBEToLinear( value );
|
|
|
|
} else if ( inputEncoding == 3 ) {
|
|
|
|
return RGBMToLinear( value, 7.0 );
|
|
|
|
} else if ( inputEncoding == 4 ) {
|
|
|
|
return RGBMToLinear( value, 16.0 );
|
|
|
|
} else if ( inputEncoding == 5 ) {
|
|
|
|
return RGBDToLinear( value, 256.0 );
|
|
|
|
} else {
|
|
|
|
return GammaToLinear( value, 2.2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vec4 linearToOutputTexel( vec4 value ) {
|
|
|
|
if ( outputEncoding == 0 ) {
|
|
|
|
return value;
|
|
|
|
} else if ( outputEncoding == 1 ) {
|
|
|
|
return LinearTosRGB( value );
|
|
|
|
} else if ( outputEncoding == 2 ) {
|
|
|
|
return LinearToRGBE( value );
|
|
|
|
} else if ( outputEncoding == 3 ) {
|
|
|
|
return LinearToRGBM( value, 7.0 );
|
|
|
|
} else if ( outputEncoding == 4 ) {
|
|
|
|
return LinearToRGBM( value, 16.0 );
|
|
|
|
} else if ( outputEncoding == 5 ) {
|
|
|
|
return LinearToRGBD( value, 256.0 );
|
|
|
|
} else {
|
|
|
|
return LinearToGamma( value, 2.2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vec4 envMapTexelToLinear( vec4 color ) {
|
|
|
|
return inputTexelToLinear( color );
|
|
|
|
}
|
|
`;
|
|
}
|
|
function WebGLCubeUVMaps(renderer) {
|
|
let cubeUVmaps = new WeakMap();
|
|
let pmremGenerator = null;
|
|
function get(texture) {
|
|
if (texture && texture.isTexture && texture.isRenderTargetTexture === false) {
|
|
const mapping = texture.mapping;
|
|
const isEquirectMap = mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping;
|
|
const isCubeMap = mapping === CubeReflectionMapping || mapping === CubeRefractionMapping;
|
|
if (isEquirectMap || isCubeMap) {
|
|
if (cubeUVmaps.has(texture)) {
|
|
return cubeUVmaps.get(texture).texture;
|
|
} else {
|
|
const image = texture.image;
|
|
if (isEquirectMap && image && image.height > 0 || isCubeMap && image && isCubeTextureComplete(image)) {
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
if (pmremGenerator === null)
|
|
pmremGenerator = new PMREMGenerator(renderer);
|
|
const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture);
|
|
cubeUVmaps.set(texture, renderTarget);
|
|
renderer.setRenderTarget(currentRenderTarget);
|
|
texture.addEventListener("dispose", onTextureDispose);
|
|
return renderTarget.texture;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return texture;
|
|
}
|
|
function isCubeTextureComplete(image) {
|
|
let count = 0;
|
|
const length = 6;
|
|
for (let i = 0; i < length; i++) {
|
|
if (image[i] !== void 0)
|
|
count++;
|
|
}
|
|
return count === length;
|
|
}
|
|
function onTextureDispose(event) {
|
|
const texture = event.target;
|
|
texture.removeEventListener("dispose", onTextureDispose);
|
|
const cubemapUV = cubeUVmaps.get(texture);
|
|
if (cubemapUV !== void 0) {
|
|
cubeUVmaps.delete(texture);
|
|
cubemapUV.dispose();
|
|
}
|
|
}
|
|
function dispose() {
|
|
cubeUVmaps = new WeakMap();
|
|
if (pmremGenerator !== null) {
|
|
pmremGenerator.dispose();
|
|
pmremGenerator = null;
|
|
}
|
|
}
|
|
return {
|
|
get,
|
|
dispose
|
|
};
|
|
}
|
|
function WebGLExtensions(gl) {
|
|
const extensions = {};
|
|
function getExtension(name) {
|
|
if (extensions[name] !== void 0) {
|
|
return extensions[name];
|
|
}
|
|
let extension;
|
|
switch (name) {
|
|
case "WEBGL_depth_texture":
|
|
extension = gl.getExtension("WEBGL_depth_texture") || gl.getExtension("MOZ_WEBGL_depth_texture") || gl.getExtension("WEBKIT_WEBGL_depth_texture");
|
|
break;
|
|
case "EXT_texture_filter_anisotropic":
|
|
extension = gl.getExtension("EXT_texture_filter_anisotropic") || gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic");
|
|
break;
|
|
case "WEBGL_compressed_texture_s3tc":
|
|
extension = gl.getExtension("WEBGL_compressed_texture_s3tc") || gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");
|
|
break;
|
|
case "WEBGL_compressed_texture_pvrtc":
|
|
extension = gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");
|
|
break;
|
|
default:
|
|
extension = gl.getExtension(name);
|
|
}
|
|
extensions[name] = extension;
|
|
return extension;
|
|
}
|
|
return {
|
|
has: function(name) {
|
|
return getExtension(name) !== null;
|
|
},
|
|
init: function(capabilities) {
|
|
if (capabilities.isWebGL2) {
|
|
getExtension("EXT_color_buffer_float");
|
|
} else {
|
|
getExtension("WEBGL_depth_texture");
|
|
getExtension("OES_texture_float");
|
|
getExtension("OES_texture_half_float");
|
|
getExtension("OES_texture_half_float_linear");
|
|
getExtension("OES_standard_derivatives");
|
|
getExtension("OES_element_index_uint");
|
|
getExtension("OES_vertex_array_object");
|
|
getExtension("ANGLE_instanced_arrays");
|
|
}
|
|
getExtension("OES_texture_float_linear");
|
|
getExtension("EXT_color_buffer_half_float");
|
|
},
|
|
get: function(name) {
|
|
const extension = getExtension(name);
|
|
if (extension === null) {
|
|
console.warn("THREE.WebGLRenderer: " + name + " extension not supported.");
|
|
}
|
|
return extension;
|
|
}
|
|
};
|
|
}
|
|
function WebGLGeometries(gl, attributes, info, bindingStates) {
|
|
const geometries = {};
|
|
const wireframeAttributes = new WeakMap();
|
|
function onGeometryDispose(event) {
|
|
const geometry = event.target;
|
|
if (geometry.index !== null) {
|
|
attributes.remove(geometry.index);
|
|
}
|
|
for (const name in geometry.attributes) {
|
|
attributes.remove(geometry.attributes[name]);
|
|
}
|
|
geometry.removeEventListener("dispose", onGeometryDispose);
|
|
delete geometries[geometry.id];
|
|
const attribute = wireframeAttributes.get(geometry);
|
|
if (attribute) {
|
|
attributes.remove(attribute);
|
|
wireframeAttributes.delete(geometry);
|
|
}
|
|
bindingStates.releaseStatesOfGeometry(geometry);
|
|
if (geometry.isInstancedBufferGeometry === true) {
|
|
delete geometry._maxInstanceCount;
|
|
}
|
|
info.memory.geometries--;
|
|
}
|
|
function get(object, geometry) {
|
|
if (geometries[geometry.id] === true)
|
|
return geometry;
|
|
geometry.addEventListener("dispose", onGeometryDispose);
|
|
geometries[geometry.id] = true;
|
|
info.memory.geometries++;
|
|
return geometry;
|
|
}
|
|
function update(geometry) {
|
|
const geometryAttributes = geometry.attributes;
|
|
for (const name in geometryAttributes) {
|
|
attributes.update(geometryAttributes[name], 34962);
|
|
}
|
|
const morphAttributes = geometry.morphAttributes;
|
|
for (const name in morphAttributes) {
|
|
const array = morphAttributes[name];
|
|
for (let i = 0, l = array.length; i < l; i++) {
|
|
attributes.update(array[i], 34962);
|
|
}
|
|
}
|
|
}
|
|
function updateWireframeAttribute(geometry) {
|
|
const indices = [];
|
|
const geometryIndex = geometry.index;
|
|
const geometryPosition = geometry.attributes.position;
|
|
let version = 0;
|
|
if (geometryIndex !== null) {
|
|
const array = geometryIndex.array;
|
|
version = geometryIndex.version;
|
|
for (let i = 0, l = array.length; i < l; i += 3) {
|
|
const a2 = array[i + 0];
|
|
const b2 = array[i + 1];
|
|
const c2 = array[i + 2];
|
|
indices.push(a2, b2, b2, c2, c2, a2);
|
|
}
|
|
} else {
|
|
const array = geometryPosition.array;
|
|
version = geometryPosition.version;
|
|
for (let i = 0, l = array.length / 3 - 1; i < l; i += 3) {
|
|
const a2 = i + 0;
|
|
const b2 = i + 1;
|
|
const c2 = i + 2;
|
|
indices.push(a2, b2, b2, c2, c2, a2);
|
|
}
|
|
}
|
|
const attribute = new (arrayMax(indices) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1);
|
|
attribute.version = version;
|
|
const previousAttribute = wireframeAttributes.get(geometry);
|
|
if (previousAttribute)
|
|
attributes.remove(previousAttribute);
|
|
wireframeAttributes.set(geometry, attribute);
|
|
}
|
|
function getWireframeAttribute(geometry) {
|
|
const currentAttribute = wireframeAttributes.get(geometry);
|
|
if (currentAttribute) {
|
|
const geometryIndex = geometry.index;
|
|
if (geometryIndex !== null) {
|
|
if (currentAttribute.version < geometryIndex.version) {
|
|
updateWireframeAttribute(geometry);
|
|
}
|
|
}
|
|
} else {
|
|
updateWireframeAttribute(geometry);
|
|
}
|
|
return wireframeAttributes.get(geometry);
|
|
}
|
|
return {
|
|
get,
|
|
update,
|
|
getWireframeAttribute
|
|
};
|
|
}
|
|
function WebGLIndexedBufferRenderer(gl, extensions, info, capabilities) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
let mode;
|
|
function setMode(value) {
|
|
mode = value;
|
|
}
|
|
let type, bytesPerElement;
|
|
function setIndex(value) {
|
|
type = value.type;
|
|
bytesPerElement = value.bytesPerElement;
|
|
}
|
|
function render(start, count) {
|
|
gl.drawElements(mode, count, type, start * bytesPerElement);
|
|
info.update(count, mode, 1);
|
|
}
|
|
function renderInstances(start, count, primcount) {
|
|
if (primcount === 0)
|
|
return;
|
|
let extension, methodName;
|
|
if (isWebGL2) {
|
|
extension = gl;
|
|
methodName = "drawElementsInstanced";
|
|
} else {
|
|
extension = extensions.get("ANGLE_instanced_arrays");
|
|
methodName = "drawElementsInstancedANGLE";
|
|
if (extension === null) {
|
|
console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");
|
|
return;
|
|
}
|
|
}
|
|
extension[methodName](mode, count, type, start * bytesPerElement, primcount);
|
|
info.update(count, mode, primcount);
|
|
}
|
|
this.setMode = setMode;
|
|
this.setIndex = setIndex;
|
|
this.render = render;
|
|
this.renderInstances = renderInstances;
|
|
}
|
|
function WebGLInfo(gl) {
|
|
const memory = {
|
|
geometries: 0,
|
|
textures: 0
|
|
};
|
|
const render = {
|
|
frame: 0,
|
|
calls: 0,
|
|
triangles: 0,
|
|
points: 0,
|
|
lines: 0
|
|
};
|
|
function update(count, mode, instanceCount) {
|
|
render.calls++;
|
|
switch (mode) {
|
|
case 4:
|
|
render.triangles += instanceCount * (count / 3);
|
|
break;
|
|
case 1:
|
|
render.lines += instanceCount * (count / 2);
|
|
break;
|
|
case 3:
|
|
render.lines += instanceCount * (count - 1);
|
|
break;
|
|
case 2:
|
|
render.lines += instanceCount * count;
|
|
break;
|
|
case 0:
|
|
render.points += instanceCount * count;
|
|
break;
|
|
default:
|
|
console.error("THREE.WebGLInfo: Unknown draw mode:", mode);
|
|
break;
|
|
}
|
|
}
|
|
function reset() {
|
|
render.frame++;
|
|
render.calls = 0;
|
|
render.triangles = 0;
|
|
render.points = 0;
|
|
render.lines = 0;
|
|
}
|
|
return {
|
|
memory,
|
|
render,
|
|
programs: null,
|
|
autoReset: true,
|
|
reset,
|
|
update
|
|
};
|
|
}
|
|
function numericalSort(a2, b2) {
|
|
return a2[0] - b2[0];
|
|
}
|
|
function absNumericalSort(a2, b2) {
|
|
return Math.abs(b2[1]) - Math.abs(a2[1]);
|
|
}
|
|
function WebGLMorphtargets(gl) {
|
|
const influencesList = {};
|
|
const morphInfluences = new Float32Array(8);
|
|
const workInfluences = [];
|
|
for (let i = 0; i < 8; i++) {
|
|
workInfluences[i] = [i, 0];
|
|
}
|
|
function update(object, geometry, material, program) {
|
|
const objectInfluences = object.morphTargetInfluences;
|
|
const length = objectInfluences === void 0 ? 0 : objectInfluences.length;
|
|
let influences = influencesList[geometry.id];
|
|
if (influences === void 0 || influences.length !== length) {
|
|
influences = [];
|
|
for (let i = 0; i < length; i++) {
|
|
influences[i] = [i, 0];
|
|
}
|
|
influencesList[geometry.id] = influences;
|
|
}
|
|
for (let i = 0; i < length; i++) {
|
|
const influence = influences[i];
|
|
influence[0] = i;
|
|
influence[1] = objectInfluences[i];
|
|
}
|
|
influences.sort(absNumericalSort);
|
|
for (let i = 0; i < 8; i++) {
|
|
if (i < length && influences[i][1]) {
|
|
workInfluences[i][0] = influences[i][0];
|
|
workInfluences[i][1] = influences[i][1];
|
|
} else {
|
|
workInfluences[i][0] = Number.MAX_SAFE_INTEGER;
|
|
workInfluences[i][1] = 0;
|
|
}
|
|
}
|
|
workInfluences.sort(numericalSort);
|
|
const morphTargets = geometry.morphAttributes.position;
|
|
const morphNormals = geometry.morphAttributes.normal;
|
|
let morphInfluencesSum = 0;
|
|
for (let i = 0; i < 8; i++) {
|
|
const influence = workInfluences[i];
|
|
const index = influence[0];
|
|
const value = influence[1];
|
|
if (index !== Number.MAX_SAFE_INTEGER && value) {
|
|
if (morphTargets && geometry.getAttribute("morphTarget" + i) !== morphTargets[index]) {
|
|
geometry.setAttribute("morphTarget" + i, morphTargets[index]);
|
|
}
|
|
if (morphNormals && geometry.getAttribute("morphNormal" + i) !== morphNormals[index]) {
|
|
geometry.setAttribute("morphNormal" + i, morphNormals[index]);
|
|
}
|
|
morphInfluences[i] = value;
|
|
morphInfluencesSum += value;
|
|
} else {
|
|
if (morphTargets && geometry.hasAttribute("morphTarget" + i) === true) {
|
|
geometry.deleteAttribute("morphTarget" + i);
|
|
}
|
|
if (morphNormals && geometry.hasAttribute("morphNormal" + i) === true) {
|
|
geometry.deleteAttribute("morphNormal" + i);
|
|
}
|
|
morphInfluences[i] = 0;
|
|
}
|
|
}
|
|
const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
|
|
program.getUniforms().setValue(gl, "morphTargetBaseInfluence", morphBaseInfluence);
|
|
program.getUniforms().setValue(gl, "morphTargetInfluences", morphInfluences);
|
|
}
|
|
return {
|
|
update
|
|
};
|
|
}
|
|
function WebGLObjects(gl, geometries, attributes, info) {
|
|
let updateMap = new WeakMap();
|
|
function update(object) {
|
|
const frame = info.render.frame;
|
|
const geometry = object.geometry;
|
|
const buffergeometry = geometries.get(object, geometry);
|
|
if (updateMap.get(buffergeometry) !== frame) {
|
|
geometries.update(buffergeometry);
|
|
updateMap.set(buffergeometry, frame);
|
|
}
|
|
if (object.isInstancedMesh) {
|
|
if (object.hasEventListener("dispose", onInstancedMeshDispose) === false) {
|
|
object.addEventListener("dispose", onInstancedMeshDispose);
|
|
}
|
|
attributes.update(object.instanceMatrix, 34962);
|
|
if (object.instanceColor !== null) {
|
|
attributes.update(object.instanceColor, 34962);
|
|
}
|
|
}
|
|
return buffergeometry;
|
|
}
|
|
function dispose() {
|
|
updateMap = new WeakMap();
|
|
}
|
|
function onInstancedMeshDispose(event) {
|
|
const instancedMesh = event.target;
|
|
instancedMesh.removeEventListener("dispose", onInstancedMeshDispose);
|
|
attributes.remove(instancedMesh.instanceMatrix);
|
|
if (instancedMesh.instanceColor !== null)
|
|
attributes.remove(instancedMesh.instanceColor);
|
|
}
|
|
return {
|
|
update,
|
|
dispose
|
|
};
|
|
}
|
|
var DataTexture2DArray = class extends Texture {
|
|
constructor(data = null, width = 1, height = 1, depth = 1) {
|
|
super(null);
|
|
this.image = { data, width, height, depth };
|
|
this.magFilter = NearestFilter;
|
|
this.minFilter = NearestFilter;
|
|
this.wrapR = ClampToEdgeWrapping;
|
|
this.generateMipmaps = false;
|
|
this.flipY = false;
|
|
this.unpackAlignment = 1;
|
|
this.needsUpdate = true;
|
|
}
|
|
};
|
|
DataTexture2DArray.prototype.isDataTexture2DArray = true;
|
|
var DataTexture3D = class extends Texture {
|
|
constructor(data = null, width = 1, height = 1, depth = 1) {
|
|
super(null);
|
|
this.image = { data, width, height, depth };
|
|
this.magFilter = NearestFilter;
|
|
this.minFilter = NearestFilter;
|
|
this.wrapR = ClampToEdgeWrapping;
|
|
this.generateMipmaps = false;
|
|
this.flipY = false;
|
|
this.unpackAlignment = 1;
|
|
this.needsUpdate = true;
|
|
}
|
|
};
|
|
DataTexture3D.prototype.isDataTexture3D = true;
|
|
var emptyTexture = new Texture();
|
|
var emptyTexture2dArray = new DataTexture2DArray();
|
|
var emptyTexture3d = new DataTexture3D();
|
|
var emptyCubeTexture = new CubeTexture();
|
|
var arrayCacheF32 = [];
|
|
var arrayCacheI32 = [];
|
|
var mat4array = new Float32Array(16);
|
|
var mat3array = new Float32Array(9);
|
|
var mat2array = new Float32Array(4);
|
|
function flatten(array, nBlocks, blockSize) {
|
|
const firstElem = array[0];
|
|
if (firstElem <= 0 || firstElem > 0)
|
|
return array;
|
|
const n = nBlocks * blockSize;
|
|
let r = arrayCacheF32[n];
|
|
if (r === void 0) {
|
|
r = new Float32Array(n);
|
|
arrayCacheF32[n] = r;
|
|
}
|
|
if (nBlocks !== 0) {
|
|
firstElem.toArray(r, 0);
|
|
for (let i = 1, offset = 0; i !== nBlocks; ++i) {
|
|
offset += blockSize;
|
|
array[i].toArray(r, offset);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
function arraysEqual(a2, b2) {
|
|
if (a2.length !== b2.length)
|
|
return false;
|
|
for (let i = 0, l = a2.length; i < l; i++) {
|
|
if (a2[i] !== b2[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function copyArray(a2, b2) {
|
|
for (let i = 0, l = b2.length; i < l; i++) {
|
|
a2[i] = b2[i];
|
|
}
|
|
}
|
|
function allocTexUnits(textures, n) {
|
|
let r = arrayCacheI32[n];
|
|
if (r === void 0) {
|
|
r = new Int32Array(n);
|
|
arrayCacheI32[n] = r;
|
|
}
|
|
for (let i = 0; i !== n; ++i) {
|
|
r[i] = textures.allocateTextureUnit();
|
|
}
|
|
return r;
|
|
}
|
|
function setValueV1f(gl, v) {
|
|
const cache = this.cache;
|
|
if (cache[0] === v)
|
|
return;
|
|
gl.uniform1f(this.addr, v);
|
|
cache[0] = v;
|
|
}
|
|
function setValueV2f(gl, v) {
|
|
const cache = this.cache;
|
|
if (v.x !== void 0) {
|
|
if (cache[0] !== v.x || cache[1] !== v.y) {
|
|
gl.uniform2f(this.addr, v.x, v.y);
|
|
cache[0] = v.x;
|
|
cache[1] = v.y;
|
|
}
|
|
} else {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform2fv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
}
|
|
function setValueV3f(gl, v) {
|
|
const cache = this.cache;
|
|
if (v.x !== void 0) {
|
|
if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) {
|
|
gl.uniform3f(this.addr, v.x, v.y, v.z);
|
|
cache[0] = v.x;
|
|
cache[1] = v.y;
|
|
cache[2] = v.z;
|
|
}
|
|
} else if (v.r !== void 0) {
|
|
if (cache[0] !== v.r || cache[1] !== v.g || cache[2] !== v.b) {
|
|
gl.uniform3f(this.addr, v.r, v.g, v.b);
|
|
cache[0] = v.r;
|
|
cache[1] = v.g;
|
|
cache[2] = v.b;
|
|
}
|
|
} else {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform3fv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
}
|
|
function setValueV4f(gl, v) {
|
|
const cache = this.cache;
|
|
if (v.x !== void 0) {
|
|
if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z || cache[3] !== v.w) {
|
|
gl.uniform4f(this.addr, v.x, v.y, v.z, v.w);
|
|
cache[0] = v.x;
|
|
cache[1] = v.y;
|
|
cache[2] = v.z;
|
|
cache[3] = v.w;
|
|
}
|
|
} else {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform4fv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
}
|
|
function setValueM2(gl, v) {
|
|
const cache = this.cache;
|
|
const elements = v.elements;
|
|
if (elements === void 0) {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniformMatrix2fv(this.addr, false, v);
|
|
copyArray(cache, v);
|
|
} else {
|
|
if (arraysEqual(cache, elements))
|
|
return;
|
|
mat2array.set(elements);
|
|
gl.uniformMatrix2fv(this.addr, false, mat2array);
|
|
copyArray(cache, elements);
|
|
}
|
|
}
|
|
function setValueM3(gl, v) {
|
|
const cache = this.cache;
|
|
const elements = v.elements;
|
|
if (elements === void 0) {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniformMatrix3fv(this.addr, false, v);
|
|
copyArray(cache, v);
|
|
} else {
|
|
if (arraysEqual(cache, elements))
|
|
return;
|
|
mat3array.set(elements);
|
|
gl.uniformMatrix3fv(this.addr, false, mat3array);
|
|
copyArray(cache, elements);
|
|
}
|
|
}
|
|
function setValueM4(gl, v) {
|
|
const cache = this.cache;
|
|
const elements = v.elements;
|
|
if (elements === void 0) {
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniformMatrix4fv(this.addr, false, v);
|
|
copyArray(cache, v);
|
|
} else {
|
|
if (arraysEqual(cache, elements))
|
|
return;
|
|
mat4array.set(elements);
|
|
gl.uniformMatrix4fv(this.addr, false, mat4array);
|
|
copyArray(cache, elements);
|
|
}
|
|
}
|
|
function setValueV1i(gl, v) {
|
|
const cache = this.cache;
|
|
if (cache[0] === v)
|
|
return;
|
|
gl.uniform1i(this.addr, v);
|
|
cache[0] = v;
|
|
}
|
|
function setValueV2i(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform2iv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueV3i(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform3iv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueV4i(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform4iv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueV1ui(gl, v) {
|
|
const cache = this.cache;
|
|
if (cache[0] === v)
|
|
return;
|
|
gl.uniform1ui(this.addr, v);
|
|
cache[0] = v;
|
|
}
|
|
function setValueV2ui(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform2uiv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueV3ui(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform3uiv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueV4ui(gl, v) {
|
|
const cache = this.cache;
|
|
if (arraysEqual(cache, v))
|
|
return;
|
|
gl.uniform4uiv(this.addr, v);
|
|
copyArray(cache, v);
|
|
}
|
|
function setValueT1(gl, v, textures) {
|
|
const cache = this.cache;
|
|
const unit = textures.allocateTextureUnit();
|
|
if (cache[0] !== unit) {
|
|
gl.uniform1i(this.addr, unit);
|
|
cache[0] = unit;
|
|
}
|
|
textures.safeSetTexture2D(v || emptyTexture, unit);
|
|
}
|
|
function setValueT3D1(gl, v, textures) {
|
|
const cache = this.cache;
|
|
const unit = textures.allocateTextureUnit();
|
|
if (cache[0] !== unit) {
|
|
gl.uniform1i(this.addr, unit);
|
|
cache[0] = unit;
|
|
}
|
|
textures.setTexture3D(v || emptyTexture3d, unit);
|
|
}
|
|
function setValueT6(gl, v, textures) {
|
|
const cache = this.cache;
|
|
const unit = textures.allocateTextureUnit();
|
|
if (cache[0] !== unit) {
|
|
gl.uniform1i(this.addr, unit);
|
|
cache[0] = unit;
|
|
}
|
|
textures.safeSetTextureCube(v || emptyCubeTexture, unit);
|
|
}
|
|
function setValueT2DArray1(gl, v, textures) {
|
|
const cache = this.cache;
|
|
const unit = textures.allocateTextureUnit();
|
|
if (cache[0] !== unit) {
|
|
gl.uniform1i(this.addr, unit);
|
|
cache[0] = unit;
|
|
}
|
|
textures.setTexture2DArray(v || emptyTexture2dArray, unit);
|
|
}
|
|
function getSingularSetter(type) {
|
|
switch (type) {
|
|
case 5126:
|
|
return setValueV1f;
|
|
case 35664:
|
|
return setValueV2f;
|
|
case 35665:
|
|
return setValueV3f;
|
|
case 35666:
|
|
return setValueV4f;
|
|
case 35674:
|
|
return setValueM2;
|
|
case 35675:
|
|
return setValueM3;
|
|
case 35676:
|
|
return setValueM4;
|
|
case 5124:
|
|
case 35670:
|
|
return setValueV1i;
|
|
case 35667:
|
|
case 35671:
|
|
return setValueV2i;
|
|
case 35668:
|
|
case 35672:
|
|
return setValueV3i;
|
|
case 35669:
|
|
case 35673:
|
|
return setValueV4i;
|
|
case 5125:
|
|
return setValueV1ui;
|
|
case 36294:
|
|
return setValueV2ui;
|
|
case 36295:
|
|
return setValueV3ui;
|
|
case 36296:
|
|
return setValueV4ui;
|
|
case 35678:
|
|
case 36198:
|
|
case 36298:
|
|
case 36306:
|
|
case 35682:
|
|
return setValueT1;
|
|
case 35679:
|
|
case 36299:
|
|
case 36307:
|
|
return setValueT3D1;
|
|
case 35680:
|
|
case 36300:
|
|
case 36308:
|
|
case 36293:
|
|
return setValueT6;
|
|
case 36289:
|
|
case 36303:
|
|
case 36311:
|
|
case 36292:
|
|
return setValueT2DArray1;
|
|
}
|
|
}
|
|
function setValueV1fArray(gl, v) {
|
|
gl.uniform1fv(this.addr, v);
|
|
}
|
|
function setValueV2fArray(gl, v) {
|
|
const data = flatten(v, this.size, 2);
|
|
gl.uniform2fv(this.addr, data);
|
|
}
|
|
function setValueV3fArray(gl, v) {
|
|
const data = flatten(v, this.size, 3);
|
|
gl.uniform3fv(this.addr, data);
|
|
}
|
|
function setValueV4fArray(gl, v) {
|
|
const data = flatten(v, this.size, 4);
|
|
gl.uniform4fv(this.addr, data);
|
|
}
|
|
function setValueM2Array(gl, v) {
|
|
const data = flatten(v, this.size, 4);
|
|
gl.uniformMatrix2fv(this.addr, false, data);
|
|
}
|
|
function setValueM3Array(gl, v) {
|
|
const data = flatten(v, this.size, 9);
|
|
gl.uniformMatrix3fv(this.addr, false, data);
|
|
}
|
|
function setValueM4Array(gl, v) {
|
|
const data = flatten(v, this.size, 16);
|
|
gl.uniformMatrix4fv(this.addr, false, data);
|
|
}
|
|
function setValueV1iArray(gl, v) {
|
|
gl.uniform1iv(this.addr, v);
|
|
}
|
|
function setValueV2iArray(gl, v) {
|
|
gl.uniform2iv(this.addr, v);
|
|
}
|
|
function setValueV3iArray(gl, v) {
|
|
gl.uniform3iv(this.addr, v);
|
|
}
|
|
function setValueV4iArray(gl, v) {
|
|
gl.uniform4iv(this.addr, v);
|
|
}
|
|
function setValueV1uiArray(gl, v) {
|
|
gl.uniform1uiv(this.addr, v);
|
|
}
|
|
function setValueV2uiArray(gl, v) {
|
|
gl.uniform2uiv(this.addr, v);
|
|
}
|
|
function setValueV3uiArray(gl, v) {
|
|
gl.uniform3uiv(this.addr, v);
|
|
}
|
|
function setValueV4uiArray(gl, v) {
|
|
gl.uniform4uiv(this.addr, v);
|
|
}
|
|
function setValueT1Array(gl, v, textures) {
|
|
const n = v.length;
|
|
const units = allocTexUnits(textures, n);
|
|
gl.uniform1iv(this.addr, units);
|
|
for (let i = 0; i !== n; ++i) {
|
|
textures.safeSetTexture2D(v[i] || emptyTexture, units[i]);
|
|
}
|
|
}
|
|
function setValueT6Array(gl, v, textures) {
|
|
const n = v.length;
|
|
const units = allocTexUnits(textures, n);
|
|
gl.uniform1iv(this.addr, units);
|
|
for (let i = 0; i !== n; ++i) {
|
|
textures.safeSetTextureCube(v[i] || emptyCubeTexture, units[i]);
|
|
}
|
|
}
|
|
function getPureArraySetter(type) {
|
|
switch (type) {
|
|
case 5126:
|
|
return setValueV1fArray;
|
|
case 35664:
|
|
return setValueV2fArray;
|
|
case 35665:
|
|
return setValueV3fArray;
|
|
case 35666:
|
|
return setValueV4fArray;
|
|
case 35674:
|
|
return setValueM2Array;
|
|
case 35675:
|
|
return setValueM3Array;
|
|
case 35676:
|
|
return setValueM4Array;
|
|
case 5124:
|
|
case 35670:
|
|
return setValueV1iArray;
|
|
case 35667:
|
|
case 35671:
|
|
return setValueV2iArray;
|
|
case 35668:
|
|
case 35672:
|
|
return setValueV3iArray;
|
|
case 35669:
|
|
case 35673:
|
|
return setValueV4iArray;
|
|
case 5125:
|
|
return setValueV1uiArray;
|
|
case 36294:
|
|
return setValueV2uiArray;
|
|
case 36295:
|
|
return setValueV3uiArray;
|
|
case 36296:
|
|
return setValueV4uiArray;
|
|
case 35678:
|
|
case 36198:
|
|
case 36298:
|
|
case 36306:
|
|
case 35682:
|
|
return setValueT1Array;
|
|
case 35680:
|
|
case 36300:
|
|
case 36308:
|
|
case 36293:
|
|
return setValueT6Array;
|
|
}
|
|
}
|
|
function SingleUniform(id, activeInfo, addr) {
|
|
this.id = id;
|
|
this.addr = addr;
|
|
this.cache = [];
|
|
this.setValue = getSingularSetter(activeInfo.type);
|
|
}
|
|
function PureArrayUniform(id, activeInfo, addr) {
|
|
this.id = id;
|
|
this.addr = addr;
|
|
this.cache = [];
|
|
this.size = activeInfo.size;
|
|
this.setValue = getPureArraySetter(activeInfo.type);
|
|
}
|
|
PureArrayUniform.prototype.updateCache = function(data) {
|
|
const cache = this.cache;
|
|
if (data instanceof Float32Array && cache.length !== data.length) {
|
|
this.cache = new Float32Array(data.length);
|
|
}
|
|
copyArray(cache, data);
|
|
};
|
|
function StructuredUniform(id) {
|
|
this.id = id;
|
|
this.seq = [];
|
|
this.map = {};
|
|
}
|
|
StructuredUniform.prototype.setValue = function(gl, value, textures) {
|
|
const seq = this.seq;
|
|
for (let i = 0, n = seq.length; i !== n; ++i) {
|
|
const u = seq[i];
|
|
u.setValue(gl, value[u.id], textures);
|
|
}
|
|
};
|
|
var RePathPart = /(\w+)(\])?(\[|\.)?/g;
|
|
function addUniform(container, uniformObject) {
|
|
container.seq.push(uniformObject);
|
|
container.map[uniformObject.id] = uniformObject;
|
|
}
|
|
function parseUniform(activeInfo, addr, container) {
|
|
const path = activeInfo.name, pathLength = path.length;
|
|
RePathPart.lastIndex = 0;
|
|
while (true) {
|
|
const match = RePathPart.exec(path), matchEnd = RePathPart.lastIndex;
|
|
let id = match[1];
|
|
const idIsIndex = match[2] === "]", subscript = match[3];
|
|
if (idIsIndex)
|
|
id = id | 0;
|
|
if (subscript === void 0 || subscript === "[" && matchEnd + 2 === pathLength) {
|
|
addUniform(container, subscript === void 0 ? new SingleUniform(id, activeInfo, addr) : new PureArrayUniform(id, activeInfo, addr));
|
|
break;
|
|
} else {
|
|
const map = container.map;
|
|
let next = map[id];
|
|
if (next === void 0) {
|
|
next = new StructuredUniform(id);
|
|
addUniform(container, next);
|
|
}
|
|
container = next;
|
|
}
|
|
}
|
|
}
|
|
function WebGLUniforms(gl, program) {
|
|
this.seq = [];
|
|
this.map = {};
|
|
const n = gl.getProgramParameter(program, 35718);
|
|
for (let i = 0; i < n; ++i) {
|
|
const info = gl.getActiveUniform(program, i), addr = gl.getUniformLocation(program, info.name);
|
|
parseUniform(info, addr, this);
|
|
}
|
|
}
|
|
WebGLUniforms.prototype.setValue = function(gl, name, value, textures) {
|
|
const u = this.map[name];
|
|
if (u !== void 0)
|
|
u.setValue(gl, value, textures);
|
|
};
|
|
WebGLUniforms.prototype.setOptional = function(gl, object, name) {
|
|
const v = object[name];
|
|
if (v !== void 0)
|
|
this.setValue(gl, name, v);
|
|
};
|
|
WebGLUniforms.upload = function(gl, seq, values, textures) {
|
|
for (let i = 0, n = seq.length; i !== n; ++i) {
|
|
const u = seq[i], v = values[u.id];
|
|
if (v.needsUpdate !== false) {
|
|
u.setValue(gl, v.value, textures);
|
|
}
|
|
}
|
|
};
|
|
WebGLUniforms.seqWithValue = function(seq, values) {
|
|
const r = [];
|
|
for (let i = 0, n = seq.length; i !== n; ++i) {
|
|
const u = seq[i];
|
|
if (u.id in values)
|
|
r.push(u);
|
|
}
|
|
return r;
|
|
};
|
|
function WebGLShader(gl, type, string) {
|
|
const shader = gl.createShader(type);
|
|
gl.shaderSource(shader, string);
|
|
gl.compileShader(shader);
|
|
return shader;
|
|
}
|
|
var programIdCount = 0;
|
|
function addLineNumbers(string) {
|
|
const lines = string.split("\n");
|
|
for (let i = 0; i < lines.length; i++) {
|
|
lines[i] = i + 1 + ": " + lines[i];
|
|
}
|
|
return lines.join("\n");
|
|
}
|
|
function getEncodingComponents(encoding) {
|
|
switch (encoding) {
|
|
case LinearEncoding:
|
|
return ["Linear", "( value )"];
|
|
case sRGBEncoding:
|
|
return ["sRGB", "( value )"];
|
|
case RGBEEncoding:
|
|
return ["RGBE", "( value )"];
|
|
case RGBM7Encoding:
|
|
return ["RGBM", "( value, 7.0 )"];
|
|
case RGBM16Encoding:
|
|
return ["RGBM", "( value, 16.0 )"];
|
|
case RGBDEncoding:
|
|
return ["RGBD", "( value, 256.0 )"];
|
|
case GammaEncoding:
|
|
return ["Gamma", "( value, float( GAMMA_FACTOR ) )"];
|
|
case LogLuvEncoding:
|
|
return ["LogLuv", "( value )"];
|
|
default:
|
|
console.warn("THREE.WebGLProgram: Unsupported encoding:", encoding);
|
|
return ["Linear", "( value )"];
|
|
}
|
|
}
|
|
function getShaderErrors(gl, shader, type) {
|
|
const status = gl.getShaderParameter(shader, 35713);
|
|
const errors = gl.getShaderInfoLog(shader).trim();
|
|
if (status && errors === "")
|
|
return "";
|
|
return type.toUpperCase() + "\n\n" + errors + "\n\n" + addLineNumbers(gl.getShaderSource(shader));
|
|
}
|
|
function getTexelDecodingFunction(functionName, encoding) {
|
|
const components = getEncodingComponents(encoding);
|
|
return "vec4 " + functionName + "( vec4 value ) { return " + components[0] + "ToLinear" + components[1] + "; }";
|
|
}
|
|
function getTexelEncodingFunction(functionName, encoding) {
|
|
const components = getEncodingComponents(encoding);
|
|
return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }";
|
|
}
|
|
function getToneMappingFunction(functionName, toneMapping) {
|
|
let toneMappingName;
|
|
switch (toneMapping) {
|
|
case LinearToneMapping:
|
|
toneMappingName = "Linear";
|
|
break;
|
|
case ReinhardToneMapping:
|
|
toneMappingName = "Reinhard";
|
|
break;
|
|
case CineonToneMapping:
|
|
toneMappingName = "OptimizedCineon";
|
|
break;
|
|
case ACESFilmicToneMapping:
|
|
toneMappingName = "ACESFilmic";
|
|
break;
|
|
case CustomToneMapping:
|
|
toneMappingName = "Custom";
|
|
break;
|
|
default:
|
|
console.warn("THREE.WebGLProgram: Unsupported toneMapping:", toneMapping);
|
|
toneMappingName = "Linear";
|
|
}
|
|
return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
|
|
}
|
|
function generateExtensions(parameters) {
|
|
const chunks = [
|
|
parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === "physical" ? "#extension GL_OES_standard_derivatives : enable" : "",
|
|
(parameters.extensionFragDepth || parameters.logarithmicDepthBuffer) && parameters.rendererExtensionFragDepth ? "#extension GL_EXT_frag_depth : enable" : "",
|
|
parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ? "#extension GL_EXT_draw_buffers : require" : "",
|
|
(parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission) && parameters.rendererExtensionShaderTextureLod ? "#extension GL_EXT_shader_texture_lod : enable" : ""
|
|
];
|
|
return chunks.filter(filterEmptyLine).join("\n");
|
|
}
|
|
function generateDefines(defines) {
|
|
const chunks = [];
|
|
for (const name in defines) {
|
|
const value = defines[name];
|
|
if (value === false)
|
|
continue;
|
|
chunks.push("#define " + name + " " + value);
|
|
}
|
|
return chunks.join("\n");
|
|
}
|
|
function fetchAttributeLocations(gl, program) {
|
|
const attributes = {};
|
|
const n = gl.getProgramParameter(program, 35721);
|
|
for (let i = 0; i < n; i++) {
|
|
const info = gl.getActiveAttrib(program, i);
|
|
const name = info.name;
|
|
let locationSize = 1;
|
|
if (info.type === 35674)
|
|
locationSize = 2;
|
|
if (info.type === 35675)
|
|
locationSize = 3;
|
|
if (info.type === 35676)
|
|
locationSize = 4;
|
|
attributes[name] = {
|
|
type: info.type,
|
|
location: gl.getAttribLocation(program, name),
|
|
locationSize
|
|
};
|
|
}
|
|
return attributes;
|
|
}
|
|
function filterEmptyLine(string) {
|
|
return string !== "";
|
|
}
|
|
function replaceLightNums(string, parameters) {
|
|
return string.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows);
|
|
}
|
|
function replaceClippingPlaneNums(string, parameters) {
|
|
return string.replace(/NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g, parameters.numClippingPlanes - parameters.numClipIntersection);
|
|
}
|
|
var includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
|
|
function resolveIncludes(string) {
|
|
return string.replace(includePattern, includeReplacer);
|
|
}
|
|
function includeReplacer(match, include) {
|
|
const string = ShaderChunk[include];
|
|
if (string === void 0) {
|
|
throw new Error("Can not resolve #include <" + include + ">");
|
|
}
|
|
return resolveIncludes(string);
|
|
}
|
|
var deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
|
|
var unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;
|
|
function unrollLoops(string) {
|
|
return string.replace(unrollLoopPattern, loopReplacer).replace(deprecatedUnrollLoopPattern, deprecatedLoopReplacer);
|
|
}
|
|
function deprecatedLoopReplacer(match, start, end, snippet) {
|
|
console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.");
|
|
return loopReplacer(match, start, end, snippet);
|
|
}
|
|
function loopReplacer(match, start, end, snippet) {
|
|
let string = "";
|
|
for (let i = parseInt(start); i < parseInt(end); i++) {
|
|
string += snippet.replace(/\[\s*i\s*\]/g, "[ " + i + " ]").replace(/UNROLLED_LOOP_INDEX/g, i);
|
|
}
|
|
return string;
|
|
}
|
|
function generatePrecision(parameters) {
|
|
let precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;";
|
|
if (parameters.precision === "highp") {
|
|
precisionstring += "\n#define HIGH_PRECISION";
|
|
} else if (parameters.precision === "mediump") {
|
|
precisionstring += "\n#define MEDIUM_PRECISION";
|
|
} else if (parameters.precision === "lowp") {
|
|
precisionstring += "\n#define LOW_PRECISION";
|
|
}
|
|
return precisionstring;
|
|
}
|
|
function generateShadowMapTypeDefine(parameters) {
|
|
let shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
|
|
if (parameters.shadowMapType === PCFShadowMap) {
|
|
shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
|
|
} else if (parameters.shadowMapType === PCFSoftShadowMap) {
|
|
shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
|
|
} else if (parameters.shadowMapType === VSMShadowMap) {
|
|
shadowMapTypeDefine = "SHADOWMAP_TYPE_VSM";
|
|
}
|
|
return shadowMapTypeDefine;
|
|
}
|
|
function generateEnvMapTypeDefine(parameters) {
|
|
let envMapTypeDefine = "ENVMAP_TYPE_CUBE";
|
|
if (parameters.envMap) {
|
|
switch (parameters.envMapMode) {
|
|
case CubeReflectionMapping:
|
|
case CubeRefractionMapping:
|
|
envMapTypeDefine = "ENVMAP_TYPE_CUBE";
|
|
break;
|
|
case CubeUVReflectionMapping:
|
|
case CubeUVRefractionMapping:
|
|
envMapTypeDefine = "ENVMAP_TYPE_CUBE_UV";
|
|
break;
|
|
}
|
|
}
|
|
return envMapTypeDefine;
|
|
}
|
|
function generateEnvMapModeDefine(parameters) {
|
|
let envMapModeDefine = "ENVMAP_MODE_REFLECTION";
|
|
if (parameters.envMap) {
|
|
switch (parameters.envMapMode) {
|
|
case CubeRefractionMapping:
|
|
case CubeUVRefractionMapping:
|
|
envMapModeDefine = "ENVMAP_MODE_REFRACTION";
|
|
break;
|
|
}
|
|
}
|
|
return envMapModeDefine;
|
|
}
|
|
function generateEnvMapBlendingDefine(parameters) {
|
|
let envMapBlendingDefine = "ENVMAP_BLENDING_NONE";
|
|
if (parameters.envMap) {
|
|
switch (parameters.combine) {
|
|
case MultiplyOperation:
|
|
envMapBlendingDefine = "ENVMAP_BLENDING_MULTIPLY";
|
|
break;
|
|
case MixOperation:
|
|
envMapBlendingDefine = "ENVMAP_BLENDING_MIX";
|
|
break;
|
|
case AddOperation:
|
|
envMapBlendingDefine = "ENVMAP_BLENDING_ADD";
|
|
break;
|
|
}
|
|
}
|
|
return envMapBlendingDefine;
|
|
}
|
|
function WebGLProgram(renderer, cacheKey, parameters, bindingStates) {
|
|
const gl = renderer.getContext();
|
|
const defines = parameters.defines;
|
|
let vertexShader = parameters.vertexShader;
|
|
let fragmentShader = parameters.fragmentShader;
|
|
const shadowMapTypeDefine = generateShadowMapTypeDefine(parameters);
|
|
const envMapTypeDefine = generateEnvMapTypeDefine(parameters);
|
|
const envMapModeDefine = generateEnvMapModeDefine(parameters);
|
|
const envMapBlendingDefine = generateEnvMapBlendingDefine(parameters);
|
|
const gammaFactorDefine = renderer.gammaFactor > 0 ? renderer.gammaFactor : 1;
|
|
const customExtensions = parameters.isWebGL2 ? "" : generateExtensions(parameters);
|
|
const customDefines = generateDefines(defines);
|
|
const program = gl.createProgram();
|
|
let prefixVertex, prefixFragment;
|
|
let versionString = parameters.glslVersion ? "#version " + parameters.glslVersion + "\n" : "";
|
|
if (parameters.isRawShaderMaterial) {
|
|
prefixVertex = [
|
|
customDefines
|
|
].filter(filterEmptyLine).join("\n");
|
|
if (prefixVertex.length > 0) {
|
|
prefixVertex += "\n";
|
|
}
|
|
prefixFragment = [
|
|
customExtensions,
|
|
customDefines
|
|
].filter(filterEmptyLine).join("\n");
|
|
if (prefixFragment.length > 0) {
|
|
prefixFragment += "\n";
|
|
}
|
|
} else {
|
|
prefixVertex = [
|
|
generatePrecision(parameters),
|
|
"#define SHADER_NAME " + parameters.shaderName,
|
|
customDefines,
|
|
parameters.instancing ? "#define USE_INSTANCING" : "",
|
|
parameters.instancingColor ? "#define USE_INSTANCING_COLOR" : "",
|
|
parameters.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
|
|
"#define GAMMA_FACTOR " + gammaFactorDefine,
|
|
"#define MAX_BONES " + parameters.maxBones,
|
|
parameters.useFog && parameters.fog ? "#define USE_FOG" : "",
|
|
parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "",
|
|
parameters.map ? "#define USE_MAP" : "",
|
|
parameters.envMap ? "#define USE_ENVMAP" : "",
|
|
parameters.envMap ? "#define " + envMapModeDefine : "",
|
|
parameters.lightMap ? "#define USE_LIGHTMAP" : "",
|
|
parameters.aoMap ? "#define USE_AOMAP" : "",
|
|
parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "",
|
|
parameters.bumpMap ? "#define USE_BUMPMAP" : "",
|
|
parameters.normalMap ? "#define USE_NORMALMAP" : "",
|
|
parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "",
|
|
parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "",
|
|
parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "",
|
|
parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "",
|
|
parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "",
|
|
parameters.displacementMap && parameters.supportsVertexTextures ? "#define USE_DISPLACEMENTMAP" : "",
|
|
parameters.specularMap ? "#define USE_SPECULARMAP" : "",
|
|
parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "",
|
|
parameters.specularTintMap ? "#define USE_SPECULARTINTMAP" : "",
|
|
parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "",
|
|
parameters.metalnessMap ? "#define USE_METALNESSMAP" : "",
|
|
parameters.alphaMap ? "#define USE_ALPHAMAP" : "",
|
|
parameters.transmission ? "#define USE_TRANSMISSION" : "",
|
|
parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "",
|
|
parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "",
|
|
parameters.vertexTangents ? "#define USE_TANGENT" : "",
|
|
parameters.vertexColors ? "#define USE_COLOR" : "",
|
|
parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "",
|
|
parameters.vertexUvs ? "#define USE_UV" : "",
|
|
parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "",
|
|
parameters.flatShading ? "#define FLAT_SHADED" : "",
|
|
parameters.skinning ? "#define USE_SKINNING" : "",
|
|
parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
|
|
parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
|
|
parameters.morphNormals && parameters.flatShading === false ? "#define USE_MORPHNORMALS" : "",
|
|
parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
|
|
parameters.flipSided ? "#define FLIP_SIDED" : "",
|
|
parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
|
|
parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
|
|
parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
|
|
parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "",
|
|
parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "",
|
|
"uniform mat4 modelMatrix;",
|
|
"uniform mat4 modelViewMatrix;",
|
|
"uniform mat4 projectionMatrix;",
|
|
"uniform mat4 viewMatrix;",
|
|
"uniform mat3 normalMatrix;",
|
|
"uniform vec3 cameraPosition;",
|
|
"uniform bool isOrthographic;",
|
|
"#ifdef USE_INSTANCING",
|
|
" attribute mat4 instanceMatrix;",
|
|
"#endif",
|
|
"#ifdef USE_INSTANCING_COLOR",
|
|
" attribute vec3 instanceColor;",
|
|
"#endif",
|
|
"attribute vec3 position;",
|
|
"attribute vec3 normal;",
|
|
"attribute vec2 uv;",
|
|
"#ifdef USE_TANGENT",
|
|
" attribute vec4 tangent;",
|
|
"#endif",
|
|
"#if defined( USE_COLOR_ALPHA )",
|
|
" attribute vec4 color;",
|
|
"#elif defined( USE_COLOR )",
|
|
" attribute vec3 color;",
|
|
"#endif",
|
|
"#ifdef USE_MORPHTARGETS",
|
|
" attribute vec3 morphTarget0;",
|
|
" attribute vec3 morphTarget1;",
|
|
" attribute vec3 morphTarget2;",
|
|
" attribute vec3 morphTarget3;",
|
|
" #ifdef USE_MORPHNORMALS",
|
|
" attribute vec3 morphNormal0;",
|
|
" attribute vec3 morphNormal1;",
|
|
" attribute vec3 morphNormal2;",
|
|
" attribute vec3 morphNormal3;",
|
|
" #else",
|
|
" attribute vec3 morphTarget4;",
|
|
" attribute vec3 morphTarget5;",
|
|
" attribute vec3 morphTarget6;",
|
|
" attribute vec3 morphTarget7;",
|
|
" #endif",
|
|
"#endif",
|
|
"#ifdef USE_SKINNING",
|
|
" attribute vec4 skinIndex;",
|
|
" attribute vec4 skinWeight;",
|
|
"#endif",
|
|
"\n"
|
|
].filter(filterEmptyLine).join("\n");
|
|
prefixFragment = [
|
|
customExtensions,
|
|
generatePrecision(parameters),
|
|
"#define SHADER_NAME " + parameters.shaderName,
|
|
customDefines,
|
|
"#define GAMMA_FACTOR " + gammaFactorDefine,
|
|
parameters.useFog && parameters.fog ? "#define USE_FOG" : "",
|
|
parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "",
|
|
parameters.map ? "#define USE_MAP" : "",
|
|
parameters.matcap ? "#define USE_MATCAP" : "",
|
|
parameters.envMap ? "#define USE_ENVMAP" : "",
|
|
parameters.envMap ? "#define " + envMapTypeDefine : "",
|
|
parameters.envMap ? "#define " + envMapModeDefine : "",
|
|
parameters.envMap ? "#define " + envMapBlendingDefine : "",
|
|
parameters.lightMap ? "#define USE_LIGHTMAP" : "",
|
|
parameters.aoMap ? "#define USE_AOMAP" : "",
|
|
parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "",
|
|
parameters.bumpMap ? "#define USE_BUMPMAP" : "",
|
|
parameters.normalMap ? "#define USE_NORMALMAP" : "",
|
|
parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "",
|
|
parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "",
|
|
parameters.clearcoat ? "#define USE_CLEARCOAT" : "",
|
|
parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "",
|
|
parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "",
|
|
parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "",
|
|
parameters.specularMap ? "#define USE_SPECULARMAP" : "",
|
|
parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "",
|
|
parameters.specularTintMap ? "#define USE_SPECULARTINTMAP" : "",
|
|
parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "",
|
|
parameters.metalnessMap ? "#define USE_METALNESSMAP" : "",
|
|
parameters.alphaMap ? "#define USE_ALPHAMAP" : "",
|
|
parameters.alphaTest ? "#define USE_ALPHATEST" : "",
|
|
parameters.sheenTint ? "#define USE_SHEEN" : "",
|
|
parameters.transmission ? "#define USE_TRANSMISSION" : "",
|
|
parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "",
|
|
parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "",
|
|
parameters.vertexTangents ? "#define USE_TANGENT" : "",
|
|
parameters.vertexColors || parameters.instancingColor ? "#define USE_COLOR" : "",
|
|
parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "",
|
|
parameters.vertexUvs ? "#define USE_UV" : "",
|
|
parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "",
|
|
parameters.gradientMap ? "#define USE_GRADIENTMAP" : "",
|
|
parameters.flatShading ? "#define FLAT_SHADED" : "",
|
|
parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
|
|
parameters.flipSided ? "#define FLIP_SIDED" : "",
|
|
parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
|
|
parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
|
|
parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : "",
|
|
parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : "",
|
|
parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "",
|
|
parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "",
|
|
(parameters.extensionShaderTextureLOD || parameters.envMap) && parameters.rendererExtensionShaderTextureLod ? "#define TEXTURE_LOD_EXT" : "",
|
|
"uniform mat4 viewMatrix;",
|
|
"uniform vec3 cameraPosition;",
|
|
"uniform bool isOrthographic;",
|
|
parameters.toneMapping !== NoToneMapping ? "#define TONE_MAPPING" : "",
|
|
parameters.toneMapping !== NoToneMapping ? ShaderChunk["tonemapping_pars_fragment"] : "",
|
|
parameters.toneMapping !== NoToneMapping ? getToneMappingFunction("toneMapping", parameters.toneMapping) : "",
|
|
parameters.dithering ? "#define DITHERING" : "",
|
|
parameters.format === RGBFormat ? "#define OPAQUE" : "",
|
|
ShaderChunk["encodings_pars_fragment"],
|
|
parameters.map ? getTexelDecodingFunction("mapTexelToLinear", parameters.mapEncoding) : "",
|
|
parameters.matcap ? getTexelDecodingFunction("matcapTexelToLinear", parameters.matcapEncoding) : "",
|
|
parameters.envMap ? getTexelDecodingFunction("envMapTexelToLinear", parameters.envMapEncoding) : "",
|
|
parameters.emissiveMap ? getTexelDecodingFunction("emissiveMapTexelToLinear", parameters.emissiveMapEncoding) : "",
|
|
parameters.specularTintMap ? getTexelDecodingFunction("specularTintMapTexelToLinear", parameters.specularTintMapEncoding) : "",
|
|
parameters.lightMap ? getTexelDecodingFunction("lightMapTexelToLinear", parameters.lightMapEncoding) : "",
|
|
getTexelEncodingFunction("linearToOutputTexel", parameters.outputEncoding),
|
|
parameters.depthPacking ? "#define DEPTH_PACKING " + parameters.depthPacking : "",
|
|
"\n"
|
|
].filter(filterEmptyLine).join("\n");
|
|
}
|
|
vertexShader = resolveIncludes(vertexShader);
|
|
vertexShader = replaceLightNums(vertexShader, parameters);
|
|
vertexShader = replaceClippingPlaneNums(vertexShader, parameters);
|
|
fragmentShader = resolveIncludes(fragmentShader);
|
|
fragmentShader = replaceLightNums(fragmentShader, parameters);
|
|
fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters);
|
|
vertexShader = unrollLoops(vertexShader);
|
|
fragmentShader = unrollLoops(fragmentShader);
|
|
if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) {
|
|
versionString = "#version 300 es\n";
|
|
prefixVertex = [
|
|
"#define attribute in",
|
|
"#define varying out",
|
|
"#define texture2D texture"
|
|
].join("\n") + "\n" + prefixVertex;
|
|
prefixFragment = [
|
|
"#define varying in",
|
|
parameters.glslVersion === GLSL3 ? "" : "out highp vec4 pc_fragColor;",
|
|
parameters.glslVersion === GLSL3 ? "" : "#define gl_FragColor pc_fragColor",
|
|
"#define gl_FragDepthEXT gl_FragDepth",
|
|
"#define texture2D texture",
|
|
"#define textureCube texture",
|
|
"#define texture2DProj textureProj",
|
|
"#define texture2DLodEXT textureLod",
|
|
"#define texture2DProjLodEXT textureProjLod",
|
|
"#define textureCubeLodEXT textureLod",
|
|
"#define texture2DGradEXT textureGrad",
|
|
"#define texture2DProjGradEXT textureProjGrad",
|
|
"#define textureCubeGradEXT textureGrad"
|
|
].join("\n") + "\n" + prefixFragment;
|
|
}
|
|
const vertexGlsl = versionString + prefixVertex + vertexShader;
|
|
const fragmentGlsl = versionString + prefixFragment + fragmentShader;
|
|
const glVertexShader = WebGLShader(gl, 35633, vertexGlsl);
|
|
const glFragmentShader = WebGLShader(gl, 35632, fragmentGlsl);
|
|
gl.attachShader(program, glVertexShader);
|
|
gl.attachShader(program, glFragmentShader);
|
|
if (parameters.index0AttributeName !== void 0) {
|
|
gl.bindAttribLocation(program, 0, parameters.index0AttributeName);
|
|
} else if (parameters.morphTargets === true) {
|
|
gl.bindAttribLocation(program, 0, "position");
|
|
}
|
|
gl.linkProgram(program);
|
|
if (renderer.debug.checkShaderErrors) {
|
|
const programLog = gl.getProgramInfoLog(program).trim();
|
|
const vertexLog = gl.getShaderInfoLog(glVertexShader).trim();
|
|
const fragmentLog = gl.getShaderInfoLog(glFragmentShader).trim();
|
|
let runnable = true;
|
|
let haveDiagnostics = true;
|
|
if (gl.getProgramParameter(program, 35714) === false) {
|
|
runnable = false;
|
|
const vertexErrors = getShaderErrors(gl, glVertexShader, "vertex");
|
|
const fragmentErrors = getShaderErrors(gl, glFragmentShader, "fragment");
|
|
console.error("THREE.WebGLProgram: Shader Error " + gl.getError() + " - VALIDATE_STATUS " + gl.getProgramParameter(program, 35715) + "\n\nProgram Info Log: " + programLog + "\n" + vertexErrors + "\n" + fragmentErrors);
|
|
} else if (programLog !== "") {
|
|
console.warn("THREE.WebGLProgram: Program Info Log:", programLog);
|
|
} else if (vertexLog === "" || fragmentLog === "") {
|
|
haveDiagnostics = false;
|
|
}
|
|
if (haveDiagnostics) {
|
|
this.diagnostics = {
|
|
runnable,
|
|
programLog,
|
|
vertexShader: {
|
|
log: vertexLog,
|
|
prefix: prefixVertex
|
|
},
|
|
fragmentShader: {
|
|
log: fragmentLog,
|
|
prefix: prefixFragment
|
|
}
|
|
};
|
|
}
|
|
}
|
|
gl.deleteShader(glVertexShader);
|
|
gl.deleteShader(glFragmentShader);
|
|
let cachedUniforms;
|
|
this.getUniforms = function() {
|
|
if (cachedUniforms === void 0) {
|
|
cachedUniforms = new WebGLUniforms(gl, program);
|
|
}
|
|
return cachedUniforms;
|
|
};
|
|
let cachedAttributes;
|
|
this.getAttributes = function() {
|
|
if (cachedAttributes === void 0) {
|
|
cachedAttributes = fetchAttributeLocations(gl, program);
|
|
}
|
|
return cachedAttributes;
|
|
};
|
|
this.destroy = function() {
|
|
bindingStates.releaseStatesOfProgram(this);
|
|
gl.deleteProgram(program);
|
|
this.program = void 0;
|
|
};
|
|
this.name = parameters.shaderName;
|
|
this.id = programIdCount++;
|
|
this.cacheKey = cacheKey;
|
|
this.usedTimes = 1;
|
|
this.program = program;
|
|
this.vertexShader = glVertexShader;
|
|
this.fragmentShader = glFragmentShader;
|
|
return this;
|
|
}
|
|
function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) {
|
|
const programs = [];
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
|
|
const floatVertexTextures = capabilities.floatVertexTextures;
|
|
const maxVertexUniforms = capabilities.maxVertexUniforms;
|
|
const vertexTextures = capabilities.vertexTextures;
|
|
let precision = capabilities.precision;
|
|
const shaderIDs = {
|
|
MeshDepthMaterial: "depth",
|
|
MeshDistanceMaterial: "distanceRGBA",
|
|
MeshNormalMaterial: "normal",
|
|
MeshBasicMaterial: "basic",
|
|
MeshLambertMaterial: "lambert",
|
|
MeshPhongMaterial: "phong",
|
|
MeshToonMaterial: "toon",
|
|
MeshStandardMaterial: "physical",
|
|
MeshPhysicalMaterial: "physical",
|
|
MeshMatcapMaterial: "matcap",
|
|
LineBasicMaterial: "basic",
|
|
LineDashedMaterial: "dashed",
|
|
PointsMaterial: "points",
|
|
ShadowMaterial: "shadow",
|
|
SpriteMaterial: "sprite"
|
|
};
|
|
const parameterNames = [
|
|
"precision",
|
|
"isWebGL2",
|
|
"supportsVertexTextures",
|
|
"outputEncoding",
|
|
"instancing",
|
|
"instancingColor",
|
|
"map",
|
|
"mapEncoding",
|
|
"matcap",
|
|
"matcapEncoding",
|
|
"envMap",
|
|
"envMapMode",
|
|
"envMapEncoding",
|
|
"envMapCubeUV",
|
|
"lightMap",
|
|
"lightMapEncoding",
|
|
"aoMap",
|
|
"emissiveMap",
|
|
"emissiveMapEncoding",
|
|
"bumpMap",
|
|
"normalMap",
|
|
"objectSpaceNormalMap",
|
|
"tangentSpaceNormalMap",
|
|
"clearcoat",
|
|
"clearcoatMap",
|
|
"clearcoatRoughnessMap",
|
|
"clearcoatNormalMap",
|
|
"displacementMap",
|
|
"specularMap",
|
|
"specularIntensityMap",
|
|
"specularTintMap",
|
|
"specularTintMapEncoding",
|
|
"roughnessMap",
|
|
"metalnessMap",
|
|
"gradientMap",
|
|
"alphaMap",
|
|
"alphaTest",
|
|
"combine",
|
|
"vertexColors",
|
|
"vertexAlphas",
|
|
"vertexTangents",
|
|
"vertexUvs",
|
|
"uvsVertexOnly",
|
|
"fog",
|
|
"useFog",
|
|
"fogExp2",
|
|
"flatShading",
|
|
"sizeAttenuation",
|
|
"logarithmicDepthBuffer",
|
|
"skinning",
|
|
"maxBones",
|
|
"useVertexTexture",
|
|
"morphTargets",
|
|
"morphNormals",
|
|
"premultipliedAlpha",
|
|
"numDirLights",
|
|
"numPointLights",
|
|
"numSpotLights",
|
|
"numHemiLights",
|
|
"numRectAreaLights",
|
|
"numDirLightShadows",
|
|
"numPointLightShadows",
|
|
"numSpotLightShadows",
|
|
"shadowMapEnabled",
|
|
"shadowMapType",
|
|
"toneMapping",
|
|
"physicallyCorrectLights",
|
|
"doubleSided",
|
|
"flipSided",
|
|
"numClippingPlanes",
|
|
"numClipIntersection",
|
|
"depthPacking",
|
|
"dithering",
|
|
"format",
|
|
"sheenTint",
|
|
"transmission",
|
|
"transmissionMap",
|
|
"thicknessMap"
|
|
];
|
|
function getMaxBones(object) {
|
|
const skeleton = object.skeleton;
|
|
const bones = skeleton.bones;
|
|
if (floatVertexTextures) {
|
|
return 1024;
|
|
} else {
|
|
const nVertexUniforms = maxVertexUniforms;
|
|
const nVertexMatrices = Math.floor((nVertexUniforms - 20) / 4);
|
|
const maxBones = Math.min(nVertexMatrices, bones.length);
|
|
if (maxBones < bones.length) {
|
|
console.warn("THREE.WebGLRenderer: Skeleton has " + bones.length + " bones. This GPU supports " + maxBones + ".");
|
|
return 0;
|
|
}
|
|
return maxBones;
|
|
}
|
|
}
|
|
function getTextureEncodingFromMap(map) {
|
|
let encoding;
|
|
if (map && map.isTexture) {
|
|
encoding = map.encoding;
|
|
} else if (map && map.isWebGLRenderTarget) {
|
|
console.warn("THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.");
|
|
encoding = map.texture.encoding;
|
|
} else {
|
|
encoding = LinearEncoding;
|
|
}
|
|
return encoding;
|
|
}
|
|
function getParameters(material, lights, shadows, scene, object) {
|
|
const fog = scene.fog;
|
|
const environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
|
|
const shaderID = shaderIDs[material.type];
|
|
const maxBones = object.isSkinnedMesh ? getMaxBones(object) : 0;
|
|
if (material.precision !== null) {
|
|
precision = capabilities.getMaxPrecision(material.precision);
|
|
if (precision !== material.precision) {
|
|
console.warn("THREE.WebGLProgram.getParameters:", material.precision, "not supported, using", precision, "instead.");
|
|
}
|
|
}
|
|
let vertexShader, fragmentShader;
|
|
if (shaderID) {
|
|
const shader = ShaderLib[shaderID];
|
|
vertexShader = shader.vertexShader;
|
|
fragmentShader = shader.fragmentShader;
|
|
} else {
|
|
vertexShader = material.vertexShader;
|
|
fragmentShader = material.fragmentShader;
|
|
}
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
const useAlphaTest = material.alphaTest > 0;
|
|
const useClearcoat = material.clearcoat > 0;
|
|
const parameters = {
|
|
isWebGL2,
|
|
shaderID,
|
|
shaderName: material.type,
|
|
vertexShader,
|
|
fragmentShader,
|
|
defines: material.defines,
|
|
isRawShaderMaterial: material.isRawShaderMaterial === true,
|
|
glslVersion: material.glslVersion,
|
|
precision,
|
|
instancing: object.isInstancedMesh === true,
|
|
instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
|
|
supportsVertexTextures: vertexTextures,
|
|
outputEncoding: currentRenderTarget !== null ? getTextureEncodingFromMap(currentRenderTarget.texture) : renderer.outputEncoding,
|
|
map: !!material.map,
|
|
mapEncoding: getTextureEncodingFromMap(material.map),
|
|
matcap: !!material.matcap,
|
|
matcapEncoding: getTextureEncodingFromMap(material.matcap),
|
|
envMap: !!envMap,
|
|
envMapMode: envMap && envMap.mapping,
|
|
envMapEncoding: getTextureEncodingFromMap(envMap),
|
|
envMapCubeUV: !!envMap && (envMap.mapping === CubeUVReflectionMapping || envMap.mapping === CubeUVRefractionMapping),
|
|
lightMap: !!material.lightMap,
|
|
lightMapEncoding: getTextureEncodingFromMap(material.lightMap),
|
|
aoMap: !!material.aoMap,
|
|
emissiveMap: !!material.emissiveMap,
|
|
emissiveMapEncoding: getTextureEncodingFromMap(material.emissiveMap),
|
|
bumpMap: !!material.bumpMap,
|
|
normalMap: !!material.normalMap,
|
|
objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
|
|
tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
|
|
clearcoat: useClearcoat,
|
|
clearcoatMap: useClearcoat && !!material.clearcoatMap,
|
|
clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap,
|
|
clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap,
|
|
displacementMap: !!material.displacementMap,
|
|
roughnessMap: !!material.roughnessMap,
|
|
metalnessMap: !!material.metalnessMap,
|
|
specularMap: !!material.specularMap,
|
|
specularIntensityMap: !!material.specularIntensityMap,
|
|
specularTintMap: !!material.specularTintMap,
|
|
specularTintMapEncoding: getTextureEncodingFromMap(material.specularTintMap),
|
|
alphaMap: !!material.alphaMap,
|
|
alphaTest: useAlphaTest,
|
|
gradientMap: !!material.gradientMap,
|
|
sheenTint: !!material.sheenTint && (material.sheenTint.r > 0 || material.sheenTint.g > 0 || material.sheenTint.b > 0),
|
|
transmission: material.transmission > 0,
|
|
transmissionMap: !!material.transmissionMap,
|
|
thicknessMap: !!material.thicknessMap,
|
|
combine: material.combine,
|
|
vertexTangents: !!material.normalMap && !!object.geometry && !!object.geometry.attributes.tangent,
|
|
vertexColors: material.vertexColors,
|
|
vertexAlphas: material.vertexColors === true && !!object.geometry && !!object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4,
|
|
vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.displacementMap || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularTintMap,
|
|
uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || material.transmission > 0 || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularTintMap) && !!material.displacementMap,
|
|
fog: !!fog,
|
|
useFog: material.fog,
|
|
fogExp2: fog && fog.isFogExp2,
|
|
flatShading: !!material.flatShading,
|
|
sizeAttenuation: material.sizeAttenuation,
|
|
logarithmicDepthBuffer,
|
|
skinning: object.isSkinnedMesh === true && maxBones > 0,
|
|
maxBones,
|
|
useVertexTexture: floatVertexTextures,
|
|
morphTargets: !!object.geometry && !!object.geometry.morphAttributes.position,
|
|
morphNormals: !!object.geometry && !!object.geometry.morphAttributes.normal,
|
|
numDirLights: lights.directional.length,
|
|
numPointLights: lights.point.length,
|
|
numSpotLights: lights.spot.length,
|
|
numRectAreaLights: lights.rectArea.length,
|
|
numHemiLights: lights.hemi.length,
|
|
numDirLightShadows: lights.directionalShadowMap.length,
|
|
numPointLightShadows: lights.pointShadowMap.length,
|
|
numSpotLightShadows: lights.spotShadowMap.length,
|
|
numClippingPlanes: clipping.numPlanes,
|
|
numClipIntersection: clipping.numIntersection,
|
|
format: material.format,
|
|
dithering: material.dithering,
|
|
shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
|
|
shadowMapType: renderer.shadowMap.type,
|
|
toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
|
|
physicallyCorrectLights: renderer.physicallyCorrectLights,
|
|
premultipliedAlpha: material.premultipliedAlpha,
|
|
doubleSided: material.side === DoubleSide,
|
|
flipSided: material.side === BackSide,
|
|
depthPacking: material.depthPacking !== void 0 ? material.depthPacking : false,
|
|
index0AttributeName: material.index0AttributeName,
|
|
extensionDerivatives: material.extensions && material.extensions.derivatives,
|
|
extensionFragDepth: material.extensions && material.extensions.fragDepth,
|
|
extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
|
|
extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
|
|
rendererExtensionFragDepth: isWebGL2 || extensions.has("EXT_frag_depth"),
|
|
rendererExtensionDrawBuffers: isWebGL2 || extensions.has("WEBGL_draw_buffers"),
|
|
rendererExtensionShaderTextureLod: isWebGL2 || extensions.has("EXT_shader_texture_lod"),
|
|
customProgramCacheKey: material.customProgramCacheKey()
|
|
};
|
|
return parameters;
|
|
}
|
|
function getProgramCacheKey(parameters) {
|
|
const array = [];
|
|
if (parameters.shaderID) {
|
|
array.push(parameters.shaderID);
|
|
} else {
|
|
array.push(parameters.fragmentShader);
|
|
array.push(parameters.vertexShader);
|
|
}
|
|
if (parameters.defines !== void 0) {
|
|
for (const name in parameters.defines) {
|
|
array.push(name);
|
|
array.push(parameters.defines[name]);
|
|
}
|
|
}
|
|
if (parameters.isRawShaderMaterial === false) {
|
|
for (let i = 0; i < parameterNames.length; i++) {
|
|
array.push(parameters[parameterNames[i]]);
|
|
}
|
|
array.push(renderer.outputEncoding);
|
|
array.push(renderer.gammaFactor);
|
|
}
|
|
array.push(parameters.customProgramCacheKey);
|
|
return array.join();
|
|
}
|
|
function getUniforms(material) {
|
|
const shaderID = shaderIDs[material.type];
|
|
let uniforms;
|
|
if (shaderID) {
|
|
const shader = ShaderLib[shaderID];
|
|
uniforms = UniformsUtils.clone(shader.uniforms);
|
|
} else {
|
|
uniforms = material.uniforms;
|
|
}
|
|
return uniforms;
|
|
}
|
|
function acquireProgram(parameters, cacheKey) {
|
|
let program;
|
|
for (let p2 = 0, pl = programs.length; p2 < pl; p2++) {
|
|
const preexistingProgram = programs[p2];
|
|
if (preexistingProgram.cacheKey === cacheKey) {
|
|
program = preexistingProgram;
|
|
++program.usedTimes;
|
|
break;
|
|
}
|
|
}
|
|
if (program === void 0) {
|
|
program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates);
|
|
programs.push(program);
|
|
}
|
|
return program;
|
|
}
|
|
function releaseProgram(program) {
|
|
if (--program.usedTimes === 0) {
|
|
const i = programs.indexOf(program);
|
|
programs[i] = programs[programs.length - 1];
|
|
programs.pop();
|
|
program.destroy();
|
|
}
|
|
}
|
|
return {
|
|
getParameters,
|
|
getProgramCacheKey,
|
|
getUniforms,
|
|
acquireProgram,
|
|
releaseProgram,
|
|
programs
|
|
};
|
|
}
|
|
function WebGLProperties() {
|
|
let properties = new WeakMap();
|
|
function get(object) {
|
|
let map = properties.get(object);
|
|
if (map === void 0) {
|
|
map = {};
|
|
properties.set(object, map);
|
|
}
|
|
return map;
|
|
}
|
|
function remove(object) {
|
|
properties.delete(object);
|
|
}
|
|
function update(object, key, value) {
|
|
properties.get(object)[key] = value;
|
|
}
|
|
function dispose() {
|
|
properties = new WeakMap();
|
|
}
|
|
return {
|
|
get,
|
|
remove,
|
|
update,
|
|
dispose
|
|
};
|
|
}
|
|
function painterSortStable(a2, b2) {
|
|
if (a2.groupOrder !== b2.groupOrder) {
|
|
return a2.groupOrder - b2.groupOrder;
|
|
} else if (a2.renderOrder !== b2.renderOrder) {
|
|
return a2.renderOrder - b2.renderOrder;
|
|
} else if (a2.program !== b2.program) {
|
|
return a2.program.id - b2.program.id;
|
|
} else if (a2.material.id !== b2.material.id) {
|
|
return a2.material.id - b2.material.id;
|
|
} else if (a2.z !== b2.z) {
|
|
return a2.z - b2.z;
|
|
} else {
|
|
return a2.id - b2.id;
|
|
}
|
|
}
|
|
function reversePainterSortStable(a2, b2) {
|
|
if (a2.groupOrder !== b2.groupOrder) {
|
|
return a2.groupOrder - b2.groupOrder;
|
|
} else if (a2.renderOrder !== b2.renderOrder) {
|
|
return a2.renderOrder - b2.renderOrder;
|
|
} else if (a2.z !== b2.z) {
|
|
return b2.z - a2.z;
|
|
} else {
|
|
return a2.id - b2.id;
|
|
}
|
|
}
|
|
function WebGLRenderList(properties) {
|
|
const renderItems = [];
|
|
let renderItemsIndex = 0;
|
|
const opaque = [];
|
|
const transmissive = [];
|
|
const transparent = [];
|
|
const defaultProgram = { id: -1 };
|
|
function init() {
|
|
renderItemsIndex = 0;
|
|
opaque.length = 0;
|
|
transmissive.length = 0;
|
|
transparent.length = 0;
|
|
}
|
|
function getNextRenderItem(object, geometry, material, groupOrder, z, group) {
|
|
let renderItem = renderItems[renderItemsIndex];
|
|
const materialProperties = properties.get(material);
|
|
if (renderItem === void 0) {
|
|
renderItem = {
|
|
id: object.id,
|
|
object,
|
|
geometry,
|
|
material,
|
|
program: materialProperties.program || defaultProgram,
|
|
groupOrder,
|
|
renderOrder: object.renderOrder,
|
|
z,
|
|
group
|
|
};
|
|
renderItems[renderItemsIndex] = renderItem;
|
|
} else {
|
|
renderItem.id = object.id;
|
|
renderItem.object = object;
|
|
renderItem.geometry = geometry;
|
|
renderItem.material = material;
|
|
renderItem.program = materialProperties.program || defaultProgram;
|
|
renderItem.groupOrder = groupOrder;
|
|
renderItem.renderOrder = object.renderOrder;
|
|
renderItem.z = z;
|
|
renderItem.group = group;
|
|
}
|
|
renderItemsIndex++;
|
|
return renderItem;
|
|
}
|
|
function push(object, geometry, material, groupOrder, z, group) {
|
|
const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group);
|
|
if (material.transmission > 0) {
|
|
transmissive.push(renderItem);
|
|
} else if (material.transparent === true) {
|
|
transparent.push(renderItem);
|
|
} else {
|
|
opaque.push(renderItem);
|
|
}
|
|
}
|
|
function unshift(object, geometry, material, groupOrder, z, group) {
|
|
const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group);
|
|
if (material.transmission > 0) {
|
|
transmissive.unshift(renderItem);
|
|
} else if (material.transparent === true) {
|
|
transparent.unshift(renderItem);
|
|
} else {
|
|
opaque.unshift(renderItem);
|
|
}
|
|
}
|
|
function sort(customOpaqueSort, customTransparentSort) {
|
|
if (opaque.length > 1)
|
|
opaque.sort(customOpaqueSort || painterSortStable);
|
|
if (transmissive.length > 1)
|
|
transmissive.sort(customTransparentSort || reversePainterSortStable);
|
|
if (transparent.length > 1)
|
|
transparent.sort(customTransparentSort || reversePainterSortStable);
|
|
}
|
|
function finish() {
|
|
for (let i = renderItemsIndex, il = renderItems.length; i < il; i++) {
|
|
const renderItem = renderItems[i];
|
|
if (renderItem.id === null)
|
|
break;
|
|
renderItem.id = null;
|
|
renderItem.object = null;
|
|
renderItem.geometry = null;
|
|
renderItem.material = null;
|
|
renderItem.program = null;
|
|
renderItem.group = null;
|
|
}
|
|
}
|
|
return {
|
|
opaque,
|
|
transmissive,
|
|
transparent,
|
|
init,
|
|
push,
|
|
unshift,
|
|
finish,
|
|
sort
|
|
};
|
|
}
|
|
function WebGLRenderLists(properties) {
|
|
let lists = new WeakMap();
|
|
function get(scene, renderCallDepth) {
|
|
let list;
|
|
if (lists.has(scene) === false) {
|
|
list = new WebGLRenderList(properties);
|
|
lists.set(scene, [list]);
|
|
} else {
|
|
if (renderCallDepth >= lists.get(scene).length) {
|
|
list = new WebGLRenderList(properties);
|
|
lists.get(scene).push(list);
|
|
} else {
|
|
list = lists.get(scene)[renderCallDepth];
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
function dispose() {
|
|
lists = new WeakMap();
|
|
}
|
|
return {
|
|
get,
|
|
dispose
|
|
};
|
|
}
|
|
function UniformsCache() {
|
|
const lights = {};
|
|
return {
|
|
get: function(light) {
|
|
if (lights[light.id] !== void 0) {
|
|
return lights[light.id];
|
|
}
|
|
let uniforms;
|
|
switch (light.type) {
|
|
case "DirectionalLight":
|
|
uniforms = {
|
|
direction: new Vector3(),
|
|
color: new Color()
|
|
};
|
|
break;
|
|
case "SpotLight":
|
|
uniforms = {
|
|
position: new Vector3(),
|
|
direction: new Vector3(),
|
|
color: new Color(),
|
|
distance: 0,
|
|
coneCos: 0,
|
|
penumbraCos: 0,
|
|
decay: 0
|
|
};
|
|
break;
|
|
case "PointLight":
|
|
uniforms = {
|
|
position: new Vector3(),
|
|
color: new Color(),
|
|
distance: 0,
|
|
decay: 0
|
|
};
|
|
break;
|
|
case "HemisphereLight":
|
|
uniforms = {
|
|
direction: new Vector3(),
|
|
skyColor: new Color(),
|
|
groundColor: new Color()
|
|
};
|
|
break;
|
|
case "RectAreaLight":
|
|
uniforms = {
|
|
color: new Color(),
|
|
position: new Vector3(),
|
|
halfWidth: new Vector3(),
|
|
halfHeight: new Vector3()
|
|
};
|
|
break;
|
|
}
|
|
lights[light.id] = uniforms;
|
|
return uniforms;
|
|
}
|
|
};
|
|
}
|
|
function ShadowUniformsCache() {
|
|
const lights = {};
|
|
return {
|
|
get: function(light) {
|
|
if (lights[light.id] !== void 0) {
|
|
return lights[light.id];
|
|
}
|
|
let uniforms;
|
|
switch (light.type) {
|
|
case "DirectionalLight":
|
|
uniforms = {
|
|
shadowBias: 0,
|
|
shadowNormalBias: 0,
|
|
shadowRadius: 1,
|
|
shadowMapSize: new Vector2()
|
|
};
|
|
break;
|
|
case "SpotLight":
|
|
uniforms = {
|
|
shadowBias: 0,
|
|
shadowNormalBias: 0,
|
|
shadowRadius: 1,
|
|
shadowMapSize: new Vector2()
|
|
};
|
|
break;
|
|
case "PointLight":
|
|
uniforms = {
|
|
shadowBias: 0,
|
|
shadowNormalBias: 0,
|
|
shadowRadius: 1,
|
|
shadowMapSize: new Vector2(),
|
|
shadowCameraNear: 1,
|
|
shadowCameraFar: 1e3
|
|
};
|
|
break;
|
|
}
|
|
lights[light.id] = uniforms;
|
|
return uniforms;
|
|
}
|
|
};
|
|
}
|
|
var nextVersion = 0;
|
|
function shadowCastingLightsFirst(lightA, lightB) {
|
|
return (lightB.castShadow ? 1 : 0) - (lightA.castShadow ? 1 : 0);
|
|
}
|
|
function WebGLLights(extensions, capabilities) {
|
|
const cache = new UniformsCache();
|
|
const shadowCache = ShadowUniformsCache();
|
|
const state = {
|
|
version: 0,
|
|
hash: {
|
|
directionalLength: -1,
|
|
pointLength: -1,
|
|
spotLength: -1,
|
|
rectAreaLength: -1,
|
|
hemiLength: -1,
|
|
numDirectionalShadows: -1,
|
|
numPointShadows: -1,
|
|
numSpotShadows: -1
|
|
},
|
|
ambient: [0, 0, 0],
|
|
probe: [],
|
|
directional: [],
|
|
directionalShadow: [],
|
|
directionalShadowMap: [],
|
|
directionalShadowMatrix: [],
|
|
spot: [],
|
|
spotShadow: [],
|
|
spotShadowMap: [],
|
|
spotShadowMatrix: [],
|
|
rectArea: [],
|
|
rectAreaLTC1: null,
|
|
rectAreaLTC2: null,
|
|
point: [],
|
|
pointShadow: [],
|
|
pointShadowMap: [],
|
|
pointShadowMatrix: [],
|
|
hemi: []
|
|
};
|
|
for (let i = 0; i < 9; i++)
|
|
state.probe.push(new Vector3());
|
|
const vector3 = new Vector3();
|
|
const matrix4 = new Matrix4();
|
|
const matrix42 = new Matrix4();
|
|
function setup(lights, physicallyCorrectLights) {
|
|
let r = 0, g = 0, b2 = 0;
|
|
for (let i = 0; i < 9; i++)
|
|
state.probe[i].set(0, 0, 0);
|
|
let directionalLength = 0;
|
|
let pointLength = 0;
|
|
let spotLength = 0;
|
|
let rectAreaLength = 0;
|
|
let hemiLength = 0;
|
|
let numDirectionalShadows = 0;
|
|
let numPointShadows = 0;
|
|
let numSpotShadows = 0;
|
|
lights.sort(shadowCastingLightsFirst);
|
|
const scaleFactor = physicallyCorrectLights !== true ? Math.PI : 1;
|
|
for (let i = 0, l = lights.length; i < l; i++) {
|
|
const light = lights[i];
|
|
const color = light.color;
|
|
const intensity = light.intensity;
|
|
const distance = light.distance;
|
|
const shadowMap = light.shadow && light.shadow.map ? light.shadow.map.texture : null;
|
|
if (light.isAmbientLight) {
|
|
r += color.r * intensity * scaleFactor;
|
|
g += color.g * intensity * scaleFactor;
|
|
b2 += color.b * intensity * scaleFactor;
|
|
} else if (light.isLightProbe) {
|
|
for (let j = 0; j < 9; j++) {
|
|
state.probe[j].addScaledVector(light.sh.coefficients[j], intensity);
|
|
}
|
|
} else if (light.isDirectionalLight) {
|
|
const uniforms = cache.get(light);
|
|
uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor);
|
|
if (light.castShadow) {
|
|
const shadow = light.shadow;
|
|
const shadowUniforms = shadowCache.get(light);
|
|
shadowUniforms.shadowBias = shadow.bias;
|
|
shadowUniforms.shadowNormalBias = shadow.normalBias;
|
|
shadowUniforms.shadowRadius = shadow.radius;
|
|
shadowUniforms.shadowMapSize = shadow.mapSize;
|
|
state.directionalShadow[directionalLength] = shadowUniforms;
|
|
state.directionalShadowMap[directionalLength] = shadowMap;
|
|
state.directionalShadowMatrix[directionalLength] = light.shadow.matrix;
|
|
numDirectionalShadows++;
|
|
}
|
|
state.directional[directionalLength] = uniforms;
|
|
directionalLength++;
|
|
} else if (light.isSpotLight) {
|
|
const uniforms = cache.get(light);
|
|
uniforms.position.setFromMatrixPosition(light.matrixWorld);
|
|
uniforms.color.copy(color).multiplyScalar(intensity * scaleFactor);
|
|
uniforms.distance = distance;
|
|
uniforms.coneCos = Math.cos(light.angle);
|
|
uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra));
|
|
uniforms.decay = light.decay;
|
|
if (light.castShadow) {
|
|
const shadow = light.shadow;
|
|
const shadowUniforms = shadowCache.get(light);
|
|
shadowUniforms.shadowBias = shadow.bias;
|
|
shadowUniforms.shadowNormalBias = shadow.normalBias;
|
|
shadowUniforms.shadowRadius = shadow.radius;
|
|
shadowUniforms.shadowMapSize = shadow.mapSize;
|
|
state.spotShadow[spotLength] = shadowUniforms;
|
|
state.spotShadowMap[spotLength] = shadowMap;
|
|
state.spotShadowMatrix[spotLength] = light.shadow.matrix;
|
|
numSpotShadows++;
|
|
}
|
|
state.spot[spotLength] = uniforms;
|
|
spotLength++;
|
|
} else if (light.isRectAreaLight) {
|
|
const uniforms = cache.get(light);
|
|
uniforms.color.copy(color).multiplyScalar(intensity);
|
|
uniforms.halfWidth.set(light.width * 0.5, 0, 0);
|
|
uniforms.halfHeight.set(0, light.height * 0.5, 0);
|
|
state.rectArea[rectAreaLength] = uniforms;
|
|
rectAreaLength++;
|
|
} else if (light.isPointLight) {
|
|
const uniforms = cache.get(light);
|
|
uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor);
|
|
uniforms.distance = light.distance;
|
|
uniforms.decay = light.decay;
|
|
if (light.castShadow) {
|
|
const shadow = light.shadow;
|
|
const shadowUniforms = shadowCache.get(light);
|
|
shadowUniforms.shadowBias = shadow.bias;
|
|
shadowUniforms.shadowNormalBias = shadow.normalBias;
|
|
shadowUniforms.shadowRadius = shadow.radius;
|
|
shadowUniforms.shadowMapSize = shadow.mapSize;
|
|
shadowUniforms.shadowCameraNear = shadow.camera.near;
|
|
shadowUniforms.shadowCameraFar = shadow.camera.far;
|
|
state.pointShadow[pointLength] = shadowUniforms;
|
|
state.pointShadowMap[pointLength] = shadowMap;
|
|
state.pointShadowMatrix[pointLength] = light.shadow.matrix;
|
|
numPointShadows++;
|
|
}
|
|
state.point[pointLength] = uniforms;
|
|
pointLength++;
|
|
} else if (light.isHemisphereLight) {
|
|
const uniforms = cache.get(light);
|
|
uniforms.skyColor.copy(light.color).multiplyScalar(intensity * scaleFactor);
|
|
uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity * scaleFactor);
|
|
state.hemi[hemiLength] = uniforms;
|
|
hemiLength++;
|
|
}
|
|
}
|
|
if (rectAreaLength > 0) {
|
|
if (capabilities.isWebGL2) {
|
|
state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
|
|
state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
|
|
} else {
|
|
if (extensions.has("OES_texture_float_linear") === true) {
|
|
state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
|
|
state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
|
|
} else if (extensions.has("OES_texture_half_float_linear") === true) {
|
|
state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
|
|
state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
|
|
} else {
|
|
console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.");
|
|
}
|
|
}
|
|
}
|
|
state.ambient[0] = r;
|
|
state.ambient[1] = g;
|
|
state.ambient[2] = b2;
|
|
const hash = state.hash;
|
|
if (hash.directionalLength !== directionalLength || hash.pointLength !== pointLength || hash.spotLength !== spotLength || hash.rectAreaLength !== rectAreaLength || hash.hemiLength !== hemiLength || hash.numDirectionalShadows !== numDirectionalShadows || hash.numPointShadows !== numPointShadows || hash.numSpotShadows !== numSpotShadows) {
|
|
state.directional.length = directionalLength;
|
|
state.spot.length = spotLength;
|
|
state.rectArea.length = rectAreaLength;
|
|
state.point.length = pointLength;
|
|
state.hemi.length = hemiLength;
|
|
state.directionalShadow.length = numDirectionalShadows;
|
|
state.directionalShadowMap.length = numDirectionalShadows;
|
|
state.pointShadow.length = numPointShadows;
|
|
state.pointShadowMap.length = numPointShadows;
|
|
state.spotShadow.length = numSpotShadows;
|
|
state.spotShadowMap.length = numSpotShadows;
|
|
state.directionalShadowMatrix.length = numDirectionalShadows;
|
|
state.pointShadowMatrix.length = numPointShadows;
|
|
state.spotShadowMatrix.length = numSpotShadows;
|
|
hash.directionalLength = directionalLength;
|
|
hash.pointLength = pointLength;
|
|
hash.spotLength = spotLength;
|
|
hash.rectAreaLength = rectAreaLength;
|
|
hash.hemiLength = hemiLength;
|
|
hash.numDirectionalShadows = numDirectionalShadows;
|
|
hash.numPointShadows = numPointShadows;
|
|
hash.numSpotShadows = numSpotShadows;
|
|
state.version = nextVersion++;
|
|
}
|
|
}
|
|
function setupView(lights, camera) {
|
|
let directionalLength = 0;
|
|
let pointLength = 0;
|
|
let spotLength = 0;
|
|
let rectAreaLength = 0;
|
|
let hemiLength = 0;
|
|
const viewMatrix = camera.matrixWorldInverse;
|
|
for (let i = 0, l = lights.length; i < l; i++) {
|
|
const light = lights[i];
|
|
if (light.isDirectionalLight) {
|
|
const uniforms = state.directional[directionalLength];
|
|
uniforms.direction.setFromMatrixPosition(light.matrixWorld);
|
|
vector3.setFromMatrixPosition(light.target.matrixWorld);
|
|
uniforms.direction.sub(vector3);
|
|
uniforms.direction.transformDirection(viewMatrix);
|
|
directionalLength++;
|
|
} else if (light.isSpotLight) {
|
|
const uniforms = state.spot[spotLength];
|
|
uniforms.position.setFromMatrixPosition(light.matrixWorld);
|
|
uniforms.position.applyMatrix4(viewMatrix);
|
|
uniforms.direction.setFromMatrixPosition(light.matrixWorld);
|
|
vector3.setFromMatrixPosition(light.target.matrixWorld);
|
|
uniforms.direction.sub(vector3);
|
|
uniforms.direction.transformDirection(viewMatrix);
|
|
spotLength++;
|
|
} else if (light.isRectAreaLight) {
|
|
const uniforms = state.rectArea[rectAreaLength];
|
|
uniforms.position.setFromMatrixPosition(light.matrixWorld);
|
|
uniforms.position.applyMatrix4(viewMatrix);
|
|
matrix42.identity();
|
|
matrix4.copy(light.matrixWorld);
|
|
matrix4.premultiply(viewMatrix);
|
|
matrix42.extractRotation(matrix4);
|
|
uniforms.halfWidth.set(light.width * 0.5, 0, 0);
|
|
uniforms.halfHeight.set(0, light.height * 0.5, 0);
|
|
uniforms.halfWidth.applyMatrix4(matrix42);
|
|
uniforms.halfHeight.applyMatrix4(matrix42);
|
|
rectAreaLength++;
|
|
} else if (light.isPointLight) {
|
|
const uniforms = state.point[pointLength];
|
|
uniforms.position.setFromMatrixPosition(light.matrixWorld);
|
|
uniforms.position.applyMatrix4(viewMatrix);
|
|
pointLength++;
|
|
} else if (light.isHemisphereLight) {
|
|
const uniforms = state.hemi[hemiLength];
|
|
uniforms.direction.setFromMatrixPosition(light.matrixWorld);
|
|
uniforms.direction.transformDirection(viewMatrix);
|
|
uniforms.direction.normalize();
|
|
hemiLength++;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
setup,
|
|
setupView,
|
|
state
|
|
};
|
|
}
|
|
function WebGLRenderState(extensions, capabilities) {
|
|
const lights = new WebGLLights(extensions, capabilities);
|
|
const lightsArray = [];
|
|
const shadowsArray = [];
|
|
function init() {
|
|
lightsArray.length = 0;
|
|
shadowsArray.length = 0;
|
|
}
|
|
function pushLight(light) {
|
|
lightsArray.push(light);
|
|
}
|
|
function pushShadow(shadowLight) {
|
|
shadowsArray.push(shadowLight);
|
|
}
|
|
function setupLights(physicallyCorrectLights) {
|
|
lights.setup(lightsArray, physicallyCorrectLights);
|
|
}
|
|
function setupLightsView(camera) {
|
|
lights.setupView(lightsArray, camera);
|
|
}
|
|
const state = {
|
|
lightsArray,
|
|
shadowsArray,
|
|
lights
|
|
};
|
|
return {
|
|
init,
|
|
state,
|
|
setupLights,
|
|
setupLightsView,
|
|
pushLight,
|
|
pushShadow
|
|
};
|
|
}
|
|
function WebGLRenderStates(extensions, capabilities) {
|
|
let renderStates = new WeakMap();
|
|
function get(scene, renderCallDepth = 0) {
|
|
let renderState;
|
|
if (renderStates.has(scene) === false) {
|
|
renderState = new WebGLRenderState(extensions, capabilities);
|
|
renderStates.set(scene, [renderState]);
|
|
} else {
|
|
if (renderCallDepth >= renderStates.get(scene).length) {
|
|
renderState = new WebGLRenderState(extensions, capabilities);
|
|
renderStates.get(scene).push(renderState);
|
|
} else {
|
|
renderState = renderStates.get(scene)[renderCallDepth];
|
|
}
|
|
}
|
|
return renderState;
|
|
}
|
|
function dispose() {
|
|
renderStates = new WeakMap();
|
|
}
|
|
return {
|
|
get,
|
|
dispose
|
|
};
|
|
}
|
|
var MeshDepthMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshDepthMaterial";
|
|
this.depthPacking = BasicDepthPacking;
|
|
this.map = null;
|
|
this.alphaMap = null;
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.fog = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.depthPacking = source.depthPacking;
|
|
this.map = source.map;
|
|
this.alphaMap = source.alphaMap;
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
return this;
|
|
}
|
|
};
|
|
MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
|
|
var MeshDistanceMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshDistanceMaterial";
|
|
this.referencePosition = new Vector3();
|
|
this.nearDistance = 1;
|
|
this.farDistance = 1e3;
|
|
this.map = null;
|
|
this.alphaMap = null;
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.fog = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.referencePosition.copy(source.referencePosition);
|
|
this.nearDistance = source.nearDistance;
|
|
this.farDistance = source.farDistance;
|
|
this.map = source.map;
|
|
this.alphaMap = source.alphaMap;
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
return this;
|
|
}
|
|
};
|
|
MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
|
|
var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\nuniform float samples;\n#include <packing>\nvoid main() {\n float mean = 0.0;\n float squared_mean = 0.0;\n float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n float uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n for ( float i = 0.0; i < samples; i ++ ) {\n float uvOffset = uvStart + i * uvStride;\n #ifdef HORIZONTAL_PASS\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n #else\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n #endif\n }\n mean = mean / samples;\n squared_mean = squared_mean / samples;\n float std_dev = sqrt( squared_mean - mean * mean );\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
|
|
var vsm_vert = "void main() {\n gl_Position = vec4( position, 1.0 );\n}";
|
|
function WebGLShadowMap(_renderer, _objects, _capabilities) {
|
|
let _frustum = new Frustum();
|
|
const _shadowMapSize = new Vector2(), _viewportSize = new Vector2(), _viewport = new Vector4(), _depthMaterial = new MeshDepthMaterial({ depthPacking: RGBADepthPacking }), _distanceMaterial = new MeshDistanceMaterial(), _materialCache = {}, _maxTextureSize = _capabilities.maxTextureSize;
|
|
const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
|
|
const shadowMaterialVertical = new ShaderMaterial({
|
|
uniforms: {
|
|
shadow_pass: { value: null },
|
|
resolution: { value: new Vector2() },
|
|
radius: { value: 4 },
|
|
samples: { value: 8 }
|
|
},
|
|
vertexShader: vsm_vert,
|
|
fragmentShader: vsm_frag
|
|
});
|
|
const shadowMaterialHorizontal = shadowMaterialVertical.clone();
|
|
shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
|
|
const fullScreenTri = new BufferGeometry();
|
|
fullScreenTri.setAttribute("position", new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3));
|
|
const fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical);
|
|
const scope = this;
|
|
this.enabled = false;
|
|
this.autoUpdate = true;
|
|
this.needsUpdate = false;
|
|
this.type = PCFShadowMap;
|
|
this.render = function(lights, scene, camera) {
|
|
if (scope.enabled === false)
|
|
return;
|
|
if (scope.autoUpdate === false && scope.needsUpdate === false)
|
|
return;
|
|
if (lights.length === 0)
|
|
return;
|
|
const currentRenderTarget = _renderer.getRenderTarget();
|
|
const activeCubeFace = _renderer.getActiveCubeFace();
|
|
const activeMipmapLevel = _renderer.getActiveMipmapLevel();
|
|
const _state = _renderer.state;
|
|
_state.setBlending(NoBlending);
|
|
_state.buffers.color.setClear(1, 1, 1, 1);
|
|
_state.buffers.depth.setTest(true);
|
|
_state.setScissorTest(false);
|
|
for (let i = 0, il = lights.length; i < il; i++) {
|
|
const light = lights[i];
|
|
const shadow = light.shadow;
|
|
if (shadow === void 0) {
|
|
console.warn("THREE.WebGLShadowMap:", light, "has no shadow.");
|
|
continue;
|
|
}
|
|
if (shadow.autoUpdate === false && shadow.needsUpdate === false)
|
|
continue;
|
|
_shadowMapSize.copy(shadow.mapSize);
|
|
const shadowFrameExtents = shadow.getFrameExtents();
|
|
_shadowMapSize.multiply(shadowFrameExtents);
|
|
_viewportSize.copy(shadow.mapSize);
|
|
if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) {
|
|
if (_shadowMapSize.x > _maxTextureSize) {
|
|
_viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x);
|
|
_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
|
|
shadow.mapSize.x = _viewportSize.x;
|
|
}
|
|
if (_shadowMapSize.y > _maxTextureSize) {
|
|
_viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y);
|
|
_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
|
|
shadow.mapSize.y = _viewportSize.y;
|
|
}
|
|
}
|
|
if (shadow.map === null && !shadow.isPointLightShadow && this.type === VSMShadowMap) {
|
|
const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
|
|
shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
|
|
shadow.map.texture.name = light.name + ".shadowMap";
|
|
shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
|
|
shadow.camera.updateProjectionMatrix();
|
|
}
|
|
if (shadow.map === null) {
|
|
const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
|
|
shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
|
|
shadow.map.texture.name = light.name + ".shadowMap";
|
|
shadow.camera.updateProjectionMatrix();
|
|
}
|
|
_renderer.setRenderTarget(shadow.map);
|
|
_renderer.clear();
|
|
const viewportCount = shadow.getViewportCount();
|
|
for (let vp = 0; vp < viewportCount; vp++) {
|
|
const viewport = shadow.getViewport(vp);
|
|
_viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w);
|
|
_state.viewport(_viewport);
|
|
shadow.updateMatrices(light, vp);
|
|
_frustum = shadow.getFrustum();
|
|
renderObject(scene, camera, shadow.camera, light, this.type);
|
|
}
|
|
if (!shadow.isPointLightShadow && this.type === VSMShadowMap) {
|
|
VSMPass(shadow, camera);
|
|
}
|
|
shadow.needsUpdate = false;
|
|
}
|
|
scope.needsUpdate = false;
|
|
_renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel);
|
|
};
|
|
function VSMPass(shadow, camera) {
|
|
const geometry = _objects.update(fullScreenMesh);
|
|
shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
|
|
shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
|
|
shadowMaterialVertical.uniforms.radius.value = shadow.radius;
|
|
shadowMaterialVertical.uniforms.samples.value = shadow.blurSamples;
|
|
_renderer.setRenderTarget(shadow.mapPass);
|
|
_renderer.clear();
|
|
_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null);
|
|
shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
|
|
shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
|
|
shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
|
|
shadowMaterialHorizontal.uniforms.samples.value = shadow.blurSamples;
|
|
_renderer.setRenderTarget(shadow.map);
|
|
_renderer.clear();
|
|
_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null);
|
|
}
|
|
function getDepthMaterial(object, geometry, material, light, shadowCameraNear, shadowCameraFar, type) {
|
|
let result = null;
|
|
const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial;
|
|
if (customMaterial !== void 0) {
|
|
result = customMaterial;
|
|
} else {
|
|
result = light.isPointLight === true ? _distanceMaterial : _depthMaterial;
|
|
}
|
|
if (_renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0 || material.displacementMap && material.displacementScale !== 0 || material.alphaMap && material.alphaTest > 0) {
|
|
const keyA = result.uuid, keyB = material.uuid;
|
|
let materialsForVariant = _materialCache[keyA];
|
|
if (materialsForVariant === void 0) {
|
|
materialsForVariant = {};
|
|
_materialCache[keyA] = materialsForVariant;
|
|
}
|
|
let cachedMaterial = materialsForVariant[keyB];
|
|
if (cachedMaterial === void 0) {
|
|
cachedMaterial = result.clone();
|
|
materialsForVariant[keyB] = cachedMaterial;
|
|
}
|
|
result = cachedMaterial;
|
|
}
|
|
result.visible = material.visible;
|
|
result.wireframe = material.wireframe;
|
|
if (type === VSMShadowMap) {
|
|
result.side = material.shadowSide !== null ? material.shadowSide : material.side;
|
|
} else {
|
|
result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side];
|
|
}
|
|
result.alphaMap = material.alphaMap;
|
|
result.alphaTest = material.alphaTest;
|
|
result.clipShadows = material.clipShadows;
|
|
result.clippingPlanes = material.clippingPlanes;
|
|
result.clipIntersection = material.clipIntersection;
|
|
result.displacementMap = material.displacementMap;
|
|
result.displacementScale = material.displacementScale;
|
|
result.displacementBias = material.displacementBias;
|
|
result.wireframeLinewidth = material.wireframeLinewidth;
|
|
result.linewidth = material.linewidth;
|
|
if (light.isPointLight === true && result.isMeshDistanceMaterial === true) {
|
|
result.referencePosition.setFromMatrixPosition(light.matrixWorld);
|
|
result.nearDistance = shadowCameraNear;
|
|
result.farDistance = shadowCameraFar;
|
|
}
|
|
return result;
|
|
}
|
|
function renderObject(object, camera, shadowCamera, light, type) {
|
|
if (object.visible === false)
|
|
return;
|
|
const visible = object.layers.test(camera.layers);
|
|
if (visible && (object.isMesh || object.isLine || object.isPoints)) {
|
|
if ((object.castShadow || object.receiveShadow && type === VSMShadowMap) && (!object.frustumCulled || _frustum.intersectsObject(object))) {
|
|
object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld);
|
|
const geometry = _objects.update(object);
|
|
const material = object.material;
|
|
if (Array.isArray(material)) {
|
|
const groups = geometry.groups;
|
|
for (let k = 0, kl = groups.length; k < kl; k++) {
|
|
const group = groups[k];
|
|
const groupMaterial = material[group.materialIndex];
|
|
if (groupMaterial && groupMaterial.visible) {
|
|
const depthMaterial = getDepthMaterial(object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type);
|
|
_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group);
|
|
}
|
|
}
|
|
} else if (material.visible) {
|
|
const depthMaterial = getDepthMaterial(object, geometry, material, light, shadowCamera.near, shadowCamera.far, type);
|
|
_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null);
|
|
}
|
|
}
|
|
}
|
|
const children = object.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
renderObject(children[i], camera, shadowCamera, light, type);
|
|
}
|
|
}
|
|
}
|
|
function WebGLState(gl, extensions, capabilities) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
function ColorBuffer() {
|
|
let locked = false;
|
|
const color = new Vector4();
|
|
let currentColorMask = null;
|
|
const currentColorClear = new Vector4(0, 0, 0, 0);
|
|
return {
|
|
setMask: function(colorMask) {
|
|
if (currentColorMask !== colorMask && !locked) {
|
|
gl.colorMask(colorMask, colorMask, colorMask, colorMask);
|
|
currentColorMask = colorMask;
|
|
}
|
|
},
|
|
setLocked: function(lock) {
|
|
locked = lock;
|
|
},
|
|
setClear: function(r, g, b2, a2, premultipliedAlpha) {
|
|
if (premultipliedAlpha === true) {
|
|
r *= a2;
|
|
g *= a2;
|
|
b2 *= a2;
|
|
}
|
|
color.set(r, g, b2, a2);
|
|
if (currentColorClear.equals(color) === false) {
|
|
gl.clearColor(r, g, b2, a2);
|
|
currentColorClear.copy(color);
|
|
}
|
|
},
|
|
reset: function() {
|
|
locked = false;
|
|
currentColorMask = null;
|
|
currentColorClear.set(-1, 0, 0, 0);
|
|
}
|
|
};
|
|
}
|
|
function DepthBuffer() {
|
|
let locked = false;
|
|
let currentDepthMask = null;
|
|
let currentDepthFunc = null;
|
|
let currentDepthClear = null;
|
|
return {
|
|
setTest: function(depthTest) {
|
|
if (depthTest) {
|
|
enable(2929);
|
|
} else {
|
|
disable(2929);
|
|
}
|
|
},
|
|
setMask: function(depthMask) {
|
|
if (currentDepthMask !== depthMask && !locked) {
|
|
gl.depthMask(depthMask);
|
|
currentDepthMask = depthMask;
|
|
}
|
|
},
|
|
setFunc: function(depthFunc) {
|
|
if (currentDepthFunc !== depthFunc) {
|
|
if (depthFunc) {
|
|
switch (depthFunc) {
|
|
case NeverDepth:
|
|
gl.depthFunc(512);
|
|
break;
|
|
case AlwaysDepth:
|
|
gl.depthFunc(519);
|
|
break;
|
|
case LessDepth:
|
|
gl.depthFunc(513);
|
|
break;
|
|
case LessEqualDepth:
|
|
gl.depthFunc(515);
|
|
break;
|
|
case EqualDepth:
|
|
gl.depthFunc(514);
|
|
break;
|
|
case GreaterEqualDepth:
|
|
gl.depthFunc(518);
|
|
break;
|
|
case GreaterDepth:
|
|
gl.depthFunc(516);
|
|
break;
|
|
case NotEqualDepth:
|
|
gl.depthFunc(517);
|
|
break;
|
|
default:
|
|
gl.depthFunc(515);
|
|
}
|
|
} else {
|
|
gl.depthFunc(515);
|
|
}
|
|
currentDepthFunc = depthFunc;
|
|
}
|
|
},
|
|
setLocked: function(lock) {
|
|
locked = lock;
|
|
},
|
|
setClear: function(depth) {
|
|
if (currentDepthClear !== depth) {
|
|
gl.clearDepth(depth);
|
|
currentDepthClear = depth;
|
|
}
|
|
},
|
|
reset: function() {
|
|
locked = false;
|
|
currentDepthMask = null;
|
|
currentDepthFunc = null;
|
|
currentDepthClear = null;
|
|
}
|
|
};
|
|
}
|
|
function StencilBuffer() {
|
|
let locked = false;
|
|
let currentStencilMask = null;
|
|
let currentStencilFunc = null;
|
|
let currentStencilRef = null;
|
|
let currentStencilFuncMask = null;
|
|
let currentStencilFail = null;
|
|
let currentStencilZFail = null;
|
|
let currentStencilZPass = null;
|
|
let currentStencilClear = null;
|
|
return {
|
|
setTest: function(stencilTest) {
|
|
if (!locked) {
|
|
if (stencilTest) {
|
|
enable(2960);
|
|
} else {
|
|
disable(2960);
|
|
}
|
|
}
|
|
},
|
|
setMask: function(stencilMask) {
|
|
if (currentStencilMask !== stencilMask && !locked) {
|
|
gl.stencilMask(stencilMask);
|
|
currentStencilMask = stencilMask;
|
|
}
|
|
},
|
|
setFunc: function(stencilFunc, stencilRef, stencilMask) {
|
|
if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) {
|
|
gl.stencilFunc(stencilFunc, stencilRef, stencilMask);
|
|
currentStencilFunc = stencilFunc;
|
|
currentStencilRef = stencilRef;
|
|
currentStencilFuncMask = stencilMask;
|
|
}
|
|
},
|
|
setOp: function(stencilFail, stencilZFail, stencilZPass) {
|
|
if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) {
|
|
gl.stencilOp(stencilFail, stencilZFail, stencilZPass);
|
|
currentStencilFail = stencilFail;
|
|
currentStencilZFail = stencilZFail;
|
|
currentStencilZPass = stencilZPass;
|
|
}
|
|
},
|
|
setLocked: function(lock) {
|
|
locked = lock;
|
|
},
|
|
setClear: function(stencil) {
|
|
if (currentStencilClear !== stencil) {
|
|
gl.clearStencil(stencil);
|
|
currentStencilClear = stencil;
|
|
}
|
|
},
|
|
reset: function() {
|
|
locked = false;
|
|
currentStencilMask = null;
|
|
currentStencilFunc = null;
|
|
currentStencilRef = null;
|
|
currentStencilFuncMask = null;
|
|
currentStencilFail = null;
|
|
currentStencilZFail = null;
|
|
currentStencilZPass = null;
|
|
currentStencilClear = null;
|
|
}
|
|
};
|
|
}
|
|
const colorBuffer = new ColorBuffer();
|
|
const depthBuffer = new DepthBuffer();
|
|
const stencilBuffer = new StencilBuffer();
|
|
let enabledCapabilities = {};
|
|
let xrFramebuffer = null;
|
|
let currentBoundFramebuffers = {};
|
|
let currentProgram = null;
|
|
let currentBlendingEnabled = false;
|
|
let currentBlending = null;
|
|
let currentBlendEquation = null;
|
|
let currentBlendSrc = null;
|
|
let currentBlendDst = null;
|
|
let currentBlendEquationAlpha = null;
|
|
let currentBlendSrcAlpha = null;
|
|
let currentBlendDstAlpha = null;
|
|
let currentPremultipledAlpha = false;
|
|
let currentFlipSided = null;
|
|
let currentCullFace = null;
|
|
let currentLineWidth = null;
|
|
let currentPolygonOffsetFactor = null;
|
|
let currentPolygonOffsetUnits = null;
|
|
const maxTextures = gl.getParameter(35661);
|
|
let lineWidthAvailable = false;
|
|
let version = 0;
|
|
const glVersion = gl.getParameter(7938);
|
|
if (glVersion.indexOf("WebGL") !== -1) {
|
|
version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]);
|
|
lineWidthAvailable = version >= 1;
|
|
} else if (glVersion.indexOf("OpenGL ES") !== -1) {
|
|
version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]);
|
|
lineWidthAvailable = version >= 2;
|
|
}
|
|
let currentTextureSlot = null;
|
|
let currentBoundTextures = {};
|
|
const scissorParam = gl.getParameter(3088);
|
|
const viewportParam = gl.getParameter(2978);
|
|
const currentScissor = new Vector4().fromArray(scissorParam);
|
|
const currentViewport = new Vector4().fromArray(viewportParam);
|
|
function createTexture(type, target, count) {
|
|
const data = new Uint8Array(4);
|
|
const texture = gl.createTexture();
|
|
gl.bindTexture(type, texture);
|
|
gl.texParameteri(type, 10241, 9728);
|
|
gl.texParameteri(type, 10240, 9728);
|
|
for (let i = 0; i < count; i++) {
|
|
gl.texImage2D(target + i, 0, 6408, 1, 1, 0, 6408, 5121, data);
|
|
}
|
|
return texture;
|
|
}
|
|
const emptyTextures = {};
|
|
emptyTextures[3553] = createTexture(3553, 3553, 1);
|
|
emptyTextures[34067] = createTexture(34067, 34069, 6);
|
|
colorBuffer.setClear(0, 0, 0, 1);
|
|
depthBuffer.setClear(1);
|
|
stencilBuffer.setClear(0);
|
|
enable(2929);
|
|
depthBuffer.setFunc(LessEqualDepth);
|
|
setFlipSided(false);
|
|
setCullFace(CullFaceBack);
|
|
enable(2884);
|
|
setBlending(NoBlending);
|
|
function enable(id) {
|
|
if (enabledCapabilities[id] !== true) {
|
|
gl.enable(id);
|
|
enabledCapabilities[id] = true;
|
|
}
|
|
}
|
|
function disable(id) {
|
|
if (enabledCapabilities[id] !== false) {
|
|
gl.disable(id);
|
|
enabledCapabilities[id] = false;
|
|
}
|
|
}
|
|
function bindXRFramebuffer(framebuffer) {
|
|
if (framebuffer !== xrFramebuffer) {
|
|
gl.bindFramebuffer(36160, framebuffer);
|
|
xrFramebuffer = framebuffer;
|
|
}
|
|
}
|
|
function bindFramebuffer(target, framebuffer) {
|
|
if (framebuffer === null && xrFramebuffer !== null)
|
|
framebuffer = xrFramebuffer;
|
|
if (currentBoundFramebuffers[target] !== framebuffer) {
|
|
gl.bindFramebuffer(target, framebuffer);
|
|
currentBoundFramebuffers[target] = framebuffer;
|
|
if (isWebGL2) {
|
|
if (target === 36009) {
|
|
currentBoundFramebuffers[36160] = framebuffer;
|
|
}
|
|
if (target === 36160) {
|
|
currentBoundFramebuffers[36009] = framebuffer;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function useProgram(program) {
|
|
if (currentProgram !== program) {
|
|
gl.useProgram(program);
|
|
currentProgram = program;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
const equationToGL = {
|
|
[AddEquation]: 32774,
|
|
[SubtractEquation]: 32778,
|
|
[ReverseSubtractEquation]: 32779
|
|
};
|
|
if (isWebGL2) {
|
|
equationToGL[MinEquation] = 32775;
|
|
equationToGL[MaxEquation] = 32776;
|
|
} else {
|
|
const extension = extensions.get("EXT_blend_minmax");
|
|
if (extension !== null) {
|
|
equationToGL[MinEquation] = extension.MIN_EXT;
|
|
equationToGL[MaxEquation] = extension.MAX_EXT;
|
|
}
|
|
}
|
|
const factorToGL = {
|
|
[ZeroFactor]: 0,
|
|
[OneFactor]: 1,
|
|
[SrcColorFactor]: 768,
|
|
[SrcAlphaFactor]: 770,
|
|
[SrcAlphaSaturateFactor]: 776,
|
|
[DstColorFactor]: 774,
|
|
[DstAlphaFactor]: 772,
|
|
[OneMinusSrcColorFactor]: 769,
|
|
[OneMinusSrcAlphaFactor]: 771,
|
|
[OneMinusDstColorFactor]: 775,
|
|
[OneMinusDstAlphaFactor]: 773
|
|
};
|
|
function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) {
|
|
if (blending === NoBlending) {
|
|
if (currentBlendingEnabled === true) {
|
|
disable(3042);
|
|
currentBlendingEnabled = false;
|
|
}
|
|
return;
|
|
}
|
|
if (currentBlendingEnabled === false) {
|
|
enable(3042);
|
|
currentBlendingEnabled = true;
|
|
}
|
|
if (blending !== CustomBlending) {
|
|
if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) {
|
|
if (currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation) {
|
|
gl.blendEquation(32774);
|
|
currentBlendEquation = AddEquation;
|
|
currentBlendEquationAlpha = AddEquation;
|
|
}
|
|
if (premultipliedAlpha) {
|
|
switch (blending) {
|
|
case NormalBlending:
|
|
gl.blendFuncSeparate(1, 771, 1, 771);
|
|
break;
|
|
case AdditiveBlending:
|
|
gl.blendFunc(1, 1);
|
|
break;
|
|
case SubtractiveBlending:
|
|
gl.blendFuncSeparate(0, 0, 769, 771);
|
|
break;
|
|
case MultiplyBlending:
|
|
gl.blendFuncSeparate(0, 768, 0, 770);
|
|
break;
|
|
default:
|
|
console.error("THREE.WebGLState: Invalid blending: ", blending);
|
|
break;
|
|
}
|
|
} else {
|
|
switch (blending) {
|
|
case NormalBlending:
|
|
gl.blendFuncSeparate(770, 771, 1, 771);
|
|
break;
|
|
case AdditiveBlending:
|
|
gl.blendFunc(770, 1);
|
|
break;
|
|
case SubtractiveBlending:
|
|
gl.blendFunc(0, 769);
|
|
break;
|
|
case MultiplyBlending:
|
|
gl.blendFunc(0, 768);
|
|
break;
|
|
default:
|
|
console.error("THREE.WebGLState: Invalid blending: ", blending);
|
|
break;
|
|
}
|
|
}
|
|
currentBlendSrc = null;
|
|
currentBlendDst = null;
|
|
currentBlendSrcAlpha = null;
|
|
currentBlendDstAlpha = null;
|
|
currentBlending = blending;
|
|
currentPremultipledAlpha = premultipliedAlpha;
|
|
}
|
|
return;
|
|
}
|
|
blendEquationAlpha = blendEquationAlpha || blendEquation;
|
|
blendSrcAlpha = blendSrcAlpha || blendSrc;
|
|
blendDstAlpha = blendDstAlpha || blendDst;
|
|
if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) {
|
|
gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]);
|
|
currentBlendEquation = blendEquation;
|
|
currentBlendEquationAlpha = blendEquationAlpha;
|
|
}
|
|
if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) {
|
|
gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]);
|
|
currentBlendSrc = blendSrc;
|
|
currentBlendDst = blendDst;
|
|
currentBlendSrcAlpha = blendSrcAlpha;
|
|
currentBlendDstAlpha = blendDstAlpha;
|
|
}
|
|
currentBlending = blending;
|
|
currentPremultipledAlpha = null;
|
|
}
|
|
function setMaterial(material, frontFaceCW) {
|
|
material.side === DoubleSide ? disable(2884) : enable(2884);
|
|
let flipSided = material.side === BackSide;
|
|
if (frontFaceCW)
|
|
flipSided = !flipSided;
|
|
setFlipSided(flipSided);
|
|
material.blending === NormalBlending && material.transparent === false ? setBlending(NoBlending) : setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha);
|
|
depthBuffer.setFunc(material.depthFunc);
|
|
depthBuffer.setTest(material.depthTest);
|
|
depthBuffer.setMask(material.depthWrite);
|
|
colorBuffer.setMask(material.colorWrite);
|
|
const stencilWrite = material.stencilWrite;
|
|
stencilBuffer.setTest(stencilWrite);
|
|
if (stencilWrite) {
|
|
stencilBuffer.setMask(material.stencilWriteMask);
|
|
stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask);
|
|
stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass);
|
|
}
|
|
setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits);
|
|
material.alphaToCoverage === true ? enable(32926) : disable(32926);
|
|
}
|
|
function setFlipSided(flipSided) {
|
|
if (currentFlipSided !== flipSided) {
|
|
if (flipSided) {
|
|
gl.frontFace(2304);
|
|
} else {
|
|
gl.frontFace(2305);
|
|
}
|
|
currentFlipSided = flipSided;
|
|
}
|
|
}
|
|
function setCullFace(cullFace) {
|
|
if (cullFace !== CullFaceNone) {
|
|
enable(2884);
|
|
if (cullFace !== currentCullFace) {
|
|
if (cullFace === CullFaceBack) {
|
|
gl.cullFace(1029);
|
|
} else if (cullFace === CullFaceFront) {
|
|
gl.cullFace(1028);
|
|
} else {
|
|
gl.cullFace(1032);
|
|
}
|
|
}
|
|
} else {
|
|
disable(2884);
|
|
}
|
|
currentCullFace = cullFace;
|
|
}
|
|
function setLineWidth(width) {
|
|
if (width !== currentLineWidth) {
|
|
if (lineWidthAvailable)
|
|
gl.lineWidth(width);
|
|
currentLineWidth = width;
|
|
}
|
|
}
|
|
function setPolygonOffset(polygonOffset, factor, units) {
|
|
if (polygonOffset) {
|
|
enable(32823);
|
|
if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) {
|
|
gl.polygonOffset(factor, units);
|
|
currentPolygonOffsetFactor = factor;
|
|
currentPolygonOffsetUnits = units;
|
|
}
|
|
} else {
|
|
disable(32823);
|
|
}
|
|
}
|
|
function setScissorTest(scissorTest) {
|
|
if (scissorTest) {
|
|
enable(3089);
|
|
} else {
|
|
disable(3089);
|
|
}
|
|
}
|
|
function activeTexture(webglSlot) {
|
|
if (webglSlot === void 0)
|
|
webglSlot = 33984 + maxTextures - 1;
|
|
if (currentTextureSlot !== webglSlot) {
|
|
gl.activeTexture(webglSlot);
|
|
currentTextureSlot = webglSlot;
|
|
}
|
|
}
|
|
function bindTexture(webglType, webglTexture) {
|
|
if (currentTextureSlot === null) {
|
|
activeTexture();
|
|
}
|
|
let boundTexture = currentBoundTextures[currentTextureSlot];
|
|
if (boundTexture === void 0) {
|
|
boundTexture = { type: void 0, texture: void 0 };
|
|
currentBoundTextures[currentTextureSlot] = boundTexture;
|
|
}
|
|
if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
|
|
gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]);
|
|
boundTexture.type = webglType;
|
|
boundTexture.texture = webglTexture;
|
|
}
|
|
}
|
|
function unbindTexture() {
|
|
const boundTexture = currentBoundTextures[currentTextureSlot];
|
|
if (boundTexture !== void 0 && boundTexture.type !== void 0) {
|
|
gl.bindTexture(boundTexture.type, null);
|
|
boundTexture.type = void 0;
|
|
boundTexture.texture = void 0;
|
|
}
|
|
}
|
|
function compressedTexImage2D() {
|
|
try {
|
|
gl.compressedTexImage2D.apply(gl, arguments);
|
|
} catch (error) {
|
|
console.error("THREE.WebGLState:", error);
|
|
}
|
|
}
|
|
function texImage2D() {
|
|
try {
|
|
gl.texImage2D.apply(gl, arguments);
|
|
} catch (error) {
|
|
console.error("THREE.WebGLState:", error);
|
|
}
|
|
}
|
|
function texImage3D() {
|
|
try {
|
|
gl.texImage3D.apply(gl, arguments);
|
|
} catch (error) {
|
|
console.error("THREE.WebGLState:", error);
|
|
}
|
|
}
|
|
function scissor(scissor2) {
|
|
if (currentScissor.equals(scissor2) === false) {
|
|
gl.scissor(scissor2.x, scissor2.y, scissor2.z, scissor2.w);
|
|
currentScissor.copy(scissor2);
|
|
}
|
|
}
|
|
function viewport(viewport2) {
|
|
if (currentViewport.equals(viewport2) === false) {
|
|
gl.viewport(viewport2.x, viewport2.y, viewport2.z, viewport2.w);
|
|
currentViewport.copy(viewport2);
|
|
}
|
|
}
|
|
function reset() {
|
|
gl.disable(3042);
|
|
gl.disable(2884);
|
|
gl.disable(2929);
|
|
gl.disable(32823);
|
|
gl.disable(3089);
|
|
gl.disable(2960);
|
|
gl.disable(32926);
|
|
gl.blendEquation(32774);
|
|
gl.blendFunc(1, 0);
|
|
gl.blendFuncSeparate(1, 0, 1, 0);
|
|
gl.colorMask(true, true, true, true);
|
|
gl.clearColor(0, 0, 0, 0);
|
|
gl.depthMask(true);
|
|
gl.depthFunc(513);
|
|
gl.clearDepth(1);
|
|
gl.stencilMask(4294967295);
|
|
gl.stencilFunc(519, 0, 4294967295);
|
|
gl.stencilOp(7680, 7680, 7680);
|
|
gl.clearStencil(0);
|
|
gl.cullFace(1029);
|
|
gl.frontFace(2305);
|
|
gl.polygonOffset(0, 0);
|
|
gl.activeTexture(33984);
|
|
gl.bindFramebuffer(36160, null);
|
|
if (isWebGL2 === true) {
|
|
gl.bindFramebuffer(36009, null);
|
|
gl.bindFramebuffer(36008, null);
|
|
}
|
|
gl.useProgram(null);
|
|
gl.lineWidth(1);
|
|
gl.scissor(0, 0, gl.canvas.width, gl.canvas.height);
|
|
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
|
enabledCapabilities = {};
|
|
currentTextureSlot = null;
|
|
currentBoundTextures = {};
|
|
xrFramebuffer = null;
|
|
currentBoundFramebuffers = {};
|
|
currentProgram = null;
|
|
currentBlendingEnabled = false;
|
|
currentBlending = null;
|
|
currentBlendEquation = null;
|
|
currentBlendSrc = null;
|
|
currentBlendDst = null;
|
|
currentBlendEquationAlpha = null;
|
|
currentBlendSrcAlpha = null;
|
|
currentBlendDstAlpha = null;
|
|
currentPremultipledAlpha = false;
|
|
currentFlipSided = null;
|
|
currentCullFace = null;
|
|
currentLineWidth = null;
|
|
currentPolygonOffsetFactor = null;
|
|
currentPolygonOffsetUnits = null;
|
|
currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height);
|
|
currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height);
|
|
colorBuffer.reset();
|
|
depthBuffer.reset();
|
|
stencilBuffer.reset();
|
|
}
|
|
return {
|
|
buffers: {
|
|
color: colorBuffer,
|
|
depth: depthBuffer,
|
|
stencil: stencilBuffer
|
|
},
|
|
enable,
|
|
disable,
|
|
bindFramebuffer,
|
|
bindXRFramebuffer,
|
|
useProgram,
|
|
setBlending,
|
|
setMaterial,
|
|
setFlipSided,
|
|
setCullFace,
|
|
setLineWidth,
|
|
setPolygonOffset,
|
|
setScissorTest,
|
|
activeTexture,
|
|
bindTexture,
|
|
unbindTexture,
|
|
compressedTexImage2D,
|
|
texImage2D,
|
|
texImage3D,
|
|
scissor,
|
|
viewport,
|
|
reset
|
|
};
|
|
}
|
|
function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
const maxTextures = capabilities.maxTextures;
|
|
const maxCubemapSize = capabilities.maxCubemapSize;
|
|
const maxTextureSize = capabilities.maxTextureSize;
|
|
const maxSamples = capabilities.maxSamples;
|
|
const _videoTextures = new WeakMap();
|
|
let _canvas2;
|
|
let useOffscreenCanvas = false;
|
|
try {
|
|
useOffscreenCanvas = typeof OffscreenCanvas !== "undefined" && new OffscreenCanvas(1, 1).getContext("2d") !== null;
|
|
} catch (err) {
|
|
}
|
|
function createCanvas(width, height) {
|
|
return useOffscreenCanvas ? new OffscreenCanvas(width, height) : document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
|
}
|
|
function resizeImage(image, needsPowerOfTwo, needsNewCanvas, maxSize) {
|
|
let scale = 1;
|
|
if (image.width > maxSize || image.height > maxSize) {
|
|
scale = maxSize / Math.max(image.width, image.height);
|
|
}
|
|
if (scale < 1 || needsPowerOfTwo === true) {
|
|
if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) {
|
|
const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor;
|
|
const width = floor(scale * image.width);
|
|
const height = floor(scale * image.height);
|
|
if (_canvas2 === void 0)
|
|
_canvas2 = createCanvas(width, height);
|
|
const canvas = needsNewCanvas ? createCanvas(width, height) : _canvas2;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
const context = canvas.getContext("2d");
|
|
context.drawImage(image, 0, 0, width, height);
|
|
console.warn("THREE.WebGLRenderer: Texture has been resized from (" + image.width + "x" + image.height + ") to (" + width + "x" + height + ").");
|
|
return canvas;
|
|
} else {
|
|
if ("data" in image) {
|
|
console.warn("THREE.WebGLRenderer: Image in DataTexture is too big (" + image.width + "x" + image.height + ").");
|
|
}
|
|
return image;
|
|
}
|
|
}
|
|
return image;
|
|
}
|
|
function isPowerOfTwo$1(image) {
|
|
return isPowerOfTwo(image.width) && isPowerOfTwo(image.height);
|
|
}
|
|
function textureNeedsPowerOfTwo(texture) {
|
|
if (isWebGL2)
|
|
return false;
|
|
return texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping || texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
|
|
}
|
|
function textureNeedsGenerateMipmaps(texture, supportsMips) {
|
|
return texture.generateMipmaps && supportsMips && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
|
|
}
|
|
function generateMipmap(target, texture, width, height, depth = 1) {
|
|
_gl.generateMipmap(target);
|
|
const textureProperties = properties.get(texture);
|
|
textureProperties.__maxMipLevel = Math.log2(Math.max(width, height, depth));
|
|
}
|
|
function getInternalFormat(internalFormatName, glFormat, glType) {
|
|
if (isWebGL2 === false)
|
|
return glFormat;
|
|
if (internalFormatName !== null) {
|
|
if (_gl[internalFormatName] !== void 0)
|
|
return _gl[internalFormatName];
|
|
console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '" + internalFormatName + "'");
|
|
}
|
|
let internalFormat = glFormat;
|
|
if (glFormat === 6403) {
|
|
if (glType === 5126)
|
|
internalFormat = 33326;
|
|
if (glType === 5131)
|
|
internalFormat = 33325;
|
|
if (glType === 5121)
|
|
internalFormat = 33321;
|
|
}
|
|
if (glFormat === 6407) {
|
|
if (glType === 5126)
|
|
internalFormat = 34837;
|
|
if (glType === 5131)
|
|
internalFormat = 34843;
|
|
if (glType === 5121)
|
|
internalFormat = 32849;
|
|
}
|
|
if (glFormat === 6408) {
|
|
if (glType === 5126)
|
|
internalFormat = 34836;
|
|
if (glType === 5131)
|
|
internalFormat = 34842;
|
|
if (glType === 5121)
|
|
internalFormat = 32856;
|
|
}
|
|
if (internalFormat === 33325 || internalFormat === 33326 || internalFormat === 34842 || internalFormat === 34836) {
|
|
extensions.get("EXT_color_buffer_float");
|
|
}
|
|
return internalFormat;
|
|
}
|
|
function filterFallback(f) {
|
|
if (f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter) {
|
|
return 9728;
|
|
}
|
|
return 9729;
|
|
}
|
|
function onTextureDispose(event) {
|
|
const texture = event.target;
|
|
texture.removeEventListener("dispose", onTextureDispose);
|
|
deallocateTexture(texture);
|
|
if (texture.isVideoTexture) {
|
|
_videoTextures.delete(texture);
|
|
}
|
|
info.memory.textures--;
|
|
}
|
|
function onRenderTargetDispose(event) {
|
|
const renderTarget = event.target;
|
|
renderTarget.removeEventListener("dispose", onRenderTargetDispose);
|
|
deallocateRenderTarget(renderTarget);
|
|
}
|
|
function deallocateTexture(texture) {
|
|
const textureProperties = properties.get(texture);
|
|
if (textureProperties.__webglInit === void 0)
|
|
return;
|
|
_gl.deleteTexture(textureProperties.__webglTexture);
|
|
properties.remove(texture);
|
|
}
|
|
function deallocateRenderTarget(renderTarget) {
|
|
const texture = renderTarget.texture;
|
|
const renderTargetProperties = properties.get(renderTarget);
|
|
const textureProperties = properties.get(texture);
|
|
if (!renderTarget)
|
|
return;
|
|
if (textureProperties.__webglTexture !== void 0) {
|
|
_gl.deleteTexture(textureProperties.__webglTexture);
|
|
info.memory.textures--;
|
|
}
|
|
if (renderTarget.depthTexture) {
|
|
renderTarget.depthTexture.dispose();
|
|
}
|
|
if (renderTarget.isWebGLCubeRenderTarget) {
|
|
for (let i = 0; i < 6; i++) {
|
|
_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]);
|
|
if (renderTargetProperties.__webglDepthbuffer)
|
|
_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]);
|
|
}
|
|
} else {
|
|
_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer);
|
|
if (renderTargetProperties.__webglDepthbuffer)
|
|
_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer);
|
|
if (renderTargetProperties.__webglMultisampledFramebuffer)
|
|
_gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer);
|
|
if (renderTargetProperties.__webglColorRenderbuffer)
|
|
_gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer);
|
|
if (renderTargetProperties.__webglDepthRenderbuffer)
|
|
_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer);
|
|
}
|
|
if (renderTarget.isWebGLMultipleRenderTargets) {
|
|
for (let i = 0, il = texture.length; i < il; i++) {
|
|
const attachmentProperties = properties.get(texture[i]);
|
|
if (attachmentProperties.__webglTexture) {
|
|
_gl.deleteTexture(attachmentProperties.__webglTexture);
|
|
info.memory.textures--;
|
|
}
|
|
properties.remove(texture[i]);
|
|
}
|
|
}
|
|
properties.remove(texture);
|
|
properties.remove(renderTarget);
|
|
}
|
|
let textureUnits = 0;
|
|
function resetTextureUnits() {
|
|
textureUnits = 0;
|
|
}
|
|
function allocateTextureUnit() {
|
|
const textureUnit = textureUnits;
|
|
if (textureUnit >= maxTextures) {
|
|
console.warn("THREE.WebGLTextures: Trying to use " + textureUnit + " texture units while this GPU supports only " + maxTextures);
|
|
}
|
|
textureUnits += 1;
|
|
return textureUnit;
|
|
}
|
|
function setTexture2D(texture, slot) {
|
|
const textureProperties = properties.get(texture);
|
|
if (texture.isVideoTexture)
|
|
updateVideoTexture(texture);
|
|
if (texture.version > 0 && textureProperties.__version !== texture.version) {
|
|
const image = texture.image;
|
|
if (image === void 0) {
|
|
console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");
|
|
} else if (image.complete === false) {
|
|
console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");
|
|
} else {
|
|
uploadTexture(textureProperties, texture, slot);
|
|
return;
|
|
}
|
|
}
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(3553, textureProperties.__webglTexture);
|
|
}
|
|
function setTexture2DArray(texture, slot) {
|
|
const textureProperties = properties.get(texture);
|
|
if (texture.version > 0 && textureProperties.__version !== texture.version) {
|
|
uploadTexture(textureProperties, texture, slot);
|
|
return;
|
|
}
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(35866, textureProperties.__webglTexture);
|
|
}
|
|
function setTexture3D(texture, slot) {
|
|
const textureProperties = properties.get(texture);
|
|
if (texture.version > 0 && textureProperties.__version !== texture.version) {
|
|
uploadTexture(textureProperties, texture, slot);
|
|
return;
|
|
}
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(32879, textureProperties.__webglTexture);
|
|
}
|
|
function setTextureCube(texture, slot) {
|
|
const textureProperties = properties.get(texture);
|
|
if (texture.version > 0 && textureProperties.__version !== texture.version) {
|
|
uploadCubeTexture(textureProperties, texture, slot);
|
|
return;
|
|
}
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(34067, textureProperties.__webglTexture);
|
|
}
|
|
const wrappingToGL = {
|
|
[RepeatWrapping]: 10497,
|
|
[ClampToEdgeWrapping]: 33071,
|
|
[MirroredRepeatWrapping]: 33648
|
|
};
|
|
const filterToGL = {
|
|
[NearestFilter]: 9728,
|
|
[NearestMipmapNearestFilter]: 9984,
|
|
[NearestMipmapLinearFilter]: 9986,
|
|
[LinearFilter]: 9729,
|
|
[LinearMipmapNearestFilter]: 9985,
|
|
[LinearMipmapLinearFilter]: 9987
|
|
};
|
|
function setTextureParameters(textureType, texture, supportsMips) {
|
|
if (supportsMips) {
|
|
_gl.texParameteri(textureType, 10242, wrappingToGL[texture.wrapS]);
|
|
_gl.texParameteri(textureType, 10243, wrappingToGL[texture.wrapT]);
|
|
if (textureType === 32879 || textureType === 35866) {
|
|
_gl.texParameteri(textureType, 32882, wrappingToGL[texture.wrapR]);
|
|
}
|
|
_gl.texParameteri(textureType, 10240, filterToGL[texture.magFilter]);
|
|
_gl.texParameteri(textureType, 10241, filterToGL[texture.minFilter]);
|
|
} else {
|
|
_gl.texParameteri(textureType, 10242, 33071);
|
|
_gl.texParameteri(textureType, 10243, 33071);
|
|
if (textureType === 32879 || textureType === 35866) {
|
|
_gl.texParameteri(textureType, 32882, 33071);
|
|
}
|
|
if (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) {
|
|
console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.");
|
|
}
|
|
_gl.texParameteri(textureType, 10240, filterFallback(texture.magFilter));
|
|
_gl.texParameteri(textureType, 10241, filterFallback(texture.minFilter));
|
|
if (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) {
|
|
console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.");
|
|
}
|
|
}
|
|
if (extensions.has("EXT_texture_filter_anisotropic") === true) {
|
|
const extension = extensions.get("EXT_texture_filter_anisotropic");
|
|
if (texture.type === FloatType && extensions.has("OES_texture_float_linear") === false)
|
|
return;
|
|
if (isWebGL2 === false && (texture.type === HalfFloatType && extensions.has("OES_texture_half_float_linear") === false))
|
|
return;
|
|
if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) {
|
|
_gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy()));
|
|
properties.get(texture).__currentAnisotropy = texture.anisotropy;
|
|
}
|
|
}
|
|
}
|
|
function initTexture(textureProperties, texture) {
|
|
if (textureProperties.__webglInit === void 0) {
|
|
textureProperties.__webglInit = true;
|
|
texture.addEventListener("dispose", onTextureDispose);
|
|
textureProperties.__webglTexture = _gl.createTexture();
|
|
info.memory.textures++;
|
|
}
|
|
}
|
|
function uploadTexture(textureProperties, texture, slot) {
|
|
let textureType = 3553;
|
|
if (texture.isDataTexture2DArray)
|
|
textureType = 35866;
|
|
if (texture.isDataTexture3D)
|
|
textureType = 32879;
|
|
initTexture(textureProperties, texture);
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(textureType, textureProperties.__webglTexture);
|
|
_gl.pixelStorei(37440, texture.flipY);
|
|
_gl.pixelStorei(37441, texture.premultiplyAlpha);
|
|
_gl.pixelStorei(3317, texture.unpackAlignment);
|
|
_gl.pixelStorei(37443, 0);
|
|
const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false;
|
|
const image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize);
|
|
const supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format);
|
|
let glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
setTextureParameters(textureType, texture, supportsMips);
|
|
let mipmap;
|
|
const mipmaps = texture.mipmaps;
|
|
if (texture.isDepthTexture) {
|
|
glInternalFormat = 6402;
|
|
if (isWebGL2) {
|
|
if (texture.type === FloatType) {
|
|
glInternalFormat = 36012;
|
|
} else if (texture.type === UnsignedIntType) {
|
|
glInternalFormat = 33190;
|
|
} else if (texture.type === UnsignedInt248Type) {
|
|
glInternalFormat = 35056;
|
|
} else {
|
|
glInternalFormat = 33189;
|
|
}
|
|
} else {
|
|
if (texture.type === FloatType) {
|
|
console.error("WebGLRenderer: Floating point depth texture requires WebGL2.");
|
|
}
|
|
}
|
|
if (texture.format === DepthFormat && glInternalFormat === 6402) {
|
|
if (texture.type !== UnsignedShortType && texture.type !== UnsignedIntType) {
|
|
console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.");
|
|
texture.type = UnsignedShortType;
|
|
glType = utils.convert(texture.type);
|
|
}
|
|
}
|
|
if (texture.format === DepthStencilFormat && glInternalFormat === 6402) {
|
|
glInternalFormat = 34041;
|
|
if (texture.type !== UnsignedInt248Type) {
|
|
console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.");
|
|
texture.type = UnsignedInt248Type;
|
|
glType = utils.convert(texture.type);
|
|
}
|
|
}
|
|
state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null);
|
|
} else if (texture.isDataTexture) {
|
|
if (mipmaps.length > 0 && supportsMips) {
|
|
for (let i = 0, il = mipmaps.length; i < il; i++) {
|
|
mipmap = mipmaps[i];
|
|
state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
|
|
}
|
|
texture.generateMipmaps = false;
|
|
textureProperties.__maxMipLevel = mipmaps.length - 1;
|
|
} else {
|
|
state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data);
|
|
textureProperties.__maxMipLevel = 0;
|
|
}
|
|
} else if (texture.isCompressedTexture) {
|
|
for (let i = 0, il = mipmaps.length; i < il; i++) {
|
|
mipmap = mipmaps[i];
|
|
if (texture.format !== RGBAFormat && texture.format !== RGBFormat) {
|
|
if (glFormat !== null) {
|
|
state.compressedTexImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data);
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");
|
|
}
|
|
} else {
|
|
state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
|
|
}
|
|
}
|
|
textureProperties.__maxMipLevel = mipmaps.length - 1;
|
|
} else if (texture.isDataTexture2DArray) {
|
|
state.texImage3D(35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data);
|
|
textureProperties.__maxMipLevel = 0;
|
|
} else if (texture.isDataTexture3D) {
|
|
state.texImage3D(32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data);
|
|
textureProperties.__maxMipLevel = 0;
|
|
} else {
|
|
if (mipmaps.length > 0 && supportsMips) {
|
|
for (let i = 0, il = mipmaps.length; i < il; i++) {
|
|
mipmap = mipmaps[i];
|
|
state.texImage2D(3553, i, glInternalFormat, glFormat, glType, mipmap);
|
|
}
|
|
texture.generateMipmaps = false;
|
|
textureProperties.__maxMipLevel = mipmaps.length - 1;
|
|
} else {
|
|
state.texImage2D(3553, 0, glInternalFormat, glFormat, glType, image);
|
|
textureProperties.__maxMipLevel = 0;
|
|
}
|
|
}
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
generateMipmap(textureType, texture, image.width, image.height);
|
|
}
|
|
textureProperties.__version = texture.version;
|
|
if (texture.onUpdate)
|
|
texture.onUpdate(texture);
|
|
}
|
|
function uploadCubeTexture(textureProperties, texture, slot) {
|
|
if (texture.image.length !== 6)
|
|
return;
|
|
initTexture(textureProperties, texture);
|
|
state.activeTexture(33984 + slot);
|
|
state.bindTexture(34067, textureProperties.__webglTexture);
|
|
_gl.pixelStorei(37440, texture.flipY);
|
|
_gl.pixelStorei(37441, texture.premultiplyAlpha);
|
|
_gl.pixelStorei(3317, texture.unpackAlignment);
|
|
_gl.pixelStorei(37443, 0);
|
|
const isCompressed = texture && (texture.isCompressedTexture || texture.image[0].isCompressedTexture);
|
|
const isDataTexture = texture.image[0] && texture.image[0].isDataTexture;
|
|
const cubeImage = [];
|
|
for (let i = 0; i < 6; i++) {
|
|
if (!isCompressed && !isDataTexture) {
|
|
cubeImage[i] = resizeImage(texture.image[i], false, true, maxCubemapSize);
|
|
} else {
|
|
cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i];
|
|
}
|
|
}
|
|
const image = cubeImage[0], supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format), glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
setTextureParameters(34067, texture, supportsMips);
|
|
let mipmaps;
|
|
if (isCompressed) {
|
|
for (let i = 0; i < 6; i++) {
|
|
mipmaps = cubeImage[i].mipmaps;
|
|
for (let j = 0; j < mipmaps.length; j++) {
|
|
const mipmap = mipmaps[j];
|
|
if (texture.format !== RGBAFormat && texture.format !== RGBFormat) {
|
|
if (glFormat !== null) {
|
|
state.compressedTexImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data);
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()");
|
|
}
|
|
} else {
|
|
state.texImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
|
|
}
|
|
}
|
|
}
|
|
textureProperties.__maxMipLevel = mipmaps.length - 1;
|
|
} else {
|
|
mipmaps = texture.mipmaps;
|
|
for (let i = 0; i < 6; i++) {
|
|
if (isDataTexture) {
|
|
state.texImage2D(34069 + i, 0, glInternalFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
|
|
for (let j = 0; j < mipmaps.length; j++) {
|
|
const mipmap = mipmaps[j];
|
|
const mipmapImage = mipmap.image[i].image;
|
|
state.texImage2D(34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data);
|
|
}
|
|
} else {
|
|
state.texImage2D(34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]);
|
|
for (let j = 0; j < mipmaps.length; j++) {
|
|
const mipmap = mipmaps[j];
|
|
state.texImage2D(34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i]);
|
|
}
|
|
}
|
|
}
|
|
textureProperties.__maxMipLevel = mipmaps.length;
|
|
}
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
generateMipmap(34067, texture, image.width, image.height);
|
|
}
|
|
textureProperties.__version = texture.version;
|
|
if (texture.onUpdate)
|
|
texture.onUpdate(texture);
|
|
}
|
|
function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) {
|
|
const glFormat = utils.convert(texture.format);
|
|
const glType = utils.convert(texture.type);
|
|
const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
if (textureTarget === 32879 || textureTarget === 35866) {
|
|
state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null);
|
|
} else {
|
|
state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null);
|
|
}
|
|
state.bindFramebuffer(36160, framebuffer);
|
|
_gl.framebufferTexture2D(36160, attachment, textureTarget, properties.get(texture).__webglTexture, 0);
|
|
state.bindFramebuffer(36160, null);
|
|
}
|
|
function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) {
|
|
_gl.bindRenderbuffer(36161, renderbuffer);
|
|
if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) {
|
|
let glInternalFormat = 33189;
|
|
if (isMultisample) {
|
|
const depthTexture = renderTarget.depthTexture;
|
|
if (depthTexture && depthTexture.isDepthTexture) {
|
|
if (depthTexture.type === FloatType) {
|
|
glInternalFormat = 36012;
|
|
} else if (depthTexture.type === UnsignedIntType) {
|
|
glInternalFormat = 33190;
|
|
}
|
|
}
|
|
const samples = getRenderTargetSamples(renderTarget);
|
|
_gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height);
|
|
} else {
|
|
_gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height);
|
|
}
|
|
_gl.framebufferRenderbuffer(36160, 36096, 36161, renderbuffer);
|
|
} else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) {
|
|
if (isMultisample) {
|
|
const samples = getRenderTargetSamples(renderTarget);
|
|
_gl.renderbufferStorageMultisample(36161, samples, 35056, renderTarget.width, renderTarget.height);
|
|
} else {
|
|
_gl.renderbufferStorage(36161, 34041, renderTarget.width, renderTarget.height);
|
|
}
|
|
_gl.framebufferRenderbuffer(36160, 33306, 36161, renderbuffer);
|
|
} else {
|
|
const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[0] : renderTarget.texture;
|
|
const glFormat = utils.convert(texture.format);
|
|
const glType = utils.convert(texture.type);
|
|
const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
if (isMultisample) {
|
|
const samples = getRenderTargetSamples(renderTarget);
|
|
_gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height);
|
|
} else {
|
|
_gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height);
|
|
}
|
|
}
|
|
_gl.bindRenderbuffer(36161, null);
|
|
}
|
|
function setupDepthTexture(framebuffer, renderTarget) {
|
|
const isCube = renderTarget && renderTarget.isWebGLCubeRenderTarget;
|
|
if (isCube)
|
|
throw new Error("Depth Texture with cube render targets is not supported");
|
|
state.bindFramebuffer(36160, framebuffer);
|
|
if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) {
|
|
throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");
|
|
}
|
|
if (!properties.get(renderTarget.depthTexture).__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height) {
|
|
renderTarget.depthTexture.image.width = renderTarget.width;
|
|
renderTarget.depthTexture.image.height = renderTarget.height;
|
|
renderTarget.depthTexture.needsUpdate = true;
|
|
}
|
|
setTexture2D(renderTarget.depthTexture, 0);
|
|
const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture;
|
|
if (renderTarget.depthTexture.format === DepthFormat) {
|
|
_gl.framebufferTexture2D(36160, 36096, 3553, webglDepthTexture, 0);
|
|
} else if (renderTarget.depthTexture.format === DepthStencilFormat) {
|
|
_gl.framebufferTexture2D(36160, 33306, 3553, webglDepthTexture, 0);
|
|
} else {
|
|
throw new Error("Unknown depthTexture format");
|
|
}
|
|
}
|
|
function setupDepthRenderbuffer(renderTarget) {
|
|
const renderTargetProperties = properties.get(renderTarget);
|
|
const isCube = renderTarget.isWebGLCubeRenderTarget === true;
|
|
if (renderTarget.depthTexture) {
|
|
if (isCube)
|
|
throw new Error("target.depthTexture not supported in Cube render targets");
|
|
setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget);
|
|
} else {
|
|
if (isCube) {
|
|
renderTargetProperties.__webglDepthbuffer = [];
|
|
for (let i = 0; i < 6; i++) {
|
|
state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer[i]);
|
|
renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer();
|
|
setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget, false);
|
|
}
|
|
} else {
|
|
state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer);
|
|
renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
|
|
setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget, false);
|
|
}
|
|
}
|
|
state.bindFramebuffer(36160, null);
|
|
}
|
|
function setupRenderTarget(renderTarget) {
|
|
const texture = renderTarget.texture;
|
|
const renderTargetProperties = properties.get(renderTarget);
|
|
const textureProperties = properties.get(texture);
|
|
renderTarget.addEventListener("dispose", onRenderTargetDispose);
|
|
if (renderTarget.isWebGLMultipleRenderTargets !== true) {
|
|
textureProperties.__webglTexture = _gl.createTexture();
|
|
textureProperties.__version = texture.version;
|
|
info.memory.textures++;
|
|
}
|
|
const isCube = renderTarget.isWebGLCubeRenderTarget === true;
|
|
const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true;
|
|
const isMultisample = renderTarget.isWebGLMultisampleRenderTarget === true;
|
|
const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray;
|
|
const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2;
|
|
if (isWebGL2 && texture.format === RGBFormat && (texture.type === FloatType || texture.type === HalfFloatType)) {
|
|
texture.format = RGBAFormat;
|
|
console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.");
|
|
}
|
|
if (isCube) {
|
|
renderTargetProperties.__webglFramebuffer = [];
|
|
for (let i = 0; i < 6; i++) {
|
|
renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer();
|
|
}
|
|
} else {
|
|
renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
|
|
if (isMultipleRenderTargets) {
|
|
if (capabilities.drawBuffers) {
|
|
const textures = renderTarget.texture;
|
|
for (let i = 0, il = textures.length; i < il; i++) {
|
|
const attachmentProperties = properties.get(textures[i]);
|
|
if (attachmentProperties.__webglTexture === void 0) {
|
|
attachmentProperties.__webglTexture = _gl.createTexture();
|
|
info.memory.textures++;
|
|
}
|
|
}
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.");
|
|
}
|
|
} else if (isMultisample) {
|
|
if (isWebGL2) {
|
|
renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
|
|
renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
|
|
_gl.bindRenderbuffer(36161, renderTargetProperties.__webglColorRenderbuffer);
|
|
const glFormat = utils.convert(texture.format);
|
|
const glType = utils.convert(texture.type);
|
|
const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType);
|
|
const samples = getRenderTargetSamples(renderTarget);
|
|
_gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height);
|
|
state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer);
|
|
_gl.framebufferRenderbuffer(36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer);
|
|
_gl.bindRenderbuffer(36161, null);
|
|
if (renderTarget.depthBuffer) {
|
|
renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
|
|
setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true);
|
|
}
|
|
state.bindFramebuffer(36160, null);
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");
|
|
}
|
|
}
|
|
}
|
|
if (isCube) {
|
|
state.bindTexture(34067, textureProperties.__webglTexture);
|
|
setTextureParameters(34067, texture, supportsMips);
|
|
for (let i = 0; i < 6; i++) {
|
|
setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, 36064, 34069 + i);
|
|
}
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
generateMipmap(34067, texture, renderTarget.width, renderTarget.height);
|
|
}
|
|
state.unbindTexture();
|
|
} else if (isMultipleRenderTargets) {
|
|
const textures = renderTarget.texture;
|
|
for (let i = 0, il = textures.length; i < il; i++) {
|
|
const attachment = textures[i];
|
|
const attachmentProperties = properties.get(attachment);
|
|
state.bindTexture(3553, attachmentProperties.__webglTexture);
|
|
setTextureParameters(3553, attachment, supportsMips);
|
|
setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553);
|
|
if (textureNeedsGenerateMipmaps(attachment, supportsMips)) {
|
|
generateMipmap(3553, attachment, renderTarget.width, renderTarget.height);
|
|
}
|
|
}
|
|
state.unbindTexture();
|
|
} else {
|
|
let glTextureType = 3553;
|
|
if (isRenderTarget3D) {
|
|
if (isWebGL2) {
|
|
const isTexture3D = texture.isDataTexture3D;
|
|
glTextureType = isTexture3D ? 32879 : 35866;
|
|
} else {
|
|
console.warn("THREE.DataTexture3D and THREE.DataTexture2DArray only supported with WebGL2.");
|
|
}
|
|
}
|
|
state.bindTexture(glTextureType, textureProperties.__webglTexture);
|
|
setTextureParameters(glTextureType, texture, supportsMips);
|
|
setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType);
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
generateMipmap(glTextureType, texture, renderTarget.width, renderTarget.height, renderTarget.depth);
|
|
}
|
|
state.unbindTexture();
|
|
}
|
|
if (renderTarget.depthBuffer) {
|
|
setupDepthRenderbuffer(renderTarget);
|
|
}
|
|
}
|
|
function updateRenderTargetMipmap(renderTarget) {
|
|
const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2;
|
|
const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture];
|
|
for (let i = 0, il = textures.length; i < il; i++) {
|
|
const texture = textures[i];
|
|
if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
|
|
const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
|
|
const webglTexture = properties.get(texture).__webglTexture;
|
|
state.bindTexture(target, webglTexture);
|
|
generateMipmap(target, texture, renderTarget.width, renderTarget.height);
|
|
state.unbindTexture();
|
|
}
|
|
}
|
|
}
|
|
function updateMultisampleRenderTarget(renderTarget) {
|
|
if (renderTarget.isWebGLMultisampleRenderTarget) {
|
|
if (isWebGL2) {
|
|
const width = renderTarget.width;
|
|
const height = renderTarget.height;
|
|
let mask = 16384;
|
|
if (renderTarget.depthBuffer)
|
|
mask |= 256;
|
|
if (renderTarget.stencilBuffer)
|
|
mask |= 1024;
|
|
const renderTargetProperties = properties.get(renderTarget);
|
|
state.bindFramebuffer(36008, renderTargetProperties.__webglMultisampledFramebuffer);
|
|
state.bindFramebuffer(36009, renderTargetProperties.__webglFramebuffer);
|
|
_gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, 9728);
|
|
state.bindFramebuffer(36008, null);
|
|
state.bindFramebuffer(36009, renderTargetProperties.__webglMultisampledFramebuffer);
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");
|
|
}
|
|
}
|
|
}
|
|
function getRenderTargetSamples(renderTarget) {
|
|
return isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ? Math.min(maxSamples, renderTarget.samples) : 0;
|
|
}
|
|
function updateVideoTexture(texture) {
|
|
const frame = info.render.frame;
|
|
if (_videoTextures.get(texture) !== frame) {
|
|
_videoTextures.set(texture, frame);
|
|
texture.update();
|
|
}
|
|
}
|
|
let warnedTexture2D = false;
|
|
let warnedTextureCube = false;
|
|
function safeSetTexture2D(texture, slot) {
|
|
if (texture && texture.isWebGLRenderTarget) {
|
|
if (warnedTexture2D === false) {
|
|
console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.");
|
|
warnedTexture2D = true;
|
|
}
|
|
texture = texture.texture;
|
|
}
|
|
setTexture2D(texture, slot);
|
|
}
|
|
function safeSetTextureCube(texture, slot) {
|
|
if (texture && texture.isWebGLCubeRenderTarget) {
|
|
if (warnedTextureCube === false) {
|
|
console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.");
|
|
warnedTextureCube = true;
|
|
}
|
|
texture = texture.texture;
|
|
}
|
|
setTextureCube(texture, slot);
|
|
}
|
|
this.allocateTextureUnit = allocateTextureUnit;
|
|
this.resetTextureUnits = resetTextureUnits;
|
|
this.setTexture2D = setTexture2D;
|
|
this.setTexture2DArray = setTexture2DArray;
|
|
this.setTexture3D = setTexture3D;
|
|
this.setTextureCube = setTextureCube;
|
|
this.setupRenderTarget = setupRenderTarget;
|
|
this.updateRenderTargetMipmap = updateRenderTargetMipmap;
|
|
this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
|
|
this.safeSetTexture2D = safeSetTexture2D;
|
|
this.safeSetTextureCube = safeSetTextureCube;
|
|
}
|
|
function WebGLUtils(gl, extensions, capabilities) {
|
|
const isWebGL2 = capabilities.isWebGL2;
|
|
function convert(p2) {
|
|
let extension;
|
|
if (p2 === UnsignedByteType)
|
|
return 5121;
|
|
if (p2 === UnsignedShort4444Type)
|
|
return 32819;
|
|
if (p2 === UnsignedShort5551Type)
|
|
return 32820;
|
|
if (p2 === UnsignedShort565Type)
|
|
return 33635;
|
|
if (p2 === ByteType)
|
|
return 5120;
|
|
if (p2 === ShortType)
|
|
return 5122;
|
|
if (p2 === UnsignedShortType)
|
|
return 5123;
|
|
if (p2 === IntType)
|
|
return 5124;
|
|
if (p2 === UnsignedIntType)
|
|
return 5125;
|
|
if (p2 === FloatType)
|
|
return 5126;
|
|
if (p2 === HalfFloatType) {
|
|
if (isWebGL2)
|
|
return 5131;
|
|
extension = extensions.get("OES_texture_half_float");
|
|
if (extension !== null) {
|
|
return extension.HALF_FLOAT_OES;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === AlphaFormat)
|
|
return 6406;
|
|
if (p2 === RGBFormat)
|
|
return 6407;
|
|
if (p2 === RGBAFormat)
|
|
return 6408;
|
|
if (p2 === LuminanceFormat)
|
|
return 6409;
|
|
if (p2 === LuminanceAlphaFormat)
|
|
return 6410;
|
|
if (p2 === DepthFormat)
|
|
return 6402;
|
|
if (p2 === DepthStencilFormat)
|
|
return 34041;
|
|
if (p2 === RedFormat)
|
|
return 6403;
|
|
if (p2 === RedIntegerFormat)
|
|
return 36244;
|
|
if (p2 === RGFormat)
|
|
return 33319;
|
|
if (p2 === RGIntegerFormat)
|
|
return 33320;
|
|
if (p2 === RGBIntegerFormat)
|
|
return 36248;
|
|
if (p2 === RGBAIntegerFormat)
|
|
return 36249;
|
|
if (p2 === RGB_S3TC_DXT1_Format || p2 === RGBA_S3TC_DXT1_Format || p2 === RGBA_S3TC_DXT3_Format || p2 === RGBA_S3TC_DXT5_Format) {
|
|
extension = extensions.get("WEBGL_compressed_texture_s3tc");
|
|
if (extension !== null) {
|
|
if (p2 === RGB_S3TC_DXT1_Format)
|
|
return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
if (p2 === RGBA_S3TC_DXT1_Format)
|
|
return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
|
if (p2 === RGBA_S3TC_DXT3_Format)
|
|
return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
if (p2 === RGBA_S3TC_DXT5_Format)
|
|
return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === RGB_PVRTC_4BPPV1_Format || p2 === RGB_PVRTC_2BPPV1_Format || p2 === RGBA_PVRTC_4BPPV1_Format || p2 === RGBA_PVRTC_2BPPV1_Format) {
|
|
extension = extensions.get("WEBGL_compressed_texture_pvrtc");
|
|
if (extension !== null) {
|
|
if (p2 === RGB_PVRTC_4BPPV1_Format)
|
|
return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
|
|
if (p2 === RGB_PVRTC_2BPPV1_Format)
|
|
return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
|
|
if (p2 === RGBA_PVRTC_4BPPV1_Format)
|
|
return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
|
if (p2 === RGBA_PVRTC_2BPPV1_Format)
|
|
return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === RGB_ETC1_Format) {
|
|
extension = extensions.get("WEBGL_compressed_texture_etc1");
|
|
if (extension !== null) {
|
|
return extension.COMPRESSED_RGB_ETC1_WEBGL;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === RGB_ETC2_Format || p2 === RGBA_ETC2_EAC_Format) {
|
|
extension = extensions.get("WEBGL_compressed_texture_etc");
|
|
if (extension !== null) {
|
|
if (p2 === RGB_ETC2_Format)
|
|
return extension.COMPRESSED_RGB8_ETC2;
|
|
if (p2 === RGBA_ETC2_EAC_Format)
|
|
return extension.COMPRESSED_RGBA8_ETC2_EAC;
|
|
}
|
|
}
|
|
if (p2 === RGBA_ASTC_4x4_Format || p2 === RGBA_ASTC_5x4_Format || p2 === RGBA_ASTC_5x5_Format || p2 === RGBA_ASTC_6x5_Format || p2 === RGBA_ASTC_6x6_Format || p2 === RGBA_ASTC_8x5_Format || p2 === RGBA_ASTC_8x6_Format || p2 === RGBA_ASTC_8x8_Format || p2 === RGBA_ASTC_10x5_Format || p2 === RGBA_ASTC_10x6_Format || p2 === RGBA_ASTC_10x8_Format || p2 === RGBA_ASTC_10x10_Format || p2 === RGBA_ASTC_12x10_Format || p2 === RGBA_ASTC_12x12_Format || p2 === SRGB8_ALPHA8_ASTC_4x4_Format || p2 === SRGB8_ALPHA8_ASTC_5x4_Format || p2 === SRGB8_ALPHA8_ASTC_5x5_Format || p2 === SRGB8_ALPHA8_ASTC_6x5_Format || p2 === SRGB8_ALPHA8_ASTC_6x6_Format || p2 === SRGB8_ALPHA8_ASTC_8x5_Format || p2 === SRGB8_ALPHA8_ASTC_8x6_Format || p2 === SRGB8_ALPHA8_ASTC_8x8_Format || p2 === SRGB8_ALPHA8_ASTC_10x5_Format || p2 === SRGB8_ALPHA8_ASTC_10x6_Format || p2 === SRGB8_ALPHA8_ASTC_10x8_Format || p2 === SRGB8_ALPHA8_ASTC_10x10_Format || p2 === SRGB8_ALPHA8_ASTC_12x10_Format || p2 === SRGB8_ALPHA8_ASTC_12x12_Format) {
|
|
extension = extensions.get("WEBGL_compressed_texture_astc");
|
|
if (extension !== null) {
|
|
return p2;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === RGBA_BPTC_Format) {
|
|
extension = extensions.get("EXT_texture_compression_bptc");
|
|
if (extension !== null) {
|
|
return p2;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
if (p2 === UnsignedInt248Type) {
|
|
if (isWebGL2)
|
|
return 34042;
|
|
extension = extensions.get("WEBGL_depth_texture");
|
|
if (extension !== null) {
|
|
return extension.UNSIGNED_INT_24_8_WEBGL;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
return { convert };
|
|
}
|
|
var ArrayCamera = class extends PerspectiveCamera {
|
|
constructor(array = []) {
|
|
super();
|
|
this.cameras = array;
|
|
}
|
|
};
|
|
ArrayCamera.prototype.isArrayCamera = true;
|
|
var Group = class extends Object3D {
|
|
constructor() {
|
|
super();
|
|
this.type = "Group";
|
|
}
|
|
};
|
|
Group.prototype.isGroup = true;
|
|
var _moveEvent = { type: "move" };
|
|
var WebXRController = class {
|
|
constructor() {
|
|
this._targetRay = null;
|
|
this._grip = null;
|
|
this._hand = null;
|
|
}
|
|
getHandSpace() {
|
|
if (this._hand === null) {
|
|
this._hand = new Group();
|
|
this._hand.matrixAutoUpdate = false;
|
|
this._hand.visible = false;
|
|
this._hand.joints = {};
|
|
this._hand.inputState = { pinching: false };
|
|
}
|
|
return this._hand;
|
|
}
|
|
getTargetRaySpace() {
|
|
if (this._targetRay === null) {
|
|
this._targetRay = new Group();
|
|
this._targetRay.matrixAutoUpdate = false;
|
|
this._targetRay.visible = false;
|
|
this._targetRay.hasLinearVelocity = false;
|
|
this._targetRay.linearVelocity = new Vector3();
|
|
this._targetRay.hasAngularVelocity = false;
|
|
this._targetRay.angularVelocity = new Vector3();
|
|
}
|
|
return this._targetRay;
|
|
}
|
|
getGripSpace() {
|
|
if (this._grip === null) {
|
|
this._grip = new Group();
|
|
this._grip.matrixAutoUpdate = false;
|
|
this._grip.visible = false;
|
|
this._grip.hasLinearVelocity = false;
|
|
this._grip.linearVelocity = new Vector3();
|
|
this._grip.hasAngularVelocity = false;
|
|
this._grip.angularVelocity = new Vector3();
|
|
}
|
|
return this._grip;
|
|
}
|
|
dispatchEvent(event) {
|
|
if (this._targetRay !== null) {
|
|
this._targetRay.dispatchEvent(event);
|
|
}
|
|
if (this._grip !== null) {
|
|
this._grip.dispatchEvent(event);
|
|
}
|
|
if (this._hand !== null) {
|
|
this._hand.dispatchEvent(event);
|
|
}
|
|
return this;
|
|
}
|
|
disconnect(inputSource) {
|
|
this.dispatchEvent({ type: "disconnected", data: inputSource });
|
|
if (this._targetRay !== null) {
|
|
this._targetRay.visible = false;
|
|
}
|
|
if (this._grip !== null) {
|
|
this._grip.visible = false;
|
|
}
|
|
if (this._hand !== null) {
|
|
this._hand.visible = false;
|
|
}
|
|
return this;
|
|
}
|
|
update(inputSource, frame, referenceSpace) {
|
|
let inputPose = null;
|
|
let gripPose = null;
|
|
let handPose = null;
|
|
const targetRay = this._targetRay;
|
|
const grip = this._grip;
|
|
const hand = this._hand;
|
|
if (inputSource && frame.session.visibilityState !== "visible-blurred") {
|
|
if (targetRay !== null) {
|
|
inputPose = frame.getPose(inputSource.targetRaySpace, referenceSpace);
|
|
if (inputPose !== null) {
|
|
targetRay.matrix.fromArray(inputPose.transform.matrix);
|
|
targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale);
|
|
if (inputPose.linearVelocity) {
|
|
targetRay.hasLinearVelocity = true;
|
|
targetRay.linearVelocity.copy(inputPose.linearVelocity);
|
|
} else {
|
|
targetRay.hasLinearVelocity = false;
|
|
}
|
|
if (inputPose.angularVelocity) {
|
|
targetRay.hasAngularVelocity = true;
|
|
targetRay.angularVelocity.copy(inputPose.angularVelocity);
|
|
} else {
|
|
targetRay.hasAngularVelocity = false;
|
|
}
|
|
this.dispatchEvent(_moveEvent);
|
|
}
|
|
}
|
|
if (hand && inputSource.hand) {
|
|
handPose = true;
|
|
for (const inputjoint of inputSource.hand.values()) {
|
|
const jointPose = frame.getJointPose(inputjoint, referenceSpace);
|
|
if (hand.joints[inputjoint.jointName] === void 0) {
|
|
const joint2 = new Group();
|
|
joint2.matrixAutoUpdate = false;
|
|
joint2.visible = false;
|
|
hand.joints[inputjoint.jointName] = joint2;
|
|
hand.add(joint2);
|
|
}
|
|
const joint = hand.joints[inputjoint.jointName];
|
|
if (jointPose !== null) {
|
|
joint.matrix.fromArray(jointPose.transform.matrix);
|
|
joint.matrix.decompose(joint.position, joint.rotation, joint.scale);
|
|
joint.jointRadius = jointPose.radius;
|
|
}
|
|
joint.visible = jointPose !== null;
|
|
}
|
|
const indexTip = hand.joints["index-finger-tip"];
|
|
const thumbTip = hand.joints["thumb-tip"];
|
|
const distance = indexTip.position.distanceTo(thumbTip.position);
|
|
const distanceToPinch = 0.02;
|
|
const threshold = 5e-3;
|
|
if (hand.inputState.pinching && distance > distanceToPinch + threshold) {
|
|
hand.inputState.pinching = false;
|
|
this.dispatchEvent({
|
|
type: "pinchend",
|
|
handedness: inputSource.handedness,
|
|
target: this
|
|
});
|
|
} else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) {
|
|
hand.inputState.pinching = true;
|
|
this.dispatchEvent({
|
|
type: "pinchstart",
|
|
handedness: inputSource.handedness,
|
|
target: this
|
|
});
|
|
}
|
|
} else {
|
|
if (grip !== null && inputSource.gripSpace) {
|
|
gripPose = frame.getPose(inputSource.gripSpace, referenceSpace);
|
|
if (gripPose !== null) {
|
|
grip.matrix.fromArray(gripPose.transform.matrix);
|
|
grip.matrix.decompose(grip.position, grip.rotation, grip.scale);
|
|
if (gripPose.linearVelocity) {
|
|
grip.hasLinearVelocity = true;
|
|
grip.linearVelocity.copy(gripPose.linearVelocity);
|
|
} else {
|
|
grip.hasLinearVelocity = false;
|
|
}
|
|
if (gripPose.angularVelocity) {
|
|
grip.hasAngularVelocity = true;
|
|
grip.angularVelocity.copy(gripPose.angularVelocity);
|
|
} else {
|
|
grip.hasAngularVelocity = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (targetRay !== null) {
|
|
targetRay.visible = inputPose !== null;
|
|
}
|
|
if (grip !== null) {
|
|
grip.visible = gripPose !== null;
|
|
}
|
|
if (hand !== null) {
|
|
hand.visible = handPose !== null;
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var WebXRManager = class extends EventDispatcher {
|
|
constructor(renderer, gl) {
|
|
super();
|
|
const scope = this;
|
|
const state = renderer.state;
|
|
let session = null;
|
|
let framebufferScaleFactor = 1;
|
|
let referenceSpace = null;
|
|
let referenceSpaceType = "local-floor";
|
|
let pose = null;
|
|
let glBinding = null;
|
|
let glFramebuffer = null;
|
|
let glProjLayer = null;
|
|
let glBaseLayer = null;
|
|
let isMultisample = false;
|
|
let glMultisampledFramebuffer = null;
|
|
let glColorRenderbuffer = null;
|
|
let glDepthRenderbuffer = null;
|
|
let xrFrame = null;
|
|
let depthStyle = null;
|
|
let clearStyle = null;
|
|
const controllers = [];
|
|
const inputSourcesMap = /* @__PURE__ */ new Map();
|
|
const cameraL = new PerspectiveCamera();
|
|
cameraL.layers.enable(1);
|
|
cameraL.viewport = new Vector4();
|
|
const cameraR = new PerspectiveCamera();
|
|
cameraR.layers.enable(2);
|
|
cameraR.viewport = new Vector4();
|
|
const cameras = [cameraL, cameraR];
|
|
const cameraVR = new ArrayCamera();
|
|
cameraVR.layers.enable(1);
|
|
cameraVR.layers.enable(2);
|
|
let _currentDepthNear = null;
|
|
let _currentDepthFar = null;
|
|
this.cameraAutoUpdate = true;
|
|
this.enabled = false;
|
|
this.isPresenting = false;
|
|
this.getController = function(index) {
|
|
let controller = controllers[index];
|
|
if (controller === void 0) {
|
|
controller = new WebXRController();
|
|
controllers[index] = controller;
|
|
}
|
|
return controller.getTargetRaySpace();
|
|
};
|
|
this.getControllerGrip = function(index) {
|
|
let controller = controllers[index];
|
|
if (controller === void 0) {
|
|
controller = new WebXRController();
|
|
controllers[index] = controller;
|
|
}
|
|
return controller.getGripSpace();
|
|
};
|
|
this.getHand = function(index) {
|
|
let controller = controllers[index];
|
|
if (controller === void 0) {
|
|
controller = new WebXRController();
|
|
controllers[index] = controller;
|
|
}
|
|
return controller.getHandSpace();
|
|
};
|
|
function onSessionEvent(event) {
|
|
const controller = inputSourcesMap.get(event.inputSource);
|
|
if (controller) {
|
|
controller.dispatchEvent({ type: event.type, data: event.inputSource });
|
|
}
|
|
}
|
|
function onSessionEnd() {
|
|
inputSourcesMap.forEach(function(controller, inputSource) {
|
|
controller.disconnect(inputSource);
|
|
});
|
|
inputSourcesMap.clear();
|
|
_currentDepthNear = null;
|
|
_currentDepthFar = null;
|
|
state.bindXRFramebuffer(null);
|
|
renderer.setRenderTarget(renderer.getRenderTarget());
|
|
if (glFramebuffer)
|
|
gl.deleteFramebuffer(glFramebuffer);
|
|
if (glMultisampledFramebuffer)
|
|
gl.deleteFramebuffer(glMultisampledFramebuffer);
|
|
if (glColorRenderbuffer)
|
|
gl.deleteRenderbuffer(glColorRenderbuffer);
|
|
if (glDepthRenderbuffer)
|
|
gl.deleteRenderbuffer(glDepthRenderbuffer);
|
|
glFramebuffer = null;
|
|
glMultisampledFramebuffer = null;
|
|
glColorRenderbuffer = null;
|
|
glDepthRenderbuffer = null;
|
|
glBaseLayer = null;
|
|
glProjLayer = null;
|
|
glBinding = null;
|
|
session = null;
|
|
animation.stop();
|
|
scope.isPresenting = false;
|
|
scope.dispatchEvent({ type: "sessionend" });
|
|
}
|
|
this.setFramebufferScaleFactor = function(value) {
|
|
framebufferScaleFactor = value;
|
|
if (scope.isPresenting === true) {
|
|
console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.");
|
|
}
|
|
};
|
|
this.setReferenceSpaceType = function(value) {
|
|
referenceSpaceType = value;
|
|
if (scope.isPresenting === true) {
|
|
console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.");
|
|
}
|
|
};
|
|
this.getReferenceSpace = function() {
|
|
return referenceSpace;
|
|
};
|
|
this.getBaseLayer = function() {
|
|
return glProjLayer !== null ? glProjLayer : glBaseLayer;
|
|
};
|
|
this.getBinding = function() {
|
|
return glBinding;
|
|
};
|
|
this.getFrame = function() {
|
|
return xrFrame;
|
|
};
|
|
this.getSession = function() {
|
|
return session;
|
|
};
|
|
this.setSession = async function(value) {
|
|
session = value;
|
|
if (session !== null) {
|
|
session.addEventListener("select", onSessionEvent);
|
|
session.addEventListener("selectstart", onSessionEvent);
|
|
session.addEventListener("selectend", onSessionEvent);
|
|
session.addEventListener("squeeze", onSessionEvent);
|
|
session.addEventListener("squeezestart", onSessionEvent);
|
|
session.addEventListener("squeezeend", onSessionEvent);
|
|
session.addEventListener("end", onSessionEnd);
|
|
session.addEventListener("inputsourceschange", onInputSourcesChange);
|
|
const attributes = gl.getContextAttributes();
|
|
if (attributes.xrCompatible !== true) {
|
|
await gl.makeXRCompatible();
|
|
}
|
|
if (session.renderState.layers === void 0) {
|
|
const layerInit = {
|
|
antialias: attributes.antialias,
|
|
alpha: attributes.alpha,
|
|
depth: attributes.depth,
|
|
stencil: attributes.stencil,
|
|
framebufferScaleFactor
|
|
};
|
|
glBaseLayer = new XRWebGLLayer(session, gl, layerInit);
|
|
session.updateRenderState({ baseLayer: glBaseLayer });
|
|
} else if (gl instanceof WebGLRenderingContext) {
|
|
const layerInit = {
|
|
antialias: true,
|
|
alpha: attributes.alpha,
|
|
depth: attributes.depth,
|
|
stencil: attributes.stencil,
|
|
framebufferScaleFactor
|
|
};
|
|
glBaseLayer = new XRWebGLLayer(session, gl, layerInit);
|
|
session.updateRenderState({ layers: [glBaseLayer] });
|
|
} else {
|
|
isMultisample = attributes.antialias;
|
|
let depthFormat = null;
|
|
if (attributes.depth) {
|
|
clearStyle = 256;
|
|
if (attributes.stencil)
|
|
clearStyle |= 1024;
|
|
depthStyle = attributes.stencil ? 33306 : 36096;
|
|
depthFormat = attributes.stencil ? 35056 : 33190;
|
|
}
|
|
const projectionlayerInit = {
|
|
colorFormat: attributes.alpha ? 32856 : 32849,
|
|
depthFormat,
|
|
scaleFactor: framebufferScaleFactor
|
|
};
|
|
glBinding = new XRWebGLBinding(session, gl);
|
|
glProjLayer = glBinding.createProjectionLayer(projectionlayerInit);
|
|
glFramebuffer = gl.createFramebuffer();
|
|
session.updateRenderState({ layers: [glProjLayer] });
|
|
if (isMultisample) {
|
|
glMultisampledFramebuffer = gl.createFramebuffer();
|
|
glColorRenderbuffer = gl.createRenderbuffer();
|
|
gl.bindRenderbuffer(36161, glColorRenderbuffer);
|
|
gl.renderbufferStorageMultisample(36161, 4, 32856, glProjLayer.textureWidth, glProjLayer.textureHeight);
|
|
state.bindFramebuffer(36160, glMultisampledFramebuffer);
|
|
gl.framebufferRenderbuffer(36160, 36064, 36161, glColorRenderbuffer);
|
|
gl.bindRenderbuffer(36161, null);
|
|
if (depthFormat !== null) {
|
|
glDepthRenderbuffer = gl.createRenderbuffer();
|
|
gl.bindRenderbuffer(36161, glDepthRenderbuffer);
|
|
gl.renderbufferStorageMultisample(36161, 4, depthFormat, glProjLayer.textureWidth, glProjLayer.textureHeight);
|
|
gl.framebufferRenderbuffer(36160, depthStyle, 36161, glDepthRenderbuffer);
|
|
gl.bindRenderbuffer(36161, null);
|
|
}
|
|
state.bindFramebuffer(36160, null);
|
|
}
|
|
}
|
|
referenceSpace = await session.requestReferenceSpace(referenceSpaceType);
|
|
animation.setContext(session);
|
|
animation.start();
|
|
scope.isPresenting = true;
|
|
scope.dispatchEvent({ type: "sessionstart" });
|
|
}
|
|
};
|
|
function onInputSourcesChange(event) {
|
|
const inputSources = session.inputSources;
|
|
for (let i = 0; i < controllers.length; i++) {
|
|
inputSourcesMap.set(inputSources[i], controllers[i]);
|
|
}
|
|
for (let i = 0; i < event.removed.length; i++) {
|
|
const inputSource = event.removed[i];
|
|
const controller = inputSourcesMap.get(inputSource);
|
|
if (controller) {
|
|
controller.dispatchEvent({ type: "disconnected", data: inputSource });
|
|
inputSourcesMap.delete(inputSource);
|
|
}
|
|
}
|
|
for (let i = 0; i < event.added.length; i++) {
|
|
const inputSource = event.added[i];
|
|
const controller = inputSourcesMap.get(inputSource);
|
|
if (controller) {
|
|
controller.dispatchEvent({ type: "connected", data: inputSource });
|
|
}
|
|
}
|
|
}
|
|
const cameraLPos = new Vector3();
|
|
const cameraRPos = new Vector3();
|
|
function setProjectionFromUnion(camera, cameraL2, cameraR2) {
|
|
cameraLPos.setFromMatrixPosition(cameraL2.matrixWorld);
|
|
cameraRPos.setFromMatrixPosition(cameraR2.matrixWorld);
|
|
const ipd = cameraLPos.distanceTo(cameraRPos);
|
|
const projL = cameraL2.projectionMatrix.elements;
|
|
const projR = cameraR2.projectionMatrix.elements;
|
|
const near = projL[14] / (projL[10] - 1);
|
|
const far = projL[14] / (projL[10] + 1);
|
|
const topFov = (projL[9] + 1) / projL[5];
|
|
const bottomFov = (projL[9] - 1) / projL[5];
|
|
const leftFov = (projL[8] - 1) / projL[0];
|
|
const rightFov = (projR[8] + 1) / projR[0];
|
|
const left = near * leftFov;
|
|
const right = near * rightFov;
|
|
const zOffset = ipd / (-leftFov + rightFov);
|
|
const xOffset = zOffset * -leftFov;
|
|
cameraL2.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale);
|
|
camera.translateX(xOffset);
|
|
camera.translateZ(zOffset);
|
|
camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale);
|
|
camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
|
|
const near2 = near + zOffset;
|
|
const far2 = far + zOffset;
|
|
const left2 = left - xOffset;
|
|
const right2 = right + (ipd - xOffset);
|
|
const top2 = topFov * far / far2 * near2;
|
|
const bottom2 = bottomFov * far / far2 * near2;
|
|
camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2);
|
|
}
|
|
function updateCamera(camera, parent) {
|
|
if (parent === null) {
|
|
camera.matrixWorld.copy(camera.matrix);
|
|
} else {
|
|
camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix);
|
|
}
|
|
camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
|
|
}
|
|
this.updateCamera = function(camera) {
|
|
if (session === null)
|
|
return;
|
|
cameraVR.near = cameraR.near = cameraL.near = camera.near;
|
|
cameraVR.far = cameraR.far = cameraL.far = camera.far;
|
|
if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) {
|
|
session.updateRenderState({
|
|
depthNear: cameraVR.near,
|
|
depthFar: cameraVR.far
|
|
});
|
|
_currentDepthNear = cameraVR.near;
|
|
_currentDepthFar = cameraVR.far;
|
|
}
|
|
const parent = camera.parent;
|
|
const cameras2 = cameraVR.cameras;
|
|
updateCamera(cameraVR, parent);
|
|
for (let i = 0; i < cameras2.length; i++) {
|
|
updateCamera(cameras2[i], parent);
|
|
}
|
|
cameraVR.matrixWorld.decompose(cameraVR.position, cameraVR.quaternion, cameraVR.scale);
|
|
camera.position.copy(cameraVR.position);
|
|
camera.quaternion.copy(cameraVR.quaternion);
|
|
camera.scale.copy(cameraVR.scale);
|
|
camera.matrix.copy(cameraVR.matrix);
|
|
camera.matrixWorld.copy(cameraVR.matrixWorld);
|
|
const children = camera.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
children[i].updateMatrixWorld(true);
|
|
}
|
|
if (cameras2.length === 2) {
|
|
setProjectionFromUnion(cameraVR, cameraL, cameraR);
|
|
} else {
|
|
cameraVR.projectionMatrix.copy(cameraL.projectionMatrix);
|
|
}
|
|
};
|
|
this.getCamera = function() {
|
|
return cameraVR;
|
|
};
|
|
this.getFoveation = function() {
|
|
if (glProjLayer !== null) {
|
|
return glProjLayer.fixedFoveation;
|
|
}
|
|
if (glBaseLayer !== null) {
|
|
return glBaseLayer.fixedFoveation;
|
|
}
|
|
return void 0;
|
|
};
|
|
this.setFoveation = function(foveation) {
|
|
if (glProjLayer !== null) {
|
|
glProjLayer.fixedFoveation = foveation;
|
|
}
|
|
if (glBaseLayer !== null && glBaseLayer.fixedFoveation !== void 0) {
|
|
glBaseLayer.fixedFoveation = foveation;
|
|
}
|
|
};
|
|
let onAnimationFrameCallback = null;
|
|
function onAnimationFrame(time, frame) {
|
|
pose = frame.getViewerPose(referenceSpace);
|
|
xrFrame = frame;
|
|
if (pose !== null) {
|
|
const views = pose.views;
|
|
if (glBaseLayer !== null) {
|
|
state.bindXRFramebuffer(glBaseLayer.framebuffer);
|
|
}
|
|
let cameraVRNeedsUpdate = false;
|
|
if (views.length !== cameraVR.cameras.length) {
|
|
cameraVR.cameras.length = 0;
|
|
cameraVRNeedsUpdate = true;
|
|
}
|
|
for (let i = 0; i < views.length; i++) {
|
|
const view = views[i];
|
|
let viewport = null;
|
|
if (glBaseLayer !== null) {
|
|
viewport = glBaseLayer.getViewport(view);
|
|
} else {
|
|
const glSubImage = glBinding.getViewSubImage(glProjLayer, view);
|
|
state.bindXRFramebuffer(glFramebuffer);
|
|
if (glSubImage.depthStencilTexture !== void 0) {
|
|
gl.framebufferTexture2D(36160, depthStyle, 3553, glSubImage.depthStencilTexture, 0);
|
|
}
|
|
gl.framebufferTexture2D(36160, 36064, 3553, glSubImage.colorTexture, 0);
|
|
viewport = glSubImage.viewport;
|
|
}
|
|
const camera = cameras[i];
|
|
camera.matrix.fromArray(view.transform.matrix);
|
|
camera.projectionMatrix.fromArray(view.projectionMatrix);
|
|
camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height);
|
|
if (i === 0) {
|
|
cameraVR.matrix.copy(camera.matrix);
|
|
}
|
|
if (cameraVRNeedsUpdate === true) {
|
|
cameraVR.cameras.push(camera);
|
|
}
|
|
}
|
|
if (isMultisample) {
|
|
state.bindXRFramebuffer(glMultisampledFramebuffer);
|
|
if (clearStyle !== null)
|
|
gl.clear(clearStyle);
|
|
}
|
|
}
|
|
const inputSources = session.inputSources;
|
|
for (let i = 0; i < controllers.length; i++) {
|
|
const controller = controllers[i];
|
|
const inputSource = inputSources[i];
|
|
controller.update(inputSource, frame, referenceSpace);
|
|
}
|
|
if (onAnimationFrameCallback)
|
|
onAnimationFrameCallback(time, frame);
|
|
if (isMultisample) {
|
|
const width = glProjLayer.textureWidth;
|
|
const height = glProjLayer.textureHeight;
|
|
state.bindFramebuffer(36008, glMultisampledFramebuffer);
|
|
state.bindFramebuffer(36009, glFramebuffer);
|
|
gl.invalidateFramebuffer(36008, [depthStyle]);
|
|
gl.invalidateFramebuffer(36009, [depthStyle]);
|
|
gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, 16384, 9728);
|
|
gl.invalidateFramebuffer(36008, [36064]);
|
|
state.bindFramebuffer(36008, null);
|
|
state.bindFramebuffer(36009, null);
|
|
state.bindFramebuffer(36160, glMultisampledFramebuffer);
|
|
}
|
|
xrFrame = null;
|
|
}
|
|
const animation = new WebGLAnimation();
|
|
animation.setAnimationLoop(onAnimationFrame);
|
|
this.setAnimationLoop = function(callback) {
|
|
onAnimationFrameCallback = callback;
|
|
};
|
|
this.dispose = function() {
|
|
};
|
|
}
|
|
};
|
|
function WebGLMaterials(properties) {
|
|
function refreshFogUniforms(uniforms, fog) {
|
|
uniforms.fogColor.value.copy(fog.color);
|
|
if (fog.isFog) {
|
|
uniforms.fogNear.value = fog.near;
|
|
uniforms.fogFar.value = fog.far;
|
|
} else if (fog.isFogExp2) {
|
|
uniforms.fogDensity.value = fog.density;
|
|
}
|
|
}
|
|
function refreshMaterialUniforms(uniforms, material, pixelRatio, height, transmissionRenderTarget) {
|
|
if (material.isMeshBasicMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
} else if (material.isMeshLambertMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsLambert(uniforms, material);
|
|
} else if (material.isMeshToonMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsToon(uniforms, material);
|
|
} else if (material.isMeshPhongMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsPhong(uniforms, material);
|
|
} else if (material.isMeshStandardMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
if (material.isMeshPhysicalMaterial) {
|
|
refreshUniformsPhysical(uniforms, material, transmissionRenderTarget);
|
|
} else {
|
|
refreshUniformsStandard(uniforms, material);
|
|
}
|
|
} else if (material.isMeshMatcapMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsMatcap(uniforms, material);
|
|
} else if (material.isMeshDepthMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsDepth(uniforms, material);
|
|
} else if (material.isMeshDistanceMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsDistance(uniforms, material);
|
|
} else if (material.isMeshNormalMaterial) {
|
|
refreshUniformsCommon(uniforms, material);
|
|
refreshUniformsNormal(uniforms, material);
|
|
} else if (material.isLineBasicMaterial) {
|
|
refreshUniformsLine(uniforms, material);
|
|
if (material.isLineDashedMaterial) {
|
|
refreshUniformsDash(uniforms, material);
|
|
}
|
|
} else if (material.isPointsMaterial) {
|
|
refreshUniformsPoints(uniforms, material, pixelRatio, height);
|
|
} else if (material.isSpriteMaterial) {
|
|
refreshUniformsSprites(uniforms, material);
|
|
} else if (material.isShadowMaterial) {
|
|
uniforms.color.value.copy(material.color);
|
|
uniforms.opacity.value = material.opacity;
|
|
} else if (material.isShaderMaterial) {
|
|
material.uniformsNeedUpdate = false;
|
|
}
|
|
}
|
|
function refreshUniformsCommon(uniforms, material) {
|
|
uniforms.opacity.value = material.opacity;
|
|
if (material.color) {
|
|
uniforms.diffuse.value.copy(material.color);
|
|
}
|
|
if (material.emissive) {
|
|
uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity);
|
|
}
|
|
if (material.map) {
|
|
uniforms.map.value = material.map;
|
|
}
|
|
if (material.alphaMap) {
|
|
uniforms.alphaMap.value = material.alphaMap;
|
|
}
|
|
if (material.specularMap) {
|
|
uniforms.specularMap.value = material.specularMap;
|
|
}
|
|
if (material.alphaTest > 0) {
|
|
uniforms.alphaTest.value = material.alphaTest;
|
|
}
|
|
const envMap = properties.get(material).envMap;
|
|
if (envMap) {
|
|
uniforms.envMap.value = envMap;
|
|
uniforms.flipEnvMap.value = envMap.isCubeTexture && envMap.isRenderTargetTexture === false ? -1 : 1;
|
|
uniforms.reflectivity.value = material.reflectivity;
|
|
uniforms.ior.value = material.ior;
|
|
uniforms.refractionRatio.value = material.refractionRatio;
|
|
const maxMipLevel = properties.get(envMap).__maxMipLevel;
|
|
if (maxMipLevel !== void 0) {
|
|
uniforms.maxMipLevel.value = maxMipLevel;
|
|
}
|
|
}
|
|
if (material.lightMap) {
|
|
uniforms.lightMap.value = material.lightMap;
|
|
uniforms.lightMapIntensity.value = material.lightMapIntensity;
|
|
}
|
|
if (material.aoMap) {
|
|
uniforms.aoMap.value = material.aoMap;
|
|
uniforms.aoMapIntensity.value = material.aoMapIntensity;
|
|
}
|
|
let uvScaleMap;
|
|
if (material.map) {
|
|
uvScaleMap = material.map;
|
|
} else if (material.specularMap) {
|
|
uvScaleMap = material.specularMap;
|
|
} else if (material.displacementMap) {
|
|
uvScaleMap = material.displacementMap;
|
|
} else if (material.normalMap) {
|
|
uvScaleMap = material.normalMap;
|
|
} else if (material.bumpMap) {
|
|
uvScaleMap = material.bumpMap;
|
|
} else if (material.roughnessMap) {
|
|
uvScaleMap = material.roughnessMap;
|
|
} else if (material.metalnessMap) {
|
|
uvScaleMap = material.metalnessMap;
|
|
} else if (material.alphaMap) {
|
|
uvScaleMap = material.alphaMap;
|
|
} else if (material.emissiveMap) {
|
|
uvScaleMap = material.emissiveMap;
|
|
} else if (material.clearcoatMap) {
|
|
uvScaleMap = material.clearcoatMap;
|
|
} else if (material.clearcoatNormalMap) {
|
|
uvScaleMap = material.clearcoatNormalMap;
|
|
} else if (material.clearcoatRoughnessMap) {
|
|
uvScaleMap = material.clearcoatRoughnessMap;
|
|
} else if (material.specularIntensityMap) {
|
|
uvScaleMap = material.specularIntensityMap;
|
|
} else if (material.specularTintMap) {
|
|
uvScaleMap = material.specularTintMap;
|
|
} else if (material.transmissionMap) {
|
|
uvScaleMap = material.transmissionMap;
|
|
} else if (material.thicknessMap) {
|
|
uvScaleMap = material.thicknessMap;
|
|
}
|
|
if (uvScaleMap !== void 0) {
|
|
if (uvScaleMap.isWebGLRenderTarget) {
|
|
uvScaleMap = uvScaleMap.texture;
|
|
}
|
|
if (uvScaleMap.matrixAutoUpdate === true) {
|
|
uvScaleMap.updateMatrix();
|
|
}
|
|
uniforms.uvTransform.value.copy(uvScaleMap.matrix);
|
|
}
|
|
let uv2ScaleMap;
|
|
if (material.aoMap) {
|
|
uv2ScaleMap = material.aoMap;
|
|
} else if (material.lightMap) {
|
|
uv2ScaleMap = material.lightMap;
|
|
}
|
|
if (uv2ScaleMap !== void 0) {
|
|
if (uv2ScaleMap.isWebGLRenderTarget) {
|
|
uv2ScaleMap = uv2ScaleMap.texture;
|
|
}
|
|
if (uv2ScaleMap.matrixAutoUpdate === true) {
|
|
uv2ScaleMap.updateMatrix();
|
|
}
|
|
uniforms.uv2Transform.value.copy(uv2ScaleMap.matrix);
|
|
}
|
|
}
|
|
function refreshUniformsLine(uniforms, material) {
|
|
uniforms.diffuse.value.copy(material.color);
|
|
uniforms.opacity.value = material.opacity;
|
|
}
|
|
function refreshUniformsDash(uniforms, material) {
|
|
uniforms.dashSize.value = material.dashSize;
|
|
uniforms.totalSize.value = material.dashSize + material.gapSize;
|
|
uniforms.scale.value = material.scale;
|
|
}
|
|
function refreshUniformsPoints(uniforms, material, pixelRatio, height) {
|
|
uniforms.diffuse.value.copy(material.color);
|
|
uniforms.opacity.value = material.opacity;
|
|
uniforms.size.value = material.size * pixelRatio;
|
|
uniforms.scale.value = height * 0.5;
|
|
if (material.map) {
|
|
uniforms.map.value = material.map;
|
|
}
|
|
if (material.alphaMap) {
|
|
uniforms.alphaMap.value = material.alphaMap;
|
|
}
|
|
if (material.alphaTest > 0) {
|
|
uniforms.alphaTest.value = material.alphaTest;
|
|
}
|
|
let uvScaleMap;
|
|
if (material.map) {
|
|
uvScaleMap = material.map;
|
|
} else if (material.alphaMap) {
|
|
uvScaleMap = material.alphaMap;
|
|
}
|
|
if (uvScaleMap !== void 0) {
|
|
if (uvScaleMap.matrixAutoUpdate === true) {
|
|
uvScaleMap.updateMatrix();
|
|
}
|
|
uniforms.uvTransform.value.copy(uvScaleMap.matrix);
|
|
}
|
|
}
|
|
function refreshUniformsSprites(uniforms, material) {
|
|
uniforms.diffuse.value.copy(material.color);
|
|
uniforms.opacity.value = material.opacity;
|
|
uniforms.rotation.value = material.rotation;
|
|
if (material.map) {
|
|
uniforms.map.value = material.map;
|
|
}
|
|
if (material.alphaMap) {
|
|
uniforms.alphaMap.value = material.alphaMap;
|
|
}
|
|
if (material.alphaTest > 0) {
|
|
uniforms.alphaTest.value = material.alphaTest;
|
|
}
|
|
let uvScaleMap;
|
|
if (material.map) {
|
|
uvScaleMap = material.map;
|
|
} else if (material.alphaMap) {
|
|
uvScaleMap = material.alphaMap;
|
|
}
|
|
if (uvScaleMap !== void 0) {
|
|
if (uvScaleMap.matrixAutoUpdate === true) {
|
|
uvScaleMap.updateMatrix();
|
|
}
|
|
uniforms.uvTransform.value.copy(uvScaleMap.matrix);
|
|
}
|
|
}
|
|
function refreshUniformsLambert(uniforms, material) {
|
|
if (material.emissiveMap) {
|
|
uniforms.emissiveMap.value = material.emissiveMap;
|
|
}
|
|
}
|
|
function refreshUniformsPhong(uniforms, material) {
|
|
uniforms.specular.value.copy(material.specular);
|
|
uniforms.shininess.value = Math.max(material.shininess, 1e-4);
|
|
if (material.emissiveMap) {
|
|
uniforms.emissiveMap.value = material.emissiveMap;
|
|
}
|
|
if (material.bumpMap) {
|
|
uniforms.bumpMap.value = material.bumpMap;
|
|
uniforms.bumpScale.value = material.bumpScale;
|
|
if (material.side === BackSide)
|
|
uniforms.bumpScale.value *= -1;
|
|
}
|
|
if (material.normalMap) {
|
|
uniforms.normalMap.value = material.normalMap;
|
|
uniforms.normalScale.value.copy(material.normalScale);
|
|
if (material.side === BackSide)
|
|
uniforms.normalScale.value.negate();
|
|
}
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
}
|
|
function refreshUniformsToon(uniforms, material) {
|
|
if (material.gradientMap) {
|
|
uniforms.gradientMap.value = material.gradientMap;
|
|
}
|
|
if (material.emissiveMap) {
|
|
uniforms.emissiveMap.value = material.emissiveMap;
|
|
}
|
|
if (material.bumpMap) {
|
|
uniforms.bumpMap.value = material.bumpMap;
|
|
uniforms.bumpScale.value = material.bumpScale;
|
|
if (material.side === BackSide)
|
|
uniforms.bumpScale.value *= -1;
|
|
}
|
|
if (material.normalMap) {
|
|
uniforms.normalMap.value = material.normalMap;
|
|
uniforms.normalScale.value.copy(material.normalScale);
|
|
if (material.side === BackSide)
|
|
uniforms.normalScale.value.negate();
|
|
}
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
}
|
|
function refreshUniformsStandard(uniforms, material) {
|
|
uniforms.roughness.value = material.roughness;
|
|
uniforms.metalness.value = material.metalness;
|
|
if (material.roughnessMap) {
|
|
uniforms.roughnessMap.value = material.roughnessMap;
|
|
}
|
|
if (material.metalnessMap) {
|
|
uniforms.metalnessMap.value = material.metalnessMap;
|
|
}
|
|
if (material.emissiveMap) {
|
|
uniforms.emissiveMap.value = material.emissiveMap;
|
|
}
|
|
if (material.bumpMap) {
|
|
uniforms.bumpMap.value = material.bumpMap;
|
|
uniforms.bumpScale.value = material.bumpScale;
|
|
if (material.side === BackSide)
|
|
uniforms.bumpScale.value *= -1;
|
|
}
|
|
if (material.normalMap) {
|
|
uniforms.normalMap.value = material.normalMap;
|
|
uniforms.normalScale.value.copy(material.normalScale);
|
|
if (material.side === BackSide)
|
|
uniforms.normalScale.value.negate();
|
|
}
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
const envMap = properties.get(material).envMap;
|
|
if (envMap) {
|
|
uniforms.envMapIntensity.value = material.envMapIntensity;
|
|
}
|
|
}
|
|
function refreshUniformsPhysical(uniforms, material, transmissionRenderTarget) {
|
|
refreshUniformsStandard(uniforms, material);
|
|
uniforms.ior.value = material.ior;
|
|
if (material.sheenTint)
|
|
uniforms.sheenTint.value.copy(material.sheenTint);
|
|
if (material.clearcoat > 0) {
|
|
uniforms.clearcoat.value = material.clearcoat;
|
|
uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
|
|
if (material.clearcoatMap) {
|
|
uniforms.clearcoatMap.value = material.clearcoatMap;
|
|
}
|
|
if (material.clearcoatRoughnessMap) {
|
|
uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
|
|
}
|
|
if (material.clearcoatNormalMap) {
|
|
uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale);
|
|
uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
|
|
if (material.side === BackSide) {
|
|
uniforms.clearcoatNormalScale.value.negate();
|
|
}
|
|
}
|
|
}
|
|
if (material.transmission > 0) {
|
|
uniforms.transmission.value = material.transmission;
|
|
uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
|
|
uniforms.transmissionSamplerSize.value.set(transmissionRenderTarget.width, transmissionRenderTarget.height);
|
|
if (material.transmissionMap) {
|
|
uniforms.transmissionMap.value = material.transmissionMap;
|
|
}
|
|
uniforms.thickness.value = material.thickness;
|
|
if (material.thicknessMap) {
|
|
uniforms.thicknessMap.value = material.thicknessMap;
|
|
}
|
|
uniforms.attenuationDistance.value = material.attenuationDistance;
|
|
uniforms.attenuationTint.value.copy(material.attenuationTint);
|
|
}
|
|
uniforms.specularIntensity.value = material.specularIntensity;
|
|
uniforms.specularTint.value.copy(material.specularTint);
|
|
if (material.specularIntensityMap) {
|
|
uniforms.specularIntensityMap.value = material.specularIntensityMap;
|
|
}
|
|
if (material.specularTintMap) {
|
|
uniforms.specularTintMap.value = material.specularTintMap;
|
|
}
|
|
}
|
|
function refreshUniformsMatcap(uniforms, material) {
|
|
if (material.matcap) {
|
|
uniforms.matcap.value = material.matcap;
|
|
}
|
|
if (material.bumpMap) {
|
|
uniforms.bumpMap.value = material.bumpMap;
|
|
uniforms.bumpScale.value = material.bumpScale;
|
|
if (material.side === BackSide)
|
|
uniforms.bumpScale.value *= -1;
|
|
}
|
|
if (material.normalMap) {
|
|
uniforms.normalMap.value = material.normalMap;
|
|
uniforms.normalScale.value.copy(material.normalScale);
|
|
if (material.side === BackSide)
|
|
uniforms.normalScale.value.negate();
|
|
}
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
}
|
|
function refreshUniformsDepth(uniforms, material) {
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
}
|
|
function refreshUniformsDistance(uniforms, material) {
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
uniforms.referencePosition.value.copy(material.referencePosition);
|
|
uniforms.nearDistance.value = material.nearDistance;
|
|
uniforms.farDistance.value = material.farDistance;
|
|
}
|
|
function refreshUniformsNormal(uniforms, material) {
|
|
if (material.bumpMap) {
|
|
uniforms.bumpMap.value = material.bumpMap;
|
|
uniforms.bumpScale.value = material.bumpScale;
|
|
if (material.side === BackSide)
|
|
uniforms.bumpScale.value *= -1;
|
|
}
|
|
if (material.normalMap) {
|
|
uniforms.normalMap.value = material.normalMap;
|
|
uniforms.normalScale.value.copy(material.normalScale);
|
|
if (material.side === BackSide)
|
|
uniforms.normalScale.value.negate();
|
|
}
|
|
if (material.displacementMap) {
|
|
uniforms.displacementMap.value = material.displacementMap;
|
|
uniforms.displacementScale.value = material.displacementScale;
|
|
uniforms.displacementBias.value = material.displacementBias;
|
|
}
|
|
}
|
|
return {
|
|
refreshFogUniforms,
|
|
refreshMaterialUniforms
|
|
};
|
|
}
|
|
function createCanvasElement() {
|
|
const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
|
canvas.style.display = "block";
|
|
return canvas;
|
|
}
|
|
function WebGLRenderer(parameters = {}) {
|
|
const _canvas2 = parameters.canvas !== void 0 ? parameters.canvas : createCanvasElement(), _context2 = parameters.context !== void 0 ? parameters.context : null, _alpha = parameters.alpha !== void 0 ? parameters.alpha : false, _depth = parameters.depth !== void 0 ? parameters.depth : true, _stencil = parameters.stencil !== void 0 ? parameters.stencil : true, _antialias = parameters.antialias !== void 0 ? parameters.antialias : false, _premultipliedAlpha = parameters.premultipliedAlpha !== void 0 ? parameters.premultipliedAlpha : true, _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== void 0 ? parameters.preserveDrawingBuffer : false, _powerPreference = parameters.powerPreference !== void 0 ? parameters.powerPreference : "default", _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== void 0 ? parameters.failIfMajorPerformanceCaveat : false;
|
|
let currentRenderList = null;
|
|
let currentRenderState = null;
|
|
const renderListStack = [];
|
|
const renderStateStack = [];
|
|
this.domElement = _canvas2;
|
|
this.debug = {
|
|
checkShaderErrors: true
|
|
};
|
|
this.autoClear = true;
|
|
this.autoClearColor = true;
|
|
this.autoClearDepth = true;
|
|
this.autoClearStencil = true;
|
|
this.sortObjects = true;
|
|
this.clippingPlanes = [];
|
|
this.localClippingEnabled = false;
|
|
this.gammaFactor = 2;
|
|
this.outputEncoding = LinearEncoding;
|
|
this.physicallyCorrectLights = false;
|
|
this.toneMapping = NoToneMapping;
|
|
this.toneMappingExposure = 1;
|
|
const _this = this;
|
|
let _isContextLost = false;
|
|
let _currentActiveCubeFace = 0;
|
|
let _currentActiveMipmapLevel = 0;
|
|
let _currentRenderTarget = null;
|
|
let _currentMaterialId = -1;
|
|
let _currentCamera = null;
|
|
const _currentViewport = new Vector4();
|
|
const _currentScissor = new Vector4();
|
|
let _currentScissorTest = null;
|
|
let _width = _canvas2.width;
|
|
let _height = _canvas2.height;
|
|
let _pixelRatio = 1;
|
|
let _opaqueSort = null;
|
|
let _transparentSort = null;
|
|
const _viewport = new Vector4(0, 0, _width, _height);
|
|
const _scissor = new Vector4(0, 0, _width, _height);
|
|
let _scissorTest = false;
|
|
const _currentDrawBuffers = [];
|
|
const _frustum = new Frustum();
|
|
let _clippingEnabled = false;
|
|
let _localClippingEnabled = false;
|
|
let _transmissionRenderTarget = null;
|
|
const _projScreenMatrix2 = new Matrix4();
|
|
const _vector3 = new Vector3();
|
|
const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
|
|
function getTargetPixelRatio() {
|
|
return _currentRenderTarget === null ? _pixelRatio : 1;
|
|
}
|
|
let _gl = _context2;
|
|
function getContext(contextNames, contextAttributes) {
|
|
for (let i = 0; i < contextNames.length; i++) {
|
|
const contextName = contextNames[i];
|
|
const context = _canvas2.getContext(contextName, contextAttributes);
|
|
if (context !== null)
|
|
return context;
|
|
}
|
|
return null;
|
|
}
|
|
try {
|
|
const contextAttributes = {
|
|
alpha: _alpha,
|
|
depth: _depth,
|
|
stencil: _stencil,
|
|
antialias: _antialias,
|
|
premultipliedAlpha: _premultipliedAlpha,
|
|
preserveDrawingBuffer: _preserveDrawingBuffer,
|
|
powerPreference: _powerPreference,
|
|
failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
|
|
};
|
|
_canvas2.addEventListener("webglcontextlost", onContextLost, false);
|
|
_canvas2.addEventListener("webglcontextrestored", onContextRestore, false);
|
|
if (_gl === null) {
|
|
const contextNames = ["webgl2", "webgl", "experimental-webgl"];
|
|
if (_this.isWebGL1Renderer === true) {
|
|
contextNames.shift();
|
|
}
|
|
_gl = getContext(contextNames, contextAttributes);
|
|
if (_gl === null) {
|
|
if (getContext(contextNames)) {
|
|
throw new Error("Error creating WebGL context with your selected attributes.");
|
|
} else {
|
|
throw new Error("Error creating WebGL context.");
|
|
}
|
|
}
|
|
}
|
|
if (_gl.getShaderPrecisionFormat === void 0) {
|
|
_gl.getShaderPrecisionFormat = function() {
|
|
return { "rangeMin": 1, "rangeMax": 1, "precision": 1 };
|
|
};
|
|
}
|
|
} catch (error) {
|
|
console.error("THREE.WebGLRenderer: " + error.message);
|
|
throw error;
|
|
}
|
|
let extensions, capabilities, state, info;
|
|
let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
|
|
let programCache, materials, renderLists, renderStates, clipping, shadowMap;
|
|
let background, morphtargets, bufferRenderer, indexedBufferRenderer;
|
|
let utils, bindingStates;
|
|
function initGLContext() {
|
|
extensions = new WebGLExtensions(_gl);
|
|
capabilities = new WebGLCapabilities(_gl, extensions, parameters);
|
|
extensions.init(capabilities);
|
|
utils = new WebGLUtils(_gl, extensions, capabilities);
|
|
state = new WebGLState(_gl, extensions, capabilities);
|
|
_currentDrawBuffers[0] = 1029;
|
|
info = new WebGLInfo(_gl);
|
|
properties = new WebGLProperties();
|
|
textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info);
|
|
cubemaps = new WebGLCubeMaps(_this);
|
|
cubeuvmaps = new WebGLCubeUVMaps(_this);
|
|
attributes = new WebGLAttributes(_gl, capabilities);
|
|
bindingStates = new WebGLBindingStates(_gl, extensions, attributes, capabilities);
|
|
geometries = new WebGLGeometries(_gl, attributes, info, bindingStates);
|
|
objects = new WebGLObjects(_gl, geometries, attributes, info);
|
|
morphtargets = new WebGLMorphtargets(_gl);
|
|
clipping = new WebGLClipping(properties);
|
|
programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping);
|
|
materials = new WebGLMaterials(properties);
|
|
renderLists = new WebGLRenderLists(properties);
|
|
renderStates = new WebGLRenderStates(extensions, capabilities);
|
|
background = new WebGLBackground(_this, cubemaps, state, objects, _premultipliedAlpha);
|
|
shadowMap = new WebGLShadowMap(_this, objects, capabilities);
|
|
bufferRenderer = new WebGLBufferRenderer(_gl, extensions, info, capabilities);
|
|
indexedBufferRenderer = new WebGLIndexedBufferRenderer(_gl, extensions, info, capabilities);
|
|
info.programs = programCache.programs;
|
|
_this.capabilities = capabilities;
|
|
_this.extensions = extensions;
|
|
_this.properties = properties;
|
|
_this.renderLists = renderLists;
|
|
_this.shadowMap = shadowMap;
|
|
_this.state = state;
|
|
_this.info = info;
|
|
}
|
|
initGLContext();
|
|
const xr = new WebXRManager(_this, _gl);
|
|
this.xr = xr;
|
|
this.getContext = function() {
|
|
return _gl;
|
|
};
|
|
this.getContextAttributes = function() {
|
|
return _gl.getContextAttributes();
|
|
};
|
|
this.forceContextLoss = function() {
|
|
const extension = extensions.get("WEBGL_lose_context");
|
|
if (extension)
|
|
extension.loseContext();
|
|
};
|
|
this.forceContextRestore = function() {
|
|
const extension = extensions.get("WEBGL_lose_context");
|
|
if (extension)
|
|
extension.restoreContext();
|
|
};
|
|
this.getPixelRatio = function() {
|
|
return _pixelRatio;
|
|
};
|
|
this.setPixelRatio = function(value) {
|
|
if (value === void 0)
|
|
return;
|
|
_pixelRatio = value;
|
|
this.setSize(_width, _height, false);
|
|
};
|
|
this.getSize = function(target) {
|
|
return target.set(_width, _height);
|
|
};
|
|
this.setSize = function(width, height, updateStyle) {
|
|
if (xr.isPresenting) {
|
|
console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting.");
|
|
return;
|
|
}
|
|
_width = width;
|
|
_height = height;
|
|
_canvas2.width = Math.floor(width * _pixelRatio);
|
|
_canvas2.height = Math.floor(height * _pixelRatio);
|
|
if (updateStyle !== false) {
|
|
_canvas2.style.width = width + "px";
|
|
_canvas2.style.height = height + "px";
|
|
}
|
|
this.setViewport(0, 0, width, height);
|
|
};
|
|
this.getDrawingBufferSize = function(target) {
|
|
return target.set(_width * _pixelRatio, _height * _pixelRatio).floor();
|
|
};
|
|
this.setDrawingBufferSize = function(width, height, pixelRatio) {
|
|
_width = width;
|
|
_height = height;
|
|
_pixelRatio = pixelRatio;
|
|
_canvas2.width = Math.floor(width * pixelRatio);
|
|
_canvas2.height = Math.floor(height * pixelRatio);
|
|
this.setViewport(0, 0, width, height);
|
|
};
|
|
this.getCurrentViewport = function(target) {
|
|
return target.copy(_currentViewport);
|
|
};
|
|
this.getViewport = function(target) {
|
|
return target.copy(_viewport);
|
|
};
|
|
this.setViewport = function(x, y, width, height) {
|
|
if (x.isVector4) {
|
|
_viewport.set(x.x, x.y, x.z, x.w);
|
|
} else {
|
|
_viewport.set(x, y, width, height);
|
|
}
|
|
state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor());
|
|
};
|
|
this.getScissor = function(target) {
|
|
return target.copy(_scissor);
|
|
};
|
|
this.setScissor = function(x, y, width, height) {
|
|
if (x.isVector4) {
|
|
_scissor.set(x.x, x.y, x.z, x.w);
|
|
} else {
|
|
_scissor.set(x, y, width, height);
|
|
}
|
|
state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor());
|
|
};
|
|
this.getScissorTest = function() {
|
|
return _scissorTest;
|
|
};
|
|
this.setScissorTest = function(boolean) {
|
|
state.setScissorTest(_scissorTest = boolean);
|
|
};
|
|
this.setOpaqueSort = function(method) {
|
|
_opaqueSort = method;
|
|
};
|
|
this.setTransparentSort = function(method) {
|
|
_transparentSort = method;
|
|
};
|
|
this.getClearColor = function(target) {
|
|
return target.copy(background.getClearColor());
|
|
};
|
|
this.setClearColor = function() {
|
|
background.setClearColor.apply(background, arguments);
|
|
};
|
|
this.getClearAlpha = function() {
|
|
return background.getClearAlpha();
|
|
};
|
|
this.setClearAlpha = function() {
|
|
background.setClearAlpha.apply(background, arguments);
|
|
};
|
|
this.clear = function(color, depth, stencil) {
|
|
let bits = 0;
|
|
if (color === void 0 || color)
|
|
bits |= 16384;
|
|
if (depth === void 0 || depth)
|
|
bits |= 256;
|
|
if (stencil === void 0 || stencil)
|
|
bits |= 1024;
|
|
_gl.clear(bits);
|
|
};
|
|
this.clearColor = function() {
|
|
this.clear(true, false, false);
|
|
};
|
|
this.clearDepth = function() {
|
|
this.clear(false, true, false);
|
|
};
|
|
this.clearStencil = function() {
|
|
this.clear(false, false, true);
|
|
};
|
|
this.dispose = function() {
|
|
_canvas2.removeEventListener("webglcontextlost", onContextLost, false);
|
|
_canvas2.removeEventListener("webglcontextrestored", onContextRestore, false);
|
|
renderLists.dispose();
|
|
renderStates.dispose();
|
|
properties.dispose();
|
|
cubemaps.dispose();
|
|
cubeuvmaps.dispose();
|
|
objects.dispose();
|
|
bindingStates.dispose();
|
|
xr.dispose();
|
|
xr.removeEventListener("sessionstart", onXRSessionStart);
|
|
xr.removeEventListener("sessionend", onXRSessionEnd);
|
|
if (_transmissionRenderTarget) {
|
|
_transmissionRenderTarget.dispose();
|
|
_transmissionRenderTarget = null;
|
|
}
|
|
animation.stop();
|
|
};
|
|
function onContextLost(event) {
|
|
event.preventDefault();
|
|
console.log("THREE.WebGLRenderer: Context Lost.");
|
|
_isContextLost = true;
|
|
}
|
|
function onContextRestore() {
|
|
console.log("THREE.WebGLRenderer: Context Restored.");
|
|
_isContextLost = false;
|
|
const infoAutoReset = info.autoReset;
|
|
const shadowMapEnabled = shadowMap.enabled;
|
|
const shadowMapAutoUpdate = shadowMap.autoUpdate;
|
|
const shadowMapNeedsUpdate = shadowMap.needsUpdate;
|
|
const shadowMapType = shadowMap.type;
|
|
initGLContext();
|
|
info.autoReset = infoAutoReset;
|
|
shadowMap.enabled = shadowMapEnabled;
|
|
shadowMap.autoUpdate = shadowMapAutoUpdate;
|
|
shadowMap.needsUpdate = shadowMapNeedsUpdate;
|
|
shadowMap.type = shadowMapType;
|
|
}
|
|
function onMaterialDispose(event) {
|
|
const material = event.target;
|
|
material.removeEventListener("dispose", onMaterialDispose);
|
|
deallocateMaterial(material);
|
|
}
|
|
function deallocateMaterial(material) {
|
|
releaseMaterialProgramReferences(material);
|
|
properties.remove(material);
|
|
}
|
|
function releaseMaterialProgramReferences(material) {
|
|
const programs = properties.get(material).programs;
|
|
if (programs !== void 0) {
|
|
programs.forEach(function(program) {
|
|
programCache.releaseProgram(program);
|
|
});
|
|
}
|
|
}
|
|
function renderObjectImmediate(object, program) {
|
|
object.render(function(object2) {
|
|
_this.renderBufferImmediate(object2, program);
|
|
});
|
|
}
|
|
this.renderBufferImmediate = function(object, program) {
|
|
bindingStates.initAttributes();
|
|
const buffers = properties.get(object);
|
|
if (object.hasPositions && !buffers.position)
|
|
buffers.position = _gl.createBuffer();
|
|
if (object.hasNormals && !buffers.normal)
|
|
buffers.normal = _gl.createBuffer();
|
|
if (object.hasUvs && !buffers.uv)
|
|
buffers.uv = _gl.createBuffer();
|
|
if (object.hasColors && !buffers.color)
|
|
buffers.color = _gl.createBuffer();
|
|
const programAttributes = program.getAttributes();
|
|
if (object.hasPositions) {
|
|
_gl.bindBuffer(34962, buffers.position);
|
|
_gl.bufferData(34962, object.positionArray, 35048);
|
|
bindingStates.enableAttribute(programAttributes.position.location);
|
|
_gl.vertexAttribPointer(programAttributes.position.location, 3, 5126, false, 0, 0);
|
|
}
|
|
if (object.hasNormals) {
|
|
_gl.bindBuffer(34962, buffers.normal);
|
|
_gl.bufferData(34962, object.normalArray, 35048);
|
|
bindingStates.enableAttribute(programAttributes.normal.location);
|
|
_gl.vertexAttribPointer(programAttributes.normal.location, 3, 5126, false, 0, 0);
|
|
}
|
|
if (object.hasUvs) {
|
|
_gl.bindBuffer(34962, buffers.uv);
|
|
_gl.bufferData(34962, object.uvArray, 35048);
|
|
bindingStates.enableAttribute(programAttributes.uv.location);
|
|
_gl.vertexAttribPointer(programAttributes.uv.location, 2, 5126, false, 0, 0);
|
|
}
|
|
if (object.hasColors) {
|
|
_gl.bindBuffer(34962, buffers.color);
|
|
_gl.bufferData(34962, object.colorArray, 35048);
|
|
bindingStates.enableAttribute(programAttributes.color.location);
|
|
_gl.vertexAttribPointer(programAttributes.color.location, 3, 5126, false, 0, 0);
|
|
}
|
|
bindingStates.disableUnusedAttributes();
|
|
_gl.drawArrays(4, 0, object.count);
|
|
object.count = 0;
|
|
};
|
|
this.renderBufferDirect = function(camera, scene, geometry, material, object, group) {
|
|
if (scene === null)
|
|
scene = _emptyScene;
|
|
const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0;
|
|
const program = setProgram(camera, scene, material, object);
|
|
state.setMaterial(material, frontFaceCW);
|
|
let index = geometry.index;
|
|
const position = geometry.attributes.position;
|
|
if (index === null) {
|
|
if (position === void 0 || position.count === 0)
|
|
return;
|
|
} else if (index.count === 0) {
|
|
return;
|
|
}
|
|
let rangeFactor = 1;
|
|
if (material.wireframe === true) {
|
|
index = geometries.getWireframeAttribute(geometry);
|
|
rangeFactor = 2;
|
|
}
|
|
if (geometry.morphAttributes.position !== void 0 || geometry.morphAttributes.normal !== void 0) {
|
|
morphtargets.update(object, geometry, material, program);
|
|
}
|
|
bindingStates.setup(object, material, program, geometry, index);
|
|
let attribute;
|
|
let renderer = bufferRenderer;
|
|
if (index !== null) {
|
|
attribute = attributes.get(index);
|
|
renderer = indexedBufferRenderer;
|
|
renderer.setIndex(attribute);
|
|
}
|
|
const dataCount = index !== null ? index.count : position.count;
|
|
const rangeStart = geometry.drawRange.start * rangeFactor;
|
|
const rangeCount = geometry.drawRange.count * rangeFactor;
|
|
const groupStart = group !== null ? group.start * rangeFactor : 0;
|
|
const groupCount = group !== null ? group.count * rangeFactor : Infinity;
|
|
const drawStart = Math.max(rangeStart, groupStart);
|
|
const drawEnd = Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1;
|
|
const drawCount = Math.max(0, drawEnd - drawStart + 1);
|
|
if (drawCount === 0)
|
|
return;
|
|
if (object.isMesh) {
|
|
if (material.wireframe === true) {
|
|
state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio());
|
|
renderer.setMode(1);
|
|
} else {
|
|
renderer.setMode(4);
|
|
}
|
|
} else if (object.isLine) {
|
|
let lineWidth = material.linewidth;
|
|
if (lineWidth === void 0)
|
|
lineWidth = 1;
|
|
state.setLineWidth(lineWidth * getTargetPixelRatio());
|
|
if (object.isLineSegments) {
|
|
renderer.setMode(1);
|
|
} else if (object.isLineLoop) {
|
|
renderer.setMode(2);
|
|
} else {
|
|
renderer.setMode(3);
|
|
}
|
|
} else if (object.isPoints) {
|
|
renderer.setMode(0);
|
|
} else if (object.isSprite) {
|
|
renderer.setMode(4);
|
|
}
|
|
if (object.isInstancedMesh) {
|
|
renderer.renderInstances(drawStart, drawCount, object.count);
|
|
} else if (geometry.isInstancedBufferGeometry) {
|
|
const instanceCount = Math.min(geometry.instanceCount, geometry._maxInstanceCount);
|
|
renderer.renderInstances(drawStart, drawCount, instanceCount);
|
|
} else {
|
|
renderer.render(drawStart, drawCount);
|
|
}
|
|
};
|
|
this.compile = function(scene, camera) {
|
|
currentRenderState = renderStates.get(scene);
|
|
currentRenderState.init();
|
|
renderStateStack.push(currentRenderState);
|
|
scene.traverseVisible(function(object) {
|
|
if (object.isLight && object.layers.test(camera.layers)) {
|
|
currentRenderState.pushLight(object);
|
|
if (object.castShadow) {
|
|
currentRenderState.pushShadow(object);
|
|
}
|
|
}
|
|
});
|
|
currentRenderState.setupLights(_this.physicallyCorrectLights);
|
|
scene.traverse(function(object) {
|
|
const material = object.material;
|
|
if (material) {
|
|
if (Array.isArray(material)) {
|
|
for (let i = 0; i < material.length; i++) {
|
|
const material2 = material[i];
|
|
getProgram(material2, scene, object);
|
|
}
|
|
} else {
|
|
getProgram(material, scene, object);
|
|
}
|
|
}
|
|
});
|
|
renderStateStack.pop();
|
|
currentRenderState = null;
|
|
};
|
|
let onAnimationFrameCallback = null;
|
|
function onAnimationFrame(time) {
|
|
if (onAnimationFrameCallback)
|
|
onAnimationFrameCallback(time);
|
|
}
|
|
function onXRSessionStart() {
|
|
animation.stop();
|
|
}
|
|
function onXRSessionEnd() {
|
|
animation.start();
|
|
}
|
|
const animation = new WebGLAnimation();
|
|
animation.setAnimationLoop(onAnimationFrame);
|
|
if (typeof window !== "undefined")
|
|
animation.setContext(window);
|
|
this.setAnimationLoop = function(callback) {
|
|
onAnimationFrameCallback = callback;
|
|
xr.setAnimationLoop(callback);
|
|
callback === null ? animation.stop() : animation.start();
|
|
};
|
|
xr.addEventListener("sessionstart", onXRSessionStart);
|
|
xr.addEventListener("sessionend", onXRSessionEnd);
|
|
this.render = function(scene, camera) {
|
|
if (camera !== void 0 && camera.isCamera !== true) {
|
|
console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");
|
|
return;
|
|
}
|
|
if (_isContextLost === true)
|
|
return;
|
|
if (scene.autoUpdate === true)
|
|
scene.updateMatrixWorld();
|
|
if (camera.parent === null)
|
|
camera.updateMatrixWorld();
|
|
if (xr.enabled === true && xr.isPresenting === true) {
|
|
if (xr.cameraAutoUpdate === true)
|
|
xr.updateCamera(camera);
|
|
camera = xr.getCamera();
|
|
}
|
|
if (scene.isScene === true)
|
|
scene.onBeforeRender(_this, scene, camera, _currentRenderTarget);
|
|
currentRenderState = renderStates.get(scene, renderStateStack.length);
|
|
currentRenderState.init();
|
|
renderStateStack.push(currentRenderState);
|
|
_projScreenMatrix2.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
_frustum.setFromProjectionMatrix(_projScreenMatrix2);
|
|
_localClippingEnabled = this.localClippingEnabled;
|
|
_clippingEnabled = clipping.init(this.clippingPlanes, _localClippingEnabled, camera);
|
|
currentRenderList = renderLists.get(scene, renderListStack.length);
|
|
currentRenderList.init();
|
|
renderListStack.push(currentRenderList);
|
|
projectObject(scene, camera, 0, _this.sortObjects);
|
|
currentRenderList.finish();
|
|
if (_this.sortObjects === true) {
|
|
currentRenderList.sort(_opaqueSort, _transparentSort);
|
|
}
|
|
if (_clippingEnabled === true)
|
|
clipping.beginShadows();
|
|
const shadowsArray = currentRenderState.state.shadowsArray;
|
|
shadowMap.render(shadowsArray, scene, camera);
|
|
if (_clippingEnabled === true)
|
|
clipping.endShadows();
|
|
if (this.info.autoReset === true)
|
|
this.info.reset();
|
|
background.render(currentRenderList, scene);
|
|
currentRenderState.setupLights(_this.physicallyCorrectLights);
|
|
if (camera.isArrayCamera) {
|
|
const cameras = camera.cameras;
|
|
for (let i = 0, l = cameras.length; i < l; i++) {
|
|
const camera2 = cameras[i];
|
|
renderScene(currentRenderList, scene, camera2, camera2.viewport);
|
|
}
|
|
} else {
|
|
renderScene(currentRenderList, scene, camera);
|
|
}
|
|
if (_currentRenderTarget !== null) {
|
|
textures.updateMultisampleRenderTarget(_currentRenderTarget);
|
|
textures.updateRenderTargetMipmap(_currentRenderTarget);
|
|
}
|
|
if (scene.isScene === true)
|
|
scene.onAfterRender(_this, scene, camera);
|
|
state.buffers.depth.setTest(true);
|
|
state.buffers.depth.setMask(true);
|
|
state.buffers.color.setMask(true);
|
|
state.setPolygonOffset(false);
|
|
bindingStates.resetDefaultState();
|
|
_currentMaterialId = -1;
|
|
_currentCamera = null;
|
|
renderStateStack.pop();
|
|
if (renderStateStack.length > 0) {
|
|
currentRenderState = renderStateStack[renderStateStack.length - 1];
|
|
} else {
|
|
currentRenderState = null;
|
|
}
|
|
renderListStack.pop();
|
|
if (renderListStack.length > 0) {
|
|
currentRenderList = renderListStack[renderListStack.length - 1];
|
|
} else {
|
|
currentRenderList = null;
|
|
}
|
|
};
|
|
function projectObject(object, camera, groupOrder, sortObjects) {
|
|
if (object.visible === false)
|
|
return;
|
|
const visible = object.layers.test(camera.layers);
|
|
if (visible) {
|
|
if (object.isGroup) {
|
|
groupOrder = object.renderOrder;
|
|
} else if (object.isLOD) {
|
|
if (object.autoUpdate === true)
|
|
object.update(camera);
|
|
} else if (object.isLight) {
|
|
currentRenderState.pushLight(object);
|
|
if (object.castShadow) {
|
|
currentRenderState.pushShadow(object);
|
|
}
|
|
} else if (object.isSprite) {
|
|
if (!object.frustumCulled || _frustum.intersectsSprite(object)) {
|
|
if (sortObjects) {
|
|
_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix2);
|
|
}
|
|
const geometry = objects.update(object);
|
|
const material = object.material;
|
|
if (material.visible) {
|
|
currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null);
|
|
}
|
|
}
|
|
} else if (object.isImmediateRenderObject) {
|
|
if (sortObjects) {
|
|
_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix2);
|
|
}
|
|
currentRenderList.push(object, null, object.material, groupOrder, _vector3.z, null);
|
|
} else if (object.isMesh || object.isLine || object.isPoints) {
|
|
if (object.isSkinnedMesh) {
|
|
if (object.skeleton.frame !== info.render.frame) {
|
|
object.skeleton.update();
|
|
object.skeleton.frame = info.render.frame;
|
|
}
|
|
}
|
|
if (!object.frustumCulled || _frustum.intersectsObject(object)) {
|
|
if (sortObjects) {
|
|
_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix2);
|
|
}
|
|
const geometry = objects.update(object);
|
|
const material = object.material;
|
|
if (Array.isArray(material)) {
|
|
const groups = geometry.groups;
|
|
for (let i = 0, l = groups.length; i < l; i++) {
|
|
const group = groups[i];
|
|
const groupMaterial = material[group.materialIndex];
|
|
if (groupMaterial && groupMaterial.visible) {
|
|
currentRenderList.push(object, geometry, groupMaterial, groupOrder, _vector3.z, group);
|
|
}
|
|
}
|
|
} else if (material.visible) {
|
|
currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const children = object.children;
|
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
projectObject(children[i], camera, groupOrder, sortObjects);
|
|
}
|
|
}
|
|
function renderScene(currentRenderList2, scene, camera, viewport) {
|
|
const opaqueObjects = currentRenderList2.opaque;
|
|
const transmissiveObjects = currentRenderList2.transmissive;
|
|
const transparentObjects = currentRenderList2.transparent;
|
|
currentRenderState.setupLightsView(camera);
|
|
if (transmissiveObjects.length > 0)
|
|
renderTransmissionPass(opaqueObjects, scene, camera);
|
|
if (viewport)
|
|
state.viewport(_currentViewport.copy(viewport));
|
|
if (opaqueObjects.length > 0)
|
|
renderObjects(opaqueObjects, scene, camera);
|
|
if (transmissiveObjects.length > 0)
|
|
renderObjects(transmissiveObjects, scene, camera);
|
|
if (transparentObjects.length > 0)
|
|
renderObjects(transparentObjects, scene, camera);
|
|
}
|
|
function renderTransmissionPass(opaqueObjects, scene, camera) {
|
|
if (_transmissionRenderTarget === null) {
|
|
const needsAntialias = _antialias === true && capabilities.isWebGL2 === true;
|
|
const renderTargetType = needsAntialias ? WebGLMultisampleRenderTarget : WebGLRenderTarget;
|
|
_transmissionRenderTarget = new renderTargetType(1024, 1024, {
|
|
generateMipmaps: true,
|
|
type: utils.convert(HalfFloatType) !== null ? HalfFloatType : UnsignedByteType,
|
|
minFilter: LinearMipmapLinearFilter,
|
|
magFilter: NearestFilter,
|
|
wrapS: ClampToEdgeWrapping,
|
|
wrapT: ClampToEdgeWrapping
|
|
});
|
|
}
|
|
const currentRenderTarget = _this.getRenderTarget();
|
|
_this.setRenderTarget(_transmissionRenderTarget);
|
|
_this.clear();
|
|
const currentToneMapping = _this.toneMapping;
|
|
_this.toneMapping = NoToneMapping;
|
|
renderObjects(opaqueObjects, scene, camera);
|
|
_this.toneMapping = currentToneMapping;
|
|
textures.updateMultisampleRenderTarget(_transmissionRenderTarget);
|
|
textures.updateRenderTargetMipmap(_transmissionRenderTarget);
|
|
_this.setRenderTarget(currentRenderTarget);
|
|
}
|
|
function renderObjects(renderList, scene, camera) {
|
|
const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
|
|
for (let i = 0, l = renderList.length; i < l; i++) {
|
|
const renderItem = renderList[i];
|
|
const object = renderItem.object;
|
|
const geometry = renderItem.geometry;
|
|
const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
|
|
const group = renderItem.group;
|
|
if (object.layers.test(camera.layers)) {
|
|
renderObject(object, scene, camera, geometry, material, group);
|
|
}
|
|
}
|
|
}
|
|
function renderObject(object, scene, camera, geometry, material, group) {
|
|
object.onBeforeRender(_this, scene, camera, geometry, material, group);
|
|
object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
|
|
object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
|
|
if (object.isImmediateRenderObject) {
|
|
const program = setProgram(camera, scene, material, object);
|
|
state.setMaterial(material);
|
|
bindingStates.reset();
|
|
renderObjectImmediate(object, program);
|
|
} else {
|
|
if (material.transparent === true && material.side === DoubleSide) {
|
|
material.side = BackSide;
|
|
material.needsUpdate = true;
|
|
_this.renderBufferDirect(camera, scene, geometry, material, object, group);
|
|
material.side = FrontSide;
|
|
material.needsUpdate = true;
|
|
_this.renderBufferDirect(camera, scene, geometry, material, object, group);
|
|
material.side = DoubleSide;
|
|
} else {
|
|
_this.renderBufferDirect(camera, scene, geometry, material, object, group);
|
|
}
|
|
}
|
|
object.onAfterRender(_this, scene, camera, geometry, material, group);
|
|
}
|
|
function getProgram(material, scene, object) {
|
|
if (scene.isScene !== true)
|
|
scene = _emptyScene;
|
|
const materialProperties = properties.get(material);
|
|
const lights = currentRenderState.state.lights;
|
|
const shadowsArray = currentRenderState.state.shadowsArray;
|
|
const lightsStateVersion = lights.state.version;
|
|
const parameters2 = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
|
|
const programCacheKey = programCache.getProgramCacheKey(parameters2);
|
|
let programs = materialProperties.programs;
|
|
materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
materialProperties.fog = scene.fog;
|
|
materialProperties.envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || materialProperties.environment);
|
|
if (programs === void 0) {
|
|
material.addEventListener("dispose", onMaterialDispose);
|
|
programs = /* @__PURE__ */ new Map();
|
|
materialProperties.programs = programs;
|
|
}
|
|
let program = programs.get(programCacheKey);
|
|
if (program !== void 0) {
|
|
if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) {
|
|
updateCommonMaterialProperties(material, parameters2);
|
|
return program;
|
|
}
|
|
} else {
|
|
parameters2.uniforms = programCache.getUniforms(material);
|
|
material.onBuild(parameters2, _this);
|
|
material.onBeforeCompile(parameters2, _this);
|
|
program = programCache.acquireProgram(parameters2, programCacheKey);
|
|
programs.set(programCacheKey, program);
|
|
materialProperties.uniforms = parameters2.uniforms;
|
|
}
|
|
const uniforms = materialProperties.uniforms;
|
|
if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) {
|
|
uniforms.clippingPlanes = clipping.uniform;
|
|
}
|
|
updateCommonMaterialProperties(material, parameters2);
|
|
materialProperties.needsLights = materialNeedsLights(material);
|
|
materialProperties.lightsStateVersion = lightsStateVersion;
|
|
if (materialProperties.needsLights) {
|
|
uniforms.ambientLightColor.value = lights.state.ambient;
|
|
uniforms.lightProbe.value = lights.state.probe;
|
|
uniforms.directionalLights.value = lights.state.directional;
|
|
uniforms.directionalLightShadows.value = lights.state.directionalShadow;
|
|
uniforms.spotLights.value = lights.state.spot;
|
|
uniforms.spotLightShadows.value = lights.state.spotShadow;
|
|
uniforms.rectAreaLights.value = lights.state.rectArea;
|
|
uniforms.ltc_1.value = lights.state.rectAreaLTC1;
|
|
uniforms.ltc_2.value = lights.state.rectAreaLTC2;
|
|
uniforms.pointLights.value = lights.state.point;
|
|
uniforms.pointLightShadows.value = lights.state.pointShadow;
|
|
uniforms.hemisphereLights.value = lights.state.hemi;
|
|
uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
|
|
uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
|
|
uniforms.spotShadowMap.value = lights.state.spotShadowMap;
|
|
uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
|
|
uniforms.pointShadowMap.value = lights.state.pointShadowMap;
|
|
uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
|
|
}
|
|
const progUniforms = program.getUniforms();
|
|
const uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
|
|
materialProperties.currentProgram = program;
|
|
materialProperties.uniformsList = uniformsList;
|
|
return program;
|
|
}
|
|
function updateCommonMaterialProperties(material, parameters2) {
|
|
const materialProperties = properties.get(material);
|
|
materialProperties.outputEncoding = parameters2.outputEncoding;
|
|
materialProperties.instancing = parameters2.instancing;
|
|
materialProperties.skinning = parameters2.skinning;
|
|
materialProperties.morphTargets = parameters2.morphTargets;
|
|
materialProperties.morphNormals = parameters2.morphNormals;
|
|
materialProperties.numClippingPlanes = parameters2.numClippingPlanes;
|
|
materialProperties.numIntersection = parameters2.numClipIntersection;
|
|
materialProperties.vertexAlphas = parameters2.vertexAlphas;
|
|
materialProperties.vertexTangents = parameters2.vertexTangents;
|
|
}
|
|
function setProgram(camera, scene, material, object) {
|
|
if (scene.isScene !== true)
|
|
scene = _emptyScene;
|
|
textures.resetTextureUnits();
|
|
const fog = scene.fog;
|
|
const environment = material.isMeshStandardMaterial ? scene.environment : null;
|
|
const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
|
|
const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
|
|
const vertexAlphas = material.vertexColors === true && !!object.geometry && !!object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4;
|
|
const vertexTangents = !!object.geometry && !!object.geometry.attributes.tangent;
|
|
const morphTargets = !!object.geometry && !!object.geometry.morphAttributes.position;
|
|
const morphNormals = !!object.geometry && !!object.geometry.morphAttributes.normal;
|
|
const materialProperties = properties.get(material);
|
|
const lights = currentRenderState.state.lights;
|
|
if (_clippingEnabled === true) {
|
|
if (_localClippingEnabled === true || camera !== _currentCamera) {
|
|
const useCache = camera === _currentCamera && material.id === _currentMaterialId;
|
|
clipping.setState(material, camera, useCache);
|
|
}
|
|
}
|
|
let needsProgramChange = false;
|
|
if (material.version === materialProperties.__version) {
|
|
if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.outputEncoding !== encoding) {
|
|
needsProgramChange = true;
|
|
} else if (object.isInstancedMesh && materialProperties.instancing === false) {
|
|
needsProgramChange = true;
|
|
} else if (!object.isInstancedMesh && materialProperties.instancing === true) {
|
|
needsProgramChange = true;
|
|
} else if (object.isSkinnedMesh && materialProperties.skinning === false) {
|
|
needsProgramChange = true;
|
|
} else if (!object.isSkinnedMesh && materialProperties.skinning === true) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.envMap !== envMap) {
|
|
needsProgramChange = true;
|
|
} else if (material.fog && materialProperties.fog !== fog) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.numClippingPlanes !== void 0 && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.vertexAlphas !== vertexAlphas) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.vertexTangents !== vertexTangents) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.morphTargets !== morphTargets) {
|
|
needsProgramChange = true;
|
|
} else if (materialProperties.morphNormals !== morphNormals) {
|
|
needsProgramChange = true;
|
|
}
|
|
} else {
|
|
needsProgramChange = true;
|
|
materialProperties.__version = material.version;
|
|
}
|
|
let program = materialProperties.currentProgram;
|
|
if (needsProgramChange === true) {
|
|
program = getProgram(material, scene, object);
|
|
}
|
|
let refreshProgram = false;
|
|
let refreshMaterial = false;
|
|
let refreshLights = false;
|
|
const p_uniforms = program.getUniforms(), m_uniforms = materialProperties.uniforms;
|
|
if (state.useProgram(program.program)) {
|
|
refreshProgram = true;
|
|
refreshMaterial = true;
|
|
refreshLights = true;
|
|
}
|
|
if (material.id !== _currentMaterialId) {
|
|
_currentMaterialId = material.id;
|
|
refreshMaterial = true;
|
|
}
|
|
if (refreshProgram || _currentCamera !== camera) {
|
|
p_uniforms.setValue(_gl, "projectionMatrix", camera.projectionMatrix);
|
|
if (capabilities.logarithmicDepthBuffer) {
|
|
p_uniforms.setValue(_gl, "logDepthBufFC", 2 / (Math.log(camera.far + 1) / Math.LN2));
|
|
}
|
|
if (_currentCamera !== camera) {
|
|
_currentCamera = camera;
|
|
refreshMaterial = true;
|
|
refreshLights = true;
|
|
}
|
|
if (material.isShaderMaterial || material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshStandardMaterial || material.envMap) {
|
|
const uCamPos = p_uniforms.map.cameraPosition;
|
|
if (uCamPos !== void 0) {
|
|
uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld));
|
|
}
|
|
}
|
|
if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial) {
|
|
p_uniforms.setValue(_gl, "isOrthographic", camera.isOrthographicCamera === true);
|
|
}
|
|
if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.isShadowMaterial || object.isSkinnedMesh) {
|
|
p_uniforms.setValue(_gl, "viewMatrix", camera.matrixWorldInverse);
|
|
}
|
|
}
|
|
if (object.isSkinnedMesh) {
|
|
p_uniforms.setOptional(_gl, object, "bindMatrix");
|
|
p_uniforms.setOptional(_gl, object, "bindMatrixInverse");
|
|
const skeleton = object.skeleton;
|
|
if (skeleton) {
|
|
if (capabilities.floatVertexTextures) {
|
|
if (skeleton.boneTexture === null)
|
|
skeleton.computeBoneTexture();
|
|
p_uniforms.setValue(_gl, "boneTexture", skeleton.boneTexture, textures);
|
|
p_uniforms.setValue(_gl, "boneTextureSize", skeleton.boneTextureSize);
|
|
} else {
|
|
p_uniforms.setOptional(_gl, skeleton, "boneMatrices");
|
|
}
|
|
}
|
|
}
|
|
if (refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow) {
|
|
materialProperties.receiveShadow = object.receiveShadow;
|
|
p_uniforms.setValue(_gl, "receiveShadow", object.receiveShadow);
|
|
}
|
|
if (refreshMaterial) {
|
|
p_uniforms.setValue(_gl, "toneMappingExposure", _this.toneMappingExposure);
|
|
if (materialProperties.needsLights) {
|
|
markUniformsLightsNeedsUpdate(m_uniforms, refreshLights);
|
|
}
|
|
if (fog && material.fog) {
|
|
materials.refreshFogUniforms(m_uniforms, fog);
|
|
}
|
|
materials.refreshMaterialUniforms(m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget);
|
|
WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures);
|
|
}
|
|
if (material.isShaderMaterial && material.uniformsNeedUpdate === true) {
|
|
WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures);
|
|
material.uniformsNeedUpdate = false;
|
|
}
|
|
if (material.isSpriteMaterial) {
|
|
p_uniforms.setValue(_gl, "center", object.center);
|
|
}
|
|
p_uniforms.setValue(_gl, "modelViewMatrix", object.modelViewMatrix);
|
|
p_uniforms.setValue(_gl, "normalMatrix", object.normalMatrix);
|
|
p_uniforms.setValue(_gl, "modelMatrix", object.matrixWorld);
|
|
return program;
|
|
}
|
|
function markUniformsLightsNeedsUpdate(uniforms, value) {
|
|
uniforms.ambientLightColor.needsUpdate = value;
|
|
uniforms.lightProbe.needsUpdate = value;
|
|
uniforms.directionalLights.needsUpdate = value;
|
|
uniforms.directionalLightShadows.needsUpdate = value;
|
|
uniforms.pointLights.needsUpdate = value;
|
|
uniforms.pointLightShadows.needsUpdate = value;
|
|
uniforms.spotLights.needsUpdate = value;
|
|
uniforms.spotLightShadows.needsUpdate = value;
|
|
uniforms.rectAreaLights.needsUpdate = value;
|
|
uniforms.hemisphereLights.needsUpdate = value;
|
|
}
|
|
function materialNeedsLights(material) {
|
|
return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isShadowMaterial || material.isShaderMaterial && material.lights === true;
|
|
}
|
|
this.getActiveCubeFace = function() {
|
|
return _currentActiveCubeFace;
|
|
};
|
|
this.getActiveMipmapLevel = function() {
|
|
return _currentActiveMipmapLevel;
|
|
};
|
|
this.getRenderTarget = function() {
|
|
return _currentRenderTarget;
|
|
};
|
|
this.setRenderTarget = function(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) {
|
|
_currentRenderTarget = renderTarget;
|
|
_currentActiveCubeFace = activeCubeFace;
|
|
_currentActiveMipmapLevel = activeMipmapLevel;
|
|
if (renderTarget && properties.get(renderTarget).__webglFramebuffer === void 0) {
|
|
textures.setupRenderTarget(renderTarget);
|
|
}
|
|
let framebuffer = null;
|
|
let isCube = false;
|
|
let isRenderTarget3D = false;
|
|
if (renderTarget) {
|
|
const texture = renderTarget.texture;
|
|
if (texture.isDataTexture3D || texture.isDataTexture2DArray) {
|
|
isRenderTarget3D = true;
|
|
}
|
|
const __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer;
|
|
if (renderTarget.isWebGLCubeRenderTarget) {
|
|
framebuffer = __webglFramebuffer[activeCubeFace];
|
|
isCube = true;
|
|
} else if (renderTarget.isWebGLMultisampleRenderTarget) {
|
|
framebuffer = properties.get(renderTarget).__webglMultisampledFramebuffer;
|
|
} else {
|
|
framebuffer = __webglFramebuffer;
|
|
}
|
|
_currentViewport.copy(renderTarget.viewport);
|
|
_currentScissor.copy(renderTarget.scissor);
|
|
_currentScissorTest = renderTarget.scissorTest;
|
|
} else {
|
|
_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor();
|
|
_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor();
|
|
_currentScissorTest = _scissorTest;
|
|
}
|
|
const framebufferBound = state.bindFramebuffer(36160, framebuffer);
|
|
if (framebufferBound && capabilities.drawBuffers) {
|
|
let needsUpdate = false;
|
|
if (renderTarget) {
|
|
if (renderTarget.isWebGLMultipleRenderTargets) {
|
|
const textures2 = renderTarget.texture;
|
|
if (_currentDrawBuffers.length !== textures2.length || _currentDrawBuffers[0] !== 36064) {
|
|
for (let i = 0, il = textures2.length; i < il; i++) {
|
|
_currentDrawBuffers[i] = 36064 + i;
|
|
}
|
|
_currentDrawBuffers.length = textures2.length;
|
|
needsUpdate = true;
|
|
}
|
|
} else {
|
|
if (_currentDrawBuffers.length !== 1 || _currentDrawBuffers[0] !== 36064) {
|
|
_currentDrawBuffers[0] = 36064;
|
|
_currentDrawBuffers.length = 1;
|
|
needsUpdate = true;
|
|
}
|
|
}
|
|
} else {
|
|
if (_currentDrawBuffers.length !== 1 || _currentDrawBuffers[0] !== 1029) {
|
|
_currentDrawBuffers[0] = 1029;
|
|
_currentDrawBuffers.length = 1;
|
|
needsUpdate = true;
|
|
}
|
|
}
|
|
if (needsUpdate) {
|
|
if (capabilities.isWebGL2) {
|
|
_gl.drawBuffers(_currentDrawBuffers);
|
|
} else {
|
|
extensions.get("WEBGL_draw_buffers").drawBuffersWEBGL(_currentDrawBuffers);
|
|
}
|
|
}
|
|
}
|
|
state.viewport(_currentViewport);
|
|
state.scissor(_currentScissor);
|
|
state.setScissorTest(_currentScissorTest);
|
|
if (isCube) {
|
|
const textureProperties = properties.get(renderTarget.texture);
|
|
_gl.framebufferTexture2D(36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel);
|
|
} else if (isRenderTarget3D) {
|
|
const textureProperties = properties.get(renderTarget.texture);
|
|
const layer = activeCubeFace || 0;
|
|
_gl.framebufferTextureLayer(36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer);
|
|
}
|
|
_currentMaterialId = -1;
|
|
};
|
|
this.readRenderTargetPixels = function(renderTarget, x, y, width, height, buffer, activeCubeFaceIndex) {
|
|
if (!(renderTarget && renderTarget.isWebGLRenderTarget)) {
|
|
console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");
|
|
return;
|
|
}
|
|
let framebuffer = properties.get(renderTarget).__webglFramebuffer;
|
|
if (renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== void 0) {
|
|
framebuffer = framebuffer[activeCubeFaceIndex];
|
|
}
|
|
if (framebuffer) {
|
|
state.bindFramebuffer(36160, framebuffer);
|
|
try {
|
|
const texture = renderTarget.texture;
|
|
const textureFormat = texture.format;
|
|
const textureType = texture.type;
|
|
if (textureFormat !== RGBAFormat && utils.convert(textureFormat) !== _gl.getParameter(35739)) {
|
|
console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");
|
|
return;
|
|
}
|
|
const halfFloatSupportedByExt = textureType === HalfFloatType && (extensions.has("EXT_color_buffer_half_float") || capabilities.isWebGL2 && extensions.has("EXT_color_buffer_float"));
|
|
if (textureType !== UnsignedByteType && utils.convert(textureType) !== _gl.getParameter(35738) && !(textureType === FloatType && (capabilities.isWebGL2 || extensions.has("OES_texture_float") || extensions.has("WEBGL_color_buffer_float"))) && !halfFloatSupportedByExt) {
|
|
console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");
|
|
return;
|
|
}
|
|
if (_gl.checkFramebufferStatus(36160) === 36053) {
|
|
if (x >= 0 && x <= renderTarget.width - width && (y >= 0 && y <= renderTarget.height - height)) {
|
|
_gl.readPixels(x, y, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer);
|
|
}
|
|
} else {
|
|
console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.");
|
|
}
|
|
} finally {
|
|
const framebuffer2 = _currentRenderTarget !== null ? properties.get(_currentRenderTarget).__webglFramebuffer : null;
|
|
state.bindFramebuffer(36160, framebuffer2);
|
|
}
|
|
}
|
|
};
|
|
this.copyFramebufferToTexture = function(position, texture, level = 0) {
|
|
const levelScale = Math.pow(2, -level);
|
|
const width = Math.floor(texture.image.width * levelScale);
|
|
const height = Math.floor(texture.image.height * levelScale);
|
|
let glFormat = utils.convert(texture.format);
|
|
if (capabilities.isWebGL2) {
|
|
if (glFormat === 6407)
|
|
glFormat = 32849;
|
|
if (glFormat === 6408)
|
|
glFormat = 32856;
|
|
}
|
|
textures.setTexture2D(texture, 0);
|
|
_gl.copyTexImage2D(3553, level, glFormat, position.x, position.y, width, height, 0);
|
|
state.unbindTexture();
|
|
};
|
|
this.copyTextureToTexture = function(position, srcTexture, dstTexture, level = 0) {
|
|
const width = srcTexture.image.width;
|
|
const height = srcTexture.image.height;
|
|
const glFormat = utils.convert(dstTexture.format);
|
|
const glType = utils.convert(dstTexture.type);
|
|
textures.setTexture2D(dstTexture, 0);
|
|
_gl.pixelStorei(37440, dstTexture.flipY);
|
|
_gl.pixelStorei(37441, dstTexture.premultiplyAlpha);
|
|
_gl.pixelStorei(3317, dstTexture.unpackAlignment);
|
|
if (srcTexture.isDataTexture) {
|
|
_gl.texSubImage2D(3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data);
|
|
} else {
|
|
if (srcTexture.isCompressedTexture) {
|
|
_gl.compressedTexSubImage2D(3553, level, position.x, position.y, srcTexture.mipmaps[0].width, srcTexture.mipmaps[0].height, glFormat, srcTexture.mipmaps[0].data);
|
|
} else {
|
|
_gl.texSubImage2D(3553, level, position.x, position.y, glFormat, glType, srcTexture.image);
|
|
}
|
|
}
|
|
if (level === 0 && dstTexture.generateMipmaps)
|
|
_gl.generateMipmap(3553);
|
|
state.unbindTexture();
|
|
};
|
|
this.copyTextureToTexture3D = function(sourceBox, position, srcTexture, dstTexture, level = 0) {
|
|
if (_this.isWebGL1Renderer) {
|
|
console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");
|
|
return;
|
|
}
|
|
const width = sourceBox.max.x - sourceBox.min.x + 1;
|
|
const height = sourceBox.max.y - sourceBox.min.y + 1;
|
|
const depth = sourceBox.max.z - sourceBox.min.z + 1;
|
|
const glFormat = utils.convert(dstTexture.format);
|
|
const glType = utils.convert(dstTexture.type);
|
|
let glTarget;
|
|
if (dstTexture.isDataTexture3D) {
|
|
textures.setTexture3D(dstTexture, 0);
|
|
glTarget = 32879;
|
|
} else if (dstTexture.isDataTexture2DArray) {
|
|
textures.setTexture2DArray(dstTexture, 0);
|
|
glTarget = 35866;
|
|
} else {
|
|
console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");
|
|
return;
|
|
}
|
|
_gl.pixelStorei(37440, dstTexture.flipY);
|
|
_gl.pixelStorei(37441, dstTexture.premultiplyAlpha);
|
|
_gl.pixelStorei(3317, dstTexture.unpackAlignment);
|
|
const unpackRowLen = _gl.getParameter(3314);
|
|
const unpackImageHeight = _gl.getParameter(32878);
|
|
const unpackSkipPixels = _gl.getParameter(3316);
|
|
const unpackSkipRows = _gl.getParameter(3315);
|
|
const unpackSkipImages = _gl.getParameter(32877);
|
|
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[0] : srcTexture.image;
|
|
_gl.pixelStorei(3314, image.width);
|
|
_gl.pixelStorei(32878, image.height);
|
|
_gl.pixelStorei(3316, sourceBox.min.x);
|
|
_gl.pixelStorei(3315, sourceBox.min.y);
|
|
_gl.pixelStorei(32877, sourceBox.min.z);
|
|
if (srcTexture.isDataTexture || srcTexture.isDataTexture3D) {
|
|
_gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data);
|
|
} else {
|
|
if (srcTexture.isCompressedTexture) {
|
|
console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.");
|
|
_gl.compressedTexSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data);
|
|
} else {
|
|
_gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image);
|
|
}
|
|
}
|
|
_gl.pixelStorei(3314, unpackRowLen);
|
|
_gl.pixelStorei(32878, unpackImageHeight);
|
|
_gl.pixelStorei(3316, unpackSkipPixels);
|
|
_gl.pixelStorei(3315, unpackSkipRows);
|
|
_gl.pixelStorei(32877, unpackSkipImages);
|
|
if (level === 0 && dstTexture.generateMipmaps)
|
|
_gl.generateMipmap(glTarget);
|
|
state.unbindTexture();
|
|
};
|
|
this.initTexture = function(texture) {
|
|
textures.setTexture2D(texture, 0);
|
|
state.unbindTexture();
|
|
};
|
|
this.resetState = function() {
|
|
_currentActiveCubeFace = 0;
|
|
_currentActiveMipmapLevel = 0;
|
|
_currentRenderTarget = null;
|
|
state.reset();
|
|
bindingStates.reset();
|
|
};
|
|
if (typeof __THREE_DEVTOOLS__ !== "undefined") {
|
|
__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { detail: this }));
|
|
}
|
|
}
|
|
var WebGL1Renderer = class extends WebGLRenderer {
|
|
};
|
|
WebGL1Renderer.prototype.isWebGL1Renderer = true;
|
|
var FogExp2 = class {
|
|
constructor(color, density = 25e-5) {
|
|
this.name = "";
|
|
this.color = new Color(color);
|
|
this.density = density;
|
|
}
|
|
clone() {
|
|
return new FogExp2(this.color, this.density);
|
|
}
|
|
toJSON() {
|
|
return {
|
|
type: "FogExp2",
|
|
color: this.color.getHex(),
|
|
density: this.density
|
|
};
|
|
}
|
|
};
|
|
FogExp2.prototype.isFogExp2 = true;
|
|
var Fog = class {
|
|
constructor(color, near = 1, far = 1e3) {
|
|
this.name = "";
|
|
this.color = new Color(color);
|
|
this.near = near;
|
|
this.far = far;
|
|
}
|
|
clone() {
|
|
return new Fog(this.color, this.near, this.far);
|
|
}
|
|
toJSON() {
|
|
return {
|
|
type: "Fog",
|
|
color: this.color.getHex(),
|
|
near: this.near,
|
|
far: this.far
|
|
};
|
|
}
|
|
};
|
|
Fog.prototype.isFog = true;
|
|
var Scene = class extends Object3D {
|
|
constructor() {
|
|
super();
|
|
this.type = "Scene";
|
|
this.background = null;
|
|
this.environment = null;
|
|
this.fog = null;
|
|
this.overrideMaterial = null;
|
|
this.autoUpdate = true;
|
|
if (typeof __THREE_DEVTOOLS__ !== "undefined") {
|
|
__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { detail: this }));
|
|
}
|
|
}
|
|
copy(source, recursive) {
|
|
super.copy(source, recursive);
|
|
if (source.background !== null)
|
|
this.background = source.background.clone();
|
|
if (source.environment !== null)
|
|
this.environment = source.environment.clone();
|
|
if (source.fog !== null)
|
|
this.fog = source.fog.clone();
|
|
if (source.overrideMaterial !== null)
|
|
this.overrideMaterial = source.overrideMaterial.clone();
|
|
this.autoUpdate = source.autoUpdate;
|
|
this.matrixAutoUpdate = source.matrixAutoUpdate;
|
|
return this;
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
if (this.fog !== null)
|
|
data.object.fog = this.fog.toJSON();
|
|
return data;
|
|
}
|
|
};
|
|
Scene.prototype.isScene = true;
|
|
var InterleavedBuffer = class {
|
|
constructor(array, stride) {
|
|
this.array = array;
|
|
this.stride = stride;
|
|
this.count = array !== void 0 ? array.length / stride : 0;
|
|
this.usage = StaticDrawUsage;
|
|
this.updateRange = { offset: 0, count: -1 };
|
|
this.version = 0;
|
|
this.uuid = generateUUID();
|
|
}
|
|
onUploadCallback() {
|
|
}
|
|
set needsUpdate(value) {
|
|
if (value === true)
|
|
this.version++;
|
|
}
|
|
setUsage(value) {
|
|
this.usage = value;
|
|
return this;
|
|
}
|
|
copy(source) {
|
|
this.array = new source.array.constructor(source.array);
|
|
this.count = source.count;
|
|
this.stride = source.stride;
|
|
this.usage = source.usage;
|
|
return this;
|
|
}
|
|
copyAt(index1, attribute, index2) {
|
|
index1 *= this.stride;
|
|
index2 *= attribute.stride;
|
|
for (let i = 0, l = this.stride; i < l; i++) {
|
|
this.array[index1 + i] = attribute.array[index2 + i];
|
|
}
|
|
return this;
|
|
}
|
|
set(value, offset = 0) {
|
|
this.array.set(value, offset);
|
|
return this;
|
|
}
|
|
clone(data) {
|
|
if (data.arrayBuffers === void 0) {
|
|
data.arrayBuffers = {};
|
|
}
|
|
if (this.array.buffer._uuid === void 0) {
|
|
this.array.buffer._uuid = generateUUID();
|
|
}
|
|
if (data.arrayBuffers[this.array.buffer._uuid] === void 0) {
|
|
data.arrayBuffers[this.array.buffer._uuid] = this.array.slice(0).buffer;
|
|
}
|
|
const array = new this.array.constructor(data.arrayBuffers[this.array.buffer._uuid]);
|
|
const ib = new this.constructor(array, this.stride);
|
|
ib.setUsage(this.usage);
|
|
return ib;
|
|
}
|
|
onUpload(callback) {
|
|
this.onUploadCallback = callback;
|
|
return this;
|
|
}
|
|
toJSON(data) {
|
|
if (data.arrayBuffers === void 0) {
|
|
data.arrayBuffers = {};
|
|
}
|
|
if (this.array.buffer._uuid === void 0) {
|
|
this.array.buffer._uuid = generateUUID();
|
|
}
|
|
if (data.arrayBuffers[this.array.buffer._uuid] === void 0) {
|
|
data.arrayBuffers[this.array.buffer._uuid] = Array.prototype.slice.call(new Uint32Array(this.array.buffer));
|
|
}
|
|
return {
|
|
uuid: this.uuid,
|
|
buffer: this.array.buffer._uuid,
|
|
type: this.array.constructor.name,
|
|
stride: this.stride
|
|
};
|
|
}
|
|
};
|
|
InterleavedBuffer.prototype.isInterleavedBuffer = true;
|
|
var _vector$6 = /* @__PURE__ */ new Vector3();
|
|
var InterleavedBufferAttribute = class {
|
|
constructor(interleavedBuffer, itemSize, offset, normalized = false) {
|
|
this.name = "";
|
|
this.data = interleavedBuffer;
|
|
this.itemSize = itemSize;
|
|
this.offset = offset;
|
|
this.normalized = normalized === true;
|
|
}
|
|
get count() {
|
|
return this.data.count;
|
|
}
|
|
get array() {
|
|
return this.data.array;
|
|
}
|
|
set needsUpdate(value) {
|
|
this.data.needsUpdate = value;
|
|
}
|
|
applyMatrix4(m) {
|
|
for (let i = 0, l = this.data.count; i < l; i++) {
|
|
_vector$6.x = this.getX(i);
|
|
_vector$6.y = this.getY(i);
|
|
_vector$6.z = this.getZ(i);
|
|
_vector$6.applyMatrix4(m);
|
|
this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
|
|
}
|
|
return this;
|
|
}
|
|
applyNormalMatrix(m) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$6.x = this.getX(i);
|
|
_vector$6.y = this.getY(i);
|
|
_vector$6.z = this.getZ(i);
|
|
_vector$6.applyNormalMatrix(m);
|
|
this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
|
|
}
|
|
return this;
|
|
}
|
|
transformDirection(m) {
|
|
for (let i = 0, l = this.count; i < l; i++) {
|
|
_vector$6.x = this.getX(i);
|
|
_vector$6.y = this.getY(i);
|
|
_vector$6.z = this.getZ(i);
|
|
_vector$6.transformDirection(m);
|
|
this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
|
|
}
|
|
return this;
|
|
}
|
|
setX(index, x) {
|
|
this.data.array[index * this.data.stride + this.offset] = x;
|
|
return this;
|
|
}
|
|
setY(index, y) {
|
|
this.data.array[index * this.data.stride + this.offset + 1] = y;
|
|
return this;
|
|
}
|
|
setZ(index, z) {
|
|
this.data.array[index * this.data.stride + this.offset + 2] = z;
|
|
return this;
|
|
}
|
|
setW(index, w2) {
|
|
this.data.array[index * this.data.stride + this.offset + 3] = w2;
|
|
return this;
|
|
}
|
|
getX(index) {
|
|
return this.data.array[index * this.data.stride + this.offset];
|
|
}
|
|
getY(index) {
|
|
return this.data.array[index * this.data.stride + this.offset + 1];
|
|
}
|
|
getZ(index) {
|
|
return this.data.array[index * this.data.stride + this.offset + 2];
|
|
}
|
|
getW(index) {
|
|
return this.data.array[index * this.data.stride + this.offset + 3];
|
|
}
|
|
setXY(index, x, y) {
|
|
index = index * this.data.stride + this.offset;
|
|
this.data.array[index + 0] = x;
|
|
this.data.array[index + 1] = y;
|
|
return this;
|
|
}
|
|
setXYZ(index, x, y, z) {
|
|
index = index * this.data.stride + this.offset;
|
|
this.data.array[index + 0] = x;
|
|
this.data.array[index + 1] = y;
|
|
this.data.array[index + 2] = z;
|
|
return this;
|
|
}
|
|
setXYZW(index, x, y, z, w2) {
|
|
index = index * this.data.stride + this.offset;
|
|
this.data.array[index + 0] = x;
|
|
this.data.array[index + 1] = y;
|
|
this.data.array[index + 2] = z;
|
|
this.data.array[index + 3] = w2;
|
|
return this;
|
|
}
|
|
clone(data) {
|
|
if (data === void 0) {
|
|
console.log("THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.");
|
|
const array = [];
|
|
for (let i = 0; i < this.count; i++) {
|
|
const index = i * this.data.stride + this.offset;
|
|
for (let j = 0; j < this.itemSize; j++) {
|
|
array.push(this.data.array[index + j]);
|
|
}
|
|
}
|
|
return new BufferAttribute(new this.array.constructor(array), this.itemSize, this.normalized);
|
|
} else {
|
|
if (data.interleavedBuffers === void 0) {
|
|
data.interleavedBuffers = {};
|
|
}
|
|
if (data.interleavedBuffers[this.data.uuid] === void 0) {
|
|
data.interleavedBuffers[this.data.uuid] = this.data.clone(data);
|
|
}
|
|
return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized);
|
|
}
|
|
}
|
|
toJSON(data) {
|
|
if (data === void 0) {
|
|
console.log("THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.");
|
|
const array = [];
|
|
for (let i = 0; i < this.count; i++) {
|
|
const index = i * this.data.stride + this.offset;
|
|
for (let j = 0; j < this.itemSize; j++) {
|
|
array.push(this.data.array[index + j]);
|
|
}
|
|
}
|
|
return {
|
|
itemSize: this.itemSize,
|
|
type: this.array.constructor.name,
|
|
array,
|
|
normalized: this.normalized
|
|
};
|
|
} else {
|
|
if (data.interleavedBuffers === void 0) {
|
|
data.interleavedBuffers = {};
|
|
}
|
|
if (data.interleavedBuffers[this.data.uuid] === void 0) {
|
|
data.interleavedBuffers[this.data.uuid] = this.data.toJSON(data);
|
|
}
|
|
return {
|
|
isInterleavedBufferAttribute: true,
|
|
itemSize: this.itemSize,
|
|
data: this.data.uuid,
|
|
offset: this.offset,
|
|
normalized: this.normalized
|
|
};
|
|
}
|
|
}
|
|
};
|
|
InterleavedBufferAttribute.prototype.isInterleavedBufferAttribute = true;
|
|
var SpriteMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "SpriteMaterial";
|
|
this.color = new Color(16777215);
|
|
this.map = null;
|
|
this.alphaMap = null;
|
|
this.rotation = 0;
|
|
this.sizeAttenuation = true;
|
|
this.transparent = true;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.map = source.map;
|
|
this.alphaMap = source.alphaMap;
|
|
this.rotation = source.rotation;
|
|
this.sizeAttenuation = source.sizeAttenuation;
|
|
return this;
|
|
}
|
|
};
|
|
SpriteMaterial.prototype.isSpriteMaterial = true;
|
|
var _geometry;
|
|
var _intersectPoint = /* @__PURE__ */ new Vector3();
|
|
var _worldScale = /* @__PURE__ */ new Vector3();
|
|
var _mvPosition = /* @__PURE__ */ new Vector3();
|
|
var _alignedPosition = /* @__PURE__ */ new Vector2();
|
|
var _rotatedPosition = /* @__PURE__ */ new Vector2();
|
|
var _viewWorldMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _vA = /* @__PURE__ */ new Vector3();
|
|
var _vB = /* @__PURE__ */ new Vector3();
|
|
var _vC = /* @__PURE__ */ new Vector3();
|
|
var _uvA = /* @__PURE__ */ new Vector2();
|
|
var _uvB = /* @__PURE__ */ new Vector2();
|
|
var _uvC = /* @__PURE__ */ new Vector2();
|
|
var Sprite = class extends Object3D {
|
|
constructor(material) {
|
|
super();
|
|
this.type = "Sprite";
|
|
if (_geometry === void 0) {
|
|
_geometry = new BufferGeometry();
|
|
const float32Array = new Float32Array([
|
|
-0.5,
|
|
-0.5,
|
|
0,
|
|
0,
|
|
0,
|
|
0.5,
|
|
-0.5,
|
|
0,
|
|
1,
|
|
0,
|
|
0.5,
|
|
0.5,
|
|
0,
|
|
1,
|
|
1,
|
|
-0.5,
|
|
0.5,
|
|
0,
|
|
0,
|
|
1
|
|
]);
|
|
const interleavedBuffer = new InterleavedBuffer(float32Array, 5);
|
|
_geometry.setIndex([0, 1, 2, 0, 2, 3]);
|
|
_geometry.setAttribute("position", new InterleavedBufferAttribute(interleavedBuffer, 3, 0, false));
|
|
_geometry.setAttribute("uv", new InterleavedBufferAttribute(interleavedBuffer, 2, 3, false));
|
|
}
|
|
this.geometry = _geometry;
|
|
this.material = material !== void 0 ? material : new SpriteMaterial();
|
|
this.center = new Vector2(0.5, 0.5);
|
|
}
|
|
raycast(raycaster, intersects2) {
|
|
if (raycaster.camera === null) {
|
|
console.error('THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.');
|
|
}
|
|
_worldScale.setFromMatrixScale(this.matrixWorld);
|
|
_viewWorldMatrix.copy(raycaster.camera.matrixWorld);
|
|
this.modelViewMatrix.multiplyMatrices(raycaster.camera.matrixWorldInverse, this.matrixWorld);
|
|
_mvPosition.setFromMatrixPosition(this.modelViewMatrix);
|
|
if (raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false) {
|
|
_worldScale.multiplyScalar(-_mvPosition.z);
|
|
}
|
|
const rotation = this.material.rotation;
|
|
let sin, cos;
|
|
if (rotation !== 0) {
|
|
cos = Math.cos(rotation);
|
|
sin = Math.sin(rotation);
|
|
}
|
|
const center = this.center;
|
|
transformVertex(_vA.set(-0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos);
|
|
transformVertex(_vB.set(0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos);
|
|
transformVertex(_vC.set(0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
|
|
_uvA.set(0, 0);
|
|
_uvB.set(1, 0);
|
|
_uvC.set(1, 1);
|
|
let intersect2 = raycaster.ray.intersectTriangle(_vA, _vB, _vC, false, _intersectPoint);
|
|
if (intersect2 === null) {
|
|
transformVertex(_vB.set(-0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
|
|
_uvB.set(0, 1);
|
|
intersect2 = raycaster.ray.intersectTriangle(_vA, _vC, _vB, false, _intersectPoint);
|
|
if (intersect2 === null) {
|
|
return;
|
|
}
|
|
}
|
|
const distance = raycaster.ray.origin.distanceTo(_intersectPoint);
|
|
if (distance < raycaster.near || distance > raycaster.far)
|
|
return;
|
|
intersects2.push({
|
|
distance,
|
|
point: _intersectPoint.clone(),
|
|
uv: Triangle.getUV(_intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2()),
|
|
face: null,
|
|
object: this
|
|
});
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
if (source.center !== void 0)
|
|
this.center.copy(source.center);
|
|
this.material = source.material;
|
|
return this;
|
|
}
|
|
};
|
|
Sprite.prototype.isSprite = true;
|
|
function transformVertex(vertexPosition, mvPosition, center, scale, sin, cos) {
|
|
_alignedPosition.subVectors(vertexPosition, center).addScalar(0.5).multiply(scale);
|
|
if (sin !== void 0) {
|
|
_rotatedPosition.x = cos * _alignedPosition.x - sin * _alignedPosition.y;
|
|
_rotatedPosition.y = sin * _alignedPosition.x + cos * _alignedPosition.y;
|
|
} else {
|
|
_rotatedPosition.copy(_alignedPosition);
|
|
}
|
|
vertexPosition.copy(mvPosition);
|
|
vertexPosition.x += _rotatedPosition.x;
|
|
vertexPosition.y += _rotatedPosition.y;
|
|
vertexPosition.applyMatrix4(_viewWorldMatrix);
|
|
}
|
|
var _basePosition = /* @__PURE__ */ new Vector3();
|
|
var _skinIndex = /* @__PURE__ */ new Vector4();
|
|
var _skinWeight = /* @__PURE__ */ new Vector4();
|
|
var _vector$5 = /* @__PURE__ */ new Vector3();
|
|
var _matrix = /* @__PURE__ */ new Matrix4();
|
|
var SkinnedMesh = class extends Mesh {
|
|
constructor(geometry, material) {
|
|
super(geometry, material);
|
|
this.type = "SkinnedMesh";
|
|
this.bindMode = "attached";
|
|
this.bindMatrix = new Matrix4();
|
|
this.bindMatrixInverse = new Matrix4();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.bindMode = source.bindMode;
|
|
this.bindMatrix.copy(source.bindMatrix);
|
|
this.bindMatrixInverse.copy(source.bindMatrixInverse);
|
|
this.skeleton = source.skeleton;
|
|
return this;
|
|
}
|
|
bind(skeleton, bindMatrix) {
|
|
this.skeleton = skeleton;
|
|
if (bindMatrix === void 0) {
|
|
this.updateMatrixWorld(true);
|
|
this.skeleton.calculateInverses();
|
|
bindMatrix = this.matrixWorld;
|
|
}
|
|
this.bindMatrix.copy(bindMatrix);
|
|
this.bindMatrixInverse.copy(bindMatrix).invert();
|
|
}
|
|
pose() {
|
|
this.skeleton.pose();
|
|
}
|
|
normalizeSkinWeights() {
|
|
const vector = new Vector4();
|
|
const skinWeight = this.geometry.attributes.skinWeight;
|
|
for (let i = 0, l = skinWeight.count; i < l; i++) {
|
|
vector.x = skinWeight.getX(i);
|
|
vector.y = skinWeight.getY(i);
|
|
vector.z = skinWeight.getZ(i);
|
|
vector.w = skinWeight.getW(i);
|
|
const scale = 1 / vector.manhattanLength();
|
|
if (scale !== Infinity) {
|
|
vector.multiplyScalar(scale);
|
|
} else {
|
|
vector.set(1, 0, 0, 0);
|
|
}
|
|
skinWeight.setXYZW(i, vector.x, vector.y, vector.z, vector.w);
|
|
}
|
|
}
|
|
updateMatrixWorld(force) {
|
|
super.updateMatrixWorld(force);
|
|
if (this.bindMode === "attached") {
|
|
this.bindMatrixInverse.copy(this.matrixWorld).invert();
|
|
} else if (this.bindMode === "detached") {
|
|
this.bindMatrixInverse.copy(this.bindMatrix).invert();
|
|
} else {
|
|
console.warn("THREE.SkinnedMesh: Unrecognized bindMode: " + this.bindMode);
|
|
}
|
|
}
|
|
boneTransform(index, target) {
|
|
const skeleton = this.skeleton;
|
|
const geometry = this.geometry;
|
|
_skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
|
|
_skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
|
|
_basePosition.fromBufferAttribute(geometry.attributes.position, index).applyMatrix4(this.bindMatrix);
|
|
target.set(0, 0, 0);
|
|
for (let i = 0; i < 4; i++) {
|
|
const weight = _skinWeight.getComponent(i);
|
|
if (weight !== 0) {
|
|
const boneIndex = _skinIndex.getComponent(i);
|
|
_matrix.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
|
|
target.addScaledVector(_vector$5.copy(_basePosition).applyMatrix4(_matrix), weight);
|
|
}
|
|
}
|
|
return target.applyMatrix4(this.bindMatrixInverse);
|
|
}
|
|
};
|
|
SkinnedMesh.prototype.isSkinnedMesh = true;
|
|
var Bone = class extends Object3D {
|
|
constructor() {
|
|
super();
|
|
this.type = "Bone";
|
|
}
|
|
};
|
|
Bone.prototype.isBone = true;
|
|
var DataTexture = class extends Texture {
|
|
constructor(data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding) {
|
|
super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
|
|
this.image = { data, width, height };
|
|
this.magFilter = magFilter;
|
|
this.minFilter = minFilter;
|
|
this.generateMipmaps = false;
|
|
this.flipY = false;
|
|
this.unpackAlignment = 1;
|
|
this.needsUpdate = true;
|
|
}
|
|
};
|
|
DataTexture.prototype.isDataTexture = true;
|
|
var InstancedBufferAttribute = class extends BufferAttribute {
|
|
constructor(array, itemSize, normalized, meshPerAttribute = 1) {
|
|
if (typeof normalized === "number") {
|
|
meshPerAttribute = normalized;
|
|
normalized = false;
|
|
console.error("THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.");
|
|
}
|
|
super(array, itemSize, normalized);
|
|
this.meshPerAttribute = meshPerAttribute;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.meshPerAttribute = source.meshPerAttribute;
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.meshPerAttribute = this.meshPerAttribute;
|
|
data.isInstancedBufferAttribute = true;
|
|
return data;
|
|
}
|
|
};
|
|
InstancedBufferAttribute.prototype.isInstancedBufferAttribute = true;
|
|
var _instanceLocalMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _instanceWorldMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _instanceIntersects = [];
|
|
var _mesh = /* @__PURE__ */ new Mesh();
|
|
var InstancedMesh = class extends Mesh {
|
|
constructor(geometry, material, count) {
|
|
super(geometry, material);
|
|
this.instanceMatrix = new InstancedBufferAttribute(new Float32Array(count * 16), 16);
|
|
this.instanceColor = null;
|
|
this.count = count;
|
|
this.frustumCulled = false;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.instanceMatrix.copy(source.instanceMatrix);
|
|
if (source.instanceColor !== null)
|
|
this.instanceColor = source.instanceColor.clone();
|
|
this.count = source.count;
|
|
return this;
|
|
}
|
|
getColorAt(index, color) {
|
|
color.fromArray(this.instanceColor.array, index * 3);
|
|
}
|
|
getMatrixAt(index, matrix) {
|
|
matrix.fromArray(this.instanceMatrix.array, index * 16);
|
|
}
|
|
raycast(raycaster, intersects2) {
|
|
const matrixWorld = this.matrixWorld;
|
|
const raycastTimes = this.count;
|
|
_mesh.geometry = this.geometry;
|
|
_mesh.material = this.material;
|
|
if (_mesh.material === void 0)
|
|
return;
|
|
for (let instanceId = 0; instanceId < raycastTimes; instanceId++) {
|
|
this.getMatrixAt(instanceId, _instanceLocalMatrix);
|
|
_instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix);
|
|
_mesh.matrixWorld = _instanceWorldMatrix;
|
|
_mesh.raycast(raycaster, _instanceIntersects);
|
|
for (let i = 0, l = _instanceIntersects.length; i < l; i++) {
|
|
const intersect2 = _instanceIntersects[i];
|
|
intersect2.instanceId = instanceId;
|
|
intersect2.object = this;
|
|
intersects2.push(intersect2);
|
|
}
|
|
_instanceIntersects.length = 0;
|
|
}
|
|
}
|
|
setColorAt(index, color) {
|
|
if (this.instanceColor === null) {
|
|
this.instanceColor = new InstancedBufferAttribute(new Float32Array(this.instanceMatrix.count * 3), 3);
|
|
}
|
|
color.toArray(this.instanceColor.array, index * 3);
|
|
}
|
|
setMatrixAt(index, matrix) {
|
|
matrix.toArray(this.instanceMatrix.array, index * 16);
|
|
}
|
|
updateMorphTargets() {
|
|
}
|
|
dispose() {
|
|
this.dispatchEvent({ type: "dispose" });
|
|
}
|
|
};
|
|
InstancedMesh.prototype.isInstancedMesh = true;
|
|
var LineBasicMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "LineBasicMaterial";
|
|
this.color = new Color(16777215);
|
|
this.linewidth = 1;
|
|
this.linecap = "round";
|
|
this.linejoin = "round";
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.linewidth = source.linewidth;
|
|
this.linecap = source.linecap;
|
|
this.linejoin = source.linejoin;
|
|
return this;
|
|
}
|
|
};
|
|
LineBasicMaterial.prototype.isLineBasicMaterial = true;
|
|
var _start$1 = /* @__PURE__ */ new Vector3();
|
|
var _end$1 = /* @__PURE__ */ new Vector3();
|
|
var _inverseMatrix$1 = /* @__PURE__ */ new Matrix4();
|
|
var _ray$1 = /* @__PURE__ */ new Ray();
|
|
var _sphere$1 = /* @__PURE__ */ new Sphere();
|
|
var Line = class extends Object3D {
|
|
constructor(geometry = new BufferGeometry(), material = new LineBasicMaterial()) {
|
|
super();
|
|
this.type = "Line";
|
|
this.geometry = geometry;
|
|
this.material = material;
|
|
this.updateMorphTargets();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.material = source.material;
|
|
this.geometry = source.geometry;
|
|
return this;
|
|
}
|
|
computeLineDistances() {
|
|
const geometry = this.geometry;
|
|
if (geometry.isBufferGeometry) {
|
|
if (geometry.index === null) {
|
|
const positionAttribute = geometry.attributes.position;
|
|
const lineDistances = [0];
|
|
for (let i = 1, l = positionAttribute.count; i < l; i++) {
|
|
_start$1.fromBufferAttribute(positionAttribute, i - 1);
|
|
_end$1.fromBufferAttribute(positionAttribute, i);
|
|
lineDistances[i] = lineDistances[i - 1];
|
|
lineDistances[i] += _start$1.distanceTo(_end$1);
|
|
}
|
|
geometry.setAttribute("lineDistance", new Float32BufferAttribute(lineDistances, 1));
|
|
} else {
|
|
console.warn("THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.");
|
|
}
|
|
} else if (geometry.isGeometry) {
|
|
console.error("THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
return this;
|
|
}
|
|
raycast(raycaster, intersects2) {
|
|
const geometry = this.geometry;
|
|
const matrixWorld = this.matrixWorld;
|
|
const threshold = raycaster.params.Line.threshold;
|
|
const drawRange = geometry.drawRange;
|
|
if (geometry.boundingSphere === null)
|
|
geometry.computeBoundingSphere();
|
|
_sphere$1.copy(geometry.boundingSphere);
|
|
_sphere$1.applyMatrix4(matrixWorld);
|
|
_sphere$1.radius += threshold;
|
|
if (raycaster.ray.intersectsSphere(_sphere$1) === false)
|
|
return;
|
|
_inverseMatrix$1.copy(matrixWorld).invert();
|
|
_ray$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$1);
|
|
const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
|
|
const localThresholdSq = localThreshold * localThreshold;
|
|
const vStart = new Vector3();
|
|
const vEnd = new Vector3();
|
|
const interSegment = new Vector3();
|
|
const interRay = new Vector3();
|
|
const step = this.isLineSegments ? 2 : 1;
|
|
if (geometry.isBufferGeometry) {
|
|
const index = geometry.index;
|
|
const attributes = geometry.attributes;
|
|
const positionAttribute = attributes.position;
|
|
if (index !== null) {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(index.count, drawRange.start + drawRange.count);
|
|
for (let i = start, l = end - 1; i < l; i += step) {
|
|
const a2 = index.getX(i);
|
|
const b2 = index.getX(i + 1);
|
|
vStart.fromBufferAttribute(positionAttribute, a2);
|
|
vEnd.fromBufferAttribute(positionAttribute, b2);
|
|
const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
|
|
if (distSq > localThresholdSq)
|
|
continue;
|
|
interRay.applyMatrix4(this.matrixWorld);
|
|
const distance = raycaster.ray.origin.distanceTo(interRay);
|
|
if (distance < raycaster.near || distance > raycaster.far)
|
|
continue;
|
|
intersects2.push({
|
|
distance,
|
|
point: interSegment.clone().applyMatrix4(this.matrixWorld),
|
|
index: i,
|
|
face: null,
|
|
faceIndex: null,
|
|
object: this
|
|
});
|
|
}
|
|
} else {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count);
|
|
for (let i = start, l = end - 1; i < l; i += step) {
|
|
vStart.fromBufferAttribute(positionAttribute, i);
|
|
vEnd.fromBufferAttribute(positionAttribute, i + 1);
|
|
const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
|
|
if (distSq > localThresholdSq)
|
|
continue;
|
|
interRay.applyMatrix4(this.matrixWorld);
|
|
const distance = raycaster.ray.origin.distanceTo(interRay);
|
|
if (distance < raycaster.near || distance > raycaster.far)
|
|
continue;
|
|
intersects2.push({
|
|
distance,
|
|
point: interSegment.clone().applyMatrix4(this.matrixWorld),
|
|
index: i,
|
|
face: null,
|
|
faceIndex: null,
|
|
object: this
|
|
});
|
|
}
|
|
}
|
|
} else if (geometry.isGeometry) {
|
|
console.error("THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
updateMorphTargets() {
|
|
const geometry = this.geometry;
|
|
if (geometry.isBufferGeometry) {
|
|
const morphAttributes = geometry.morphAttributes;
|
|
const keys = Object.keys(morphAttributes);
|
|
if (keys.length > 0) {
|
|
const morphAttribute = morphAttributes[keys[0]];
|
|
if (morphAttribute !== void 0) {
|
|
this.morphTargetInfluences = [];
|
|
this.morphTargetDictionary = {};
|
|
for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
|
|
const name = morphAttribute[m].name || String(m);
|
|
this.morphTargetInfluences.push(0);
|
|
this.morphTargetDictionary[name] = m;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const morphTargets = geometry.morphTargets;
|
|
if (morphTargets !== void 0 && morphTargets.length > 0) {
|
|
console.error("THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Line.prototype.isLine = true;
|
|
var _start = /* @__PURE__ */ new Vector3();
|
|
var _end = /* @__PURE__ */ new Vector3();
|
|
var LineSegments = class extends Line {
|
|
constructor(geometry, material) {
|
|
super(geometry, material);
|
|
this.type = "LineSegments";
|
|
}
|
|
computeLineDistances() {
|
|
const geometry = this.geometry;
|
|
if (geometry.isBufferGeometry) {
|
|
if (geometry.index === null) {
|
|
const positionAttribute = geometry.attributes.position;
|
|
const lineDistances = [];
|
|
for (let i = 0, l = positionAttribute.count; i < l; i += 2) {
|
|
_start.fromBufferAttribute(positionAttribute, i);
|
|
_end.fromBufferAttribute(positionAttribute, i + 1);
|
|
lineDistances[i] = i === 0 ? 0 : lineDistances[i - 1];
|
|
lineDistances[i + 1] = lineDistances[i] + _start.distanceTo(_end);
|
|
}
|
|
geometry.setAttribute("lineDistance", new Float32BufferAttribute(lineDistances, 1));
|
|
} else {
|
|
console.warn("THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.");
|
|
}
|
|
} else if (geometry.isGeometry) {
|
|
console.error("THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
LineSegments.prototype.isLineSegments = true;
|
|
var LineLoop = class extends Line {
|
|
constructor(geometry, material) {
|
|
super(geometry, material);
|
|
this.type = "LineLoop";
|
|
}
|
|
};
|
|
LineLoop.prototype.isLineLoop = true;
|
|
var PointsMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "PointsMaterial";
|
|
this.color = new Color(16777215);
|
|
this.map = null;
|
|
this.alphaMap = null;
|
|
this.size = 1;
|
|
this.sizeAttenuation = true;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.map = source.map;
|
|
this.alphaMap = source.alphaMap;
|
|
this.size = source.size;
|
|
this.sizeAttenuation = source.sizeAttenuation;
|
|
return this;
|
|
}
|
|
};
|
|
PointsMaterial.prototype.isPointsMaterial = true;
|
|
var _inverseMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _ray = /* @__PURE__ */ new Ray();
|
|
var _sphere = /* @__PURE__ */ new Sphere();
|
|
var _position$2 = /* @__PURE__ */ new Vector3();
|
|
var Points = class extends Object3D {
|
|
constructor(geometry = new BufferGeometry(), material = new PointsMaterial()) {
|
|
super();
|
|
this.type = "Points";
|
|
this.geometry = geometry;
|
|
this.material = material;
|
|
this.updateMorphTargets();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.material = source.material;
|
|
this.geometry = source.geometry;
|
|
return this;
|
|
}
|
|
raycast(raycaster, intersects2) {
|
|
const geometry = this.geometry;
|
|
const matrixWorld = this.matrixWorld;
|
|
const threshold = raycaster.params.Points.threshold;
|
|
const drawRange = geometry.drawRange;
|
|
if (geometry.boundingSphere === null)
|
|
geometry.computeBoundingSphere();
|
|
_sphere.copy(geometry.boundingSphere);
|
|
_sphere.applyMatrix4(matrixWorld);
|
|
_sphere.radius += threshold;
|
|
if (raycaster.ray.intersectsSphere(_sphere) === false)
|
|
return;
|
|
_inverseMatrix.copy(matrixWorld).invert();
|
|
_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix);
|
|
const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
|
|
const localThresholdSq = localThreshold * localThreshold;
|
|
if (geometry.isBufferGeometry) {
|
|
const index = geometry.index;
|
|
const attributes = geometry.attributes;
|
|
const positionAttribute = attributes.position;
|
|
if (index !== null) {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(index.count, drawRange.start + drawRange.count);
|
|
for (let i = start, il = end; i < il; i++) {
|
|
const a2 = index.getX(i);
|
|
_position$2.fromBufferAttribute(positionAttribute, a2);
|
|
testPoint(_position$2, a2, localThresholdSq, matrixWorld, raycaster, intersects2, this);
|
|
}
|
|
} else {
|
|
const start = Math.max(0, drawRange.start);
|
|
const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count);
|
|
for (let i = start, l = end; i < l; i++) {
|
|
_position$2.fromBufferAttribute(positionAttribute, i);
|
|
testPoint(_position$2, i, localThresholdSq, matrixWorld, raycaster, intersects2, this);
|
|
}
|
|
}
|
|
} else {
|
|
console.error("THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
updateMorphTargets() {
|
|
const geometry = this.geometry;
|
|
if (geometry.isBufferGeometry) {
|
|
const morphAttributes = geometry.morphAttributes;
|
|
const keys = Object.keys(morphAttributes);
|
|
if (keys.length > 0) {
|
|
const morphAttribute = morphAttributes[keys[0]];
|
|
if (morphAttribute !== void 0) {
|
|
this.morphTargetInfluences = [];
|
|
this.morphTargetDictionary = {};
|
|
for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
|
|
const name = morphAttribute[m].name || String(m);
|
|
this.morphTargetInfluences.push(0);
|
|
this.morphTargetDictionary[name] = m;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const morphTargets = geometry.morphTargets;
|
|
if (morphTargets !== void 0 && morphTargets.length > 0) {
|
|
console.error("THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Points.prototype.isPoints = true;
|
|
function testPoint(point, index, localThresholdSq, matrixWorld, raycaster, intersects2, object) {
|
|
const rayPointDistanceSq = _ray.distanceSqToPoint(point);
|
|
if (rayPointDistanceSq < localThresholdSq) {
|
|
const intersectPoint2 = new Vector3();
|
|
_ray.closestPointToPoint(point, intersectPoint2);
|
|
intersectPoint2.applyMatrix4(matrixWorld);
|
|
const distance = raycaster.ray.origin.distanceTo(intersectPoint2);
|
|
if (distance < raycaster.near || distance > raycaster.far)
|
|
return;
|
|
intersects2.push({
|
|
distance,
|
|
distanceToRay: Math.sqrt(rayPointDistanceSq),
|
|
point: intersectPoint2,
|
|
index,
|
|
face: null,
|
|
object
|
|
});
|
|
}
|
|
}
|
|
var VideoTexture = class extends Texture {
|
|
constructor(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
|
|
super(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
|
|
this.format = format !== void 0 ? format : RGBFormat;
|
|
this.minFilter = minFilter !== void 0 ? minFilter : LinearFilter;
|
|
this.magFilter = magFilter !== void 0 ? magFilter : LinearFilter;
|
|
this.generateMipmaps = false;
|
|
const scope = this;
|
|
function updateVideo() {
|
|
scope.needsUpdate = true;
|
|
video.requestVideoFrameCallback(updateVideo);
|
|
}
|
|
if ("requestVideoFrameCallback" in video) {
|
|
video.requestVideoFrameCallback(updateVideo);
|
|
}
|
|
}
|
|
clone() {
|
|
return new this.constructor(this.image).copy(this);
|
|
}
|
|
update() {
|
|
const video = this.image;
|
|
const hasVideoFrameCallback = "requestVideoFrameCallback" in video;
|
|
if (hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA) {
|
|
this.needsUpdate = true;
|
|
}
|
|
}
|
|
};
|
|
VideoTexture.prototype.isVideoTexture = true;
|
|
var CompressedTexture = class extends Texture {
|
|
constructor(mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
|
|
super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
|
|
this.image = { width, height };
|
|
this.mipmaps = mipmaps;
|
|
this.flipY = false;
|
|
this.generateMipmaps = false;
|
|
}
|
|
};
|
|
CompressedTexture.prototype.isCompressedTexture = true;
|
|
var CanvasTexture = class extends Texture {
|
|
constructor(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
|
|
super(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
|
|
this.needsUpdate = true;
|
|
}
|
|
};
|
|
CanvasTexture.prototype.isCanvasTexture = true;
|
|
var DepthTexture = class extends Texture {
|
|
constructor(width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format) {
|
|
format = format !== void 0 ? format : DepthFormat;
|
|
if (format !== DepthFormat && format !== DepthStencilFormat) {
|
|
throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");
|
|
}
|
|
if (type === void 0 && format === DepthFormat)
|
|
type = UnsignedShortType;
|
|
if (type === void 0 && format === DepthStencilFormat)
|
|
type = UnsignedInt248Type;
|
|
super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
|
|
this.image = { width, height };
|
|
this.magFilter = magFilter !== void 0 ? magFilter : NearestFilter;
|
|
this.minFilter = minFilter !== void 0 ? minFilter : NearestFilter;
|
|
this.flipY = false;
|
|
this.generateMipmaps = false;
|
|
}
|
|
};
|
|
DepthTexture.prototype.isDepthTexture = true;
|
|
var _v0 = new Vector3();
|
|
var _v1$1 = new Vector3();
|
|
var _normal = new Vector3();
|
|
var _triangle = new Triangle();
|
|
var Curve = class {
|
|
constructor() {
|
|
this.type = "Curve";
|
|
this.arcLengthDivisions = 200;
|
|
}
|
|
getPoint() {
|
|
console.warn("THREE.Curve: .getPoint() not implemented.");
|
|
return null;
|
|
}
|
|
getPointAt(u, optionalTarget) {
|
|
const t = this.getUtoTmapping(u);
|
|
return this.getPoint(t, optionalTarget);
|
|
}
|
|
getPoints(divisions = 5) {
|
|
const points = [];
|
|
for (let d = 0; d <= divisions; d++) {
|
|
points.push(this.getPoint(d / divisions));
|
|
}
|
|
return points;
|
|
}
|
|
getSpacedPoints(divisions = 5) {
|
|
const points = [];
|
|
for (let d = 0; d <= divisions; d++) {
|
|
points.push(this.getPointAt(d / divisions));
|
|
}
|
|
return points;
|
|
}
|
|
getLength() {
|
|
const lengths = this.getLengths();
|
|
return lengths[lengths.length - 1];
|
|
}
|
|
getLengths(divisions = this.arcLengthDivisions) {
|
|
if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) {
|
|
return this.cacheArcLengths;
|
|
}
|
|
this.needsUpdate = false;
|
|
const cache = [];
|
|
let current, last = this.getPoint(0);
|
|
let sum = 0;
|
|
cache.push(0);
|
|
for (let p2 = 1; p2 <= divisions; p2++) {
|
|
current = this.getPoint(p2 / divisions);
|
|
sum += current.distanceTo(last);
|
|
cache.push(sum);
|
|
last = current;
|
|
}
|
|
this.cacheArcLengths = cache;
|
|
return cache;
|
|
}
|
|
updateArcLengths() {
|
|
this.needsUpdate = true;
|
|
this.getLengths();
|
|
}
|
|
getUtoTmapping(u, distance) {
|
|
const arcLengths = this.getLengths();
|
|
let i = 0;
|
|
const il = arcLengths.length;
|
|
let targetArcLength;
|
|
if (distance) {
|
|
targetArcLength = distance;
|
|
} else {
|
|
targetArcLength = u * arcLengths[il - 1];
|
|
}
|
|
let low = 0, high = il - 1, comparison;
|
|
while (low <= high) {
|
|
i = Math.floor(low + (high - low) / 2);
|
|
comparison = arcLengths[i] - targetArcLength;
|
|
if (comparison < 0) {
|
|
low = i + 1;
|
|
} else if (comparison > 0) {
|
|
high = i - 1;
|
|
} else {
|
|
high = i;
|
|
break;
|
|
}
|
|
}
|
|
i = high;
|
|
if (arcLengths[i] === targetArcLength) {
|
|
return i / (il - 1);
|
|
}
|
|
const lengthBefore = arcLengths[i];
|
|
const lengthAfter = arcLengths[i + 1];
|
|
const segmentLength = lengthAfter - lengthBefore;
|
|
const segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
|
|
const t = (i + segmentFraction) / (il - 1);
|
|
return t;
|
|
}
|
|
getTangent(t, optionalTarget) {
|
|
const delta = 1e-4;
|
|
let t1 = t - delta;
|
|
let t2 = t + delta;
|
|
if (t1 < 0)
|
|
t1 = 0;
|
|
if (t2 > 1)
|
|
t2 = 1;
|
|
const pt1 = this.getPoint(t1);
|
|
const pt2 = this.getPoint(t2);
|
|
const tangent = optionalTarget || (pt1.isVector2 ? new Vector2() : new Vector3());
|
|
tangent.copy(pt2).sub(pt1).normalize();
|
|
return tangent;
|
|
}
|
|
getTangentAt(u, optionalTarget) {
|
|
const t = this.getUtoTmapping(u);
|
|
return this.getTangent(t, optionalTarget);
|
|
}
|
|
computeFrenetFrames(segments, closed) {
|
|
const normal = new Vector3();
|
|
const tangents = [];
|
|
const normals = [];
|
|
const binormals = [];
|
|
const vec = new Vector3();
|
|
const mat = new Matrix4();
|
|
for (let i = 0; i <= segments; i++) {
|
|
const u = i / segments;
|
|
tangents[i] = this.getTangentAt(u, new Vector3());
|
|
tangents[i].normalize();
|
|
}
|
|
normals[0] = new Vector3();
|
|
binormals[0] = new Vector3();
|
|
let min = Number.MAX_VALUE;
|
|
const tx = Math.abs(tangents[0].x);
|
|
const ty = Math.abs(tangents[0].y);
|
|
const tz = Math.abs(tangents[0].z);
|
|
if (tx <= min) {
|
|
min = tx;
|
|
normal.set(1, 0, 0);
|
|
}
|
|
if (ty <= min) {
|
|
min = ty;
|
|
normal.set(0, 1, 0);
|
|
}
|
|
if (tz <= min) {
|
|
normal.set(0, 0, 1);
|
|
}
|
|
vec.crossVectors(tangents[0], normal).normalize();
|
|
normals[0].crossVectors(tangents[0], vec);
|
|
binormals[0].crossVectors(tangents[0], normals[0]);
|
|
for (let i = 1; i <= segments; i++) {
|
|
normals[i] = normals[i - 1].clone();
|
|
binormals[i] = binormals[i - 1].clone();
|
|
vec.crossVectors(tangents[i - 1], tangents[i]);
|
|
if (vec.length() > Number.EPSILON) {
|
|
vec.normalize();
|
|
const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), -1, 1));
|
|
normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
|
|
}
|
|
binormals[i].crossVectors(tangents[i], normals[i]);
|
|
}
|
|
if (closed === true) {
|
|
let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1));
|
|
theta /= segments;
|
|
if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
|
|
theta = -theta;
|
|
}
|
|
for (let i = 1; i <= segments; i++) {
|
|
normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
|
|
binormals[i].crossVectors(tangents[i], normals[i]);
|
|
}
|
|
}
|
|
return {
|
|
tangents,
|
|
normals,
|
|
binormals
|
|
};
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(source) {
|
|
this.arcLengthDivisions = source.arcLengthDivisions;
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = {
|
|
metadata: {
|
|
version: 4.5,
|
|
type: "Curve",
|
|
generator: "Curve.toJSON"
|
|
}
|
|
};
|
|
data.arcLengthDivisions = this.arcLengthDivisions;
|
|
data.type = this.type;
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
this.arcLengthDivisions = json.arcLengthDivisions;
|
|
return this;
|
|
}
|
|
};
|
|
var EllipseCurve = class extends Curve {
|
|
constructor(aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0) {
|
|
super();
|
|
this.type = "EllipseCurve";
|
|
this.aX = aX;
|
|
this.aY = aY;
|
|
this.xRadius = xRadius;
|
|
this.yRadius = yRadius;
|
|
this.aStartAngle = aStartAngle;
|
|
this.aEndAngle = aEndAngle;
|
|
this.aClockwise = aClockwise;
|
|
this.aRotation = aRotation;
|
|
}
|
|
getPoint(t, optionalTarget) {
|
|
const point = optionalTarget || new Vector2();
|
|
const twoPi = Math.PI * 2;
|
|
let deltaAngle = this.aEndAngle - this.aStartAngle;
|
|
const samePoints = Math.abs(deltaAngle) < Number.EPSILON;
|
|
while (deltaAngle < 0)
|
|
deltaAngle += twoPi;
|
|
while (deltaAngle > twoPi)
|
|
deltaAngle -= twoPi;
|
|
if (deltaAngle < Number.EPSILON) {
|
|
if (samePoints) {
|
|
deltaAngle = 0;
|
|
} else {
|
|
deltaAngle = twoPi;
|
|
}
|
|
}
|
|
if (this.aClockwise === true && !samePoints) {
|
|
if (deltaAngle === twoPi) {
|
|
deltaAngle = -twoPi;
|
|
} else {
|
|
deltaAngle = deltaAngle - twoPi;
|
|
}
|
|
}
|
|
const angle = this.aStartAngle + t * deltaAngle;
|
|
let x = this.aX + this.xRadius * Math.cos(angle);
|
|
let y = this.aY + this.yRadius * Math.sin(angle);
|
|
if (this.aRotation !== 0) {
|
|
const cos = Math.cos(this.aRotation);
|
|
const sin = Math.sin(this.aRotation);
|
|
const tx = x - this.aX;
|
|
const ty = y - this.aY;
|
|
x = tx * cos - ty * sin + this.aX;
|
|
y = tx * sin + ty * cos + this.aY;
|
|
}
|
|
return point.set(x, y);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.aX = source.aX;
|
|
this.aY = source.aY;
|
|
this.xRadius = source.xRadius;
|
|
this.yRadius = source.yRadius;
|
|
this.aStartAngle = source.aStartAngle;
|
|
this.aEndAngle = source.aEndAngle;
|
|
this.aClockwise = source.aClockwise;
|
|
this.aRotation = source.aRotation;
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.aX = this.aX;
|
|
data.aY = this.aY;
|
|
data.xRadius = this.xRadius;
|
|
data.yRadius = this.yRadius;
|
|
data.aStartAngle = this.aStartAngle;
|
|
data.aEndAngle = this.aEndAngle;
|
|
data.aClockwise = this.aClockwise;
|
|
data.aRotation = this.aRotation;
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.aX = json.aX;
|
|
this.aY = json.aY;
|
|
this.xRadius = json.xRadius;
|
|
this.yRadius = json.yRadius;
|
|
this.aStartAngle = json.aStartAngle;
|
|
this.aEndAngle = json.aEndAngle;
|
|
this.aClockwise = json.aClockwise;
|
|
this.aRotation = json.aRotation;
|
|
return this;
|
|
}
|
|
};
|
|
EllipseCurve.prototype.isEllipseCurve = true;
|
|
var ArcCurve = class extends EllipseCurve {
|
|
constructor(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
|
|
super(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
|
|
this.type = "ArcCurve";
|
|
}
|
|
};
|
|
ArcCurve.prototype.isArcCurve = true;
|
|
function CubicPoly() {
|
|
let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
|
|
function init(x0, x1, t0, t1) {
|
|
c0 = x0;
|
|
c1 = t0;
|
|
c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1;
|
|
c3 = 2 * x0 - 2 * x1 + t0 + t1;
|
|
}
|
|
return {
|
|
initCatmullRom: function(x0, x1, x2, x3, tension) {
|
|
init(x1, x2, tension * (x2 - x0), tension * (x3 - x1));
|
|
},
|
|
initNonuniformCatmullRom: function(x0, x1, x2, x3, dt0, dt1, dt2) {
|
|
let t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1;
|
|
let t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2;
|
|
t1 *= dt1;
|
|
t2 *= dt1;
|
|
init(x1, x2, t1, t2);
|
|
},
|
|
calc: function(t) {
|
|
const t2 = t * t;
|
|
const t3 = t2 * t;
|
|
return c0 + c1 * t + c2 * t2 + c3 * t3;
|
|
}
|
|
};
|
|
}
|
|
var tmp = new Vector3();
|
|
var px = new CubicPoly();
|
|
var py = new CubicPoly();
|
|
var pz = new CubicPoly();
|
|
var CatmullRomCurve3 = class extends Curve {
|
|
constructor(points = [], closed = false, curveType = "centripetal", tension = 0.5) {
|
|
super();
|
|
this.type = "CatmullRomCurve3";
|
|
this.points = points;
|
|
this.closed = closed;
|
|
this.curveType = curveType;
|
|
this.tension = tension;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
const point = optionalTarget;
|
|
const points = this.points;
|
|
const l = points.length;
|
|
const p2 = (l - (this.closed ? 0 : 1)) * t;
|
|
let intPoint = Math.floor(p2);
|
|
let weight = p2 - intPoint;
|
|
if (this.closed) {
|
|
intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / l) + 1) * l;
|
|
} else if (weight === 0 && intPoint === l - 1) {
|
|
intPoint = l - 2;
|
|
weight = 1;
|
|
}
|
|
let p0, p3;
|
|
if (this.closed || intPoint > 0) {
|
|
p0 = points[(intPoint - 1) % l];
|
|
} else {
|
|
tmp.subVectors(points[0], points[1]).add(points[0]);
|
|
p0 = tmp;
|
|
}
|
|
const p1 = points[intPoint % l];
|
|
const p22 = points[(intPoint + 1) % l];
|
|
if (this.closed || intPoint + 2 < l) {
|
|
p3 = points[(intPoint + 2) % l];
|
|
} else {
|
|
tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1]);
|
|
p3 = tmp;
|
|
}
|
|
if (this.curveType === "centripetal" || this.curveType === "chordal") {
|
|
const pow = this.curveType === "chordal" ? 0.5 : 0.25;
|
|
let dt0 = Math.pow(p0.distanceToSquared(p1), pow);
|
|
let dt1 = Math.pow(p1.distanceToSquared(p22), pow);
|
|
let dt2 = Math.pow(p22.distanceToSquared(p3), pow);
|
|
if (dt1 < 1e-4)
|
|
dt1 = 1;
|
|
if (dt0 < 1e-4)
|
|
dt0 = dt1;
|
|
if (dt2 < 1e-4)
|
|
dt2 = dt1;
|
|
px.initNonuniformCatmullRom(p0.x, p1.x, p22.x, p3.x, dt0, dt1, dt2);
|
|
py.initNonuniformCatmullRom(p0.y, p1.y, p22.y, p3.y, dt0, dt1, dt2);
|
|
pz.initNonuniformCatmullRom(p0.z, p1.z, p22.z, p3.z, dt0, dt1, dt2);
|
|
} else if (this.curveType === "catmullrom") {
|
|
px.initCatmullRom(p0.x, p1.x, p22.x, p3.x, this.tension);
|
|
py.initCatmullRom(p0.y, p1.y, p22.y, p3.y, this.tension);
|
|
pz.initCatmullRom(p0.z, p1.z, p22.z, p3.z, this.tension);
|
|
}
|
|
point.set(px.calc(weight), py.calc(weight), pz.calc(weight));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.points = [];
|
|
for (let i = 0, l = source.points.length; i < l; i++) {
|
|
const point = source.points[i];
|
|
this.points.push(point.clone());
|
|
}
|
|
this.closed = source.closed;
|
|
this.curveType = source.curveType;
|
|
this.tension = source.tension;
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.points = [];
|
|
for (let i = 0, l = this.points.length; i < l; i++) {
|
|
const point = this.points[i];
|
|
data.points.push(point.toArray());
|
|
}
|
|
data.closed = this.closed;
|
|
data.curveType = this.curveType;
|
|
data.tension = this.tension;
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.points = [];
|
|
for (let i = 0, l = json.points.length; i < l; i++) {
|
|
const point = json.points[i];
|
|
this.points.push(new Vector3().fromArray(point));
|
|
}
|
|
this.closed = json.closed;
|
|
this.curveType = json.curveType;
|
|
this.tension = json.tension;
|
|
return this;
|
|
}
|
|
};
|
|
CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
|
|
function CatmullRom(t, p0, p1, p2, p3) {
|
|
const v02 = (p2 - p0) * 0.5;
|
|
const v12 = (p3 - p1) * 0.5;
|
|
const t2 = t * t;
|
|
const t3 = t * t2;
|
|
return (2 * p1 - 2 * p2 + v02 + v12) * t3 + (-3 * p1 + 3 * p2 - 2 * v02 - v12) * t2 + v02 * t + p1;
|
|
}
|
|
function QuadraticBezierP0(t, p2) {
|
|
const k = 1 - t;
|
|
return k * k * p2;
|
|
}
|
|
function QuadraticBezierP1(t, p2) {
|
|
return 2 * (1 - t) * t * p2;
|
|
}
|
|
function QuadraticBezierP2(t, p2) {
|
|
return t * t * p2;
|
|
}
|
|
function QuadraticBezier(t, p0, p1, p2) {
|
|
return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) + QuadraticBezierP2(t, p2);
|
|
}
|
|
function CubicBezierP0(t, p2) {
|
|
const k = 1 - t;
|
|
return k * k * k * p2;
|
|
}
|
|
function CubicBezierP1(t, p2) {
|
|
const k = 1 - t;
|
|
return 3 * k * k * t * p2;
|
|
}
|
|
function CubicBezierP2(t, p2) {
|
|
return 3 * (1 - t) * t * t * p2;
|
|
}
|
|
function CubicBezierP3(t, p2) {
|
|
return t * t * t * p2;
|
|
}
|
|
function CubicBezier(t, p0, p1, p2, p3) {
|
|
return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) + CubicBezierP3(t, p3);
|
|
}
|
|
var CubicBezierCurve = class extends Curve {
|
|
constructor(v02 = new Vector2(), v12 = new Vector2(), v22 = new Vector2(), v3 = new Vector2()) {
|
|
super();
|
|
this.type = "CubicBezierCurve";
|
|
this.v0 = v02;
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
this.v3 = v3;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
const point = optionalTarget;
|
|
const v02 = this.v0, v12 = this.v1, v22 = this.v2, v3 = this.v3;
|
|
point.set(CubicBezier(t, v02.x, v12.x, v22.x, v3.x), CubicBezier(t, v02.y, v12.y, v22.y, v3.y));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v0.copy(source.v0);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
this.v3.copy(source.v3);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v0 = this.v0.toArray();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
data.v3 = this.v3.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v0.fromArray(json.v0);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
this.v3.fromArray(json.v3);
|
|
return this;
|
|
}
|
|
};
|
|
CubicBezierCurve.prototype.isCubicBezierCurve = true;
|
|
var CubicBezierCurve3 = class extends Curve {
|
|
constructor(v02 = new Vector3(), v12 = new Vector3(), v22 = new Vector3(), v3 = new Vector3()) {
|
|
super();
|
|
this.type = "CubicBezierCurve3";
|
|
this.v0 = v02;
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
this.v3 = v3;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
const point = optionalTarget;
|
|
const v02 = this.v0, v12 = this.v1, v22 = this.v2, v3 = this.v3;
|
|
point.set(CubicBezier(t, v02.x, v12.x, v22.x, v3.x), CubicBezier(t, v02.y, v12.y, v22.y, v3.y), CubicBezier(t, v02.z, v12.z, v22.z, v3.z));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v0.copy(source.v0);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
this.v3.copy(source.v3);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v0 = this.v0.toArray();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
data.v3 = this.v3.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v0.fromArray(json.v0);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
this.v3.fromArray(json.v3);
|
|
return this;
|
|
}
|
|
};
|
|
CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
|
|
var LineCurve = class extends Curve {
|
|
constructor(v12 = new Vector2(), v22 = new Vector2()) {
|
|
super();
|
|
this.type = "LineCurve";
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
const point = optionalTarget;
|
|
if (t === 1) {
|
|
point.copy(this.v2);
|
|
} else {
|
|
point.copy(this.v2).sub(this.v1);
|
|
point.multiplyScalar(t).add(this.v1);
|
|
}
|
|
return point;
|
|
}
|
|
getPointAt(u, optionalTarget) {
|
|
return this.getPoint(u, optionalTarget);
|
|
}
|
|
getTangent(t, optionalTarget) {
|
|
const tangent = optionalTarget || new Vector2();
|
|
tangent.copy(this.v2).sub(this.v1).normalize();
|
|
return tangent;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
return this;
|
|
}
|
|
};
|
|
LineCurve.prototype.isLineCurve = true;
|
|
var LineCurve3 = class extends Curve {
|
|
constructor(v12 = new Vector3(), v22 = new Vector3()) {
|
|
super();
|
|
this.type = "LineCurve3";
|
|
this.isLineCurve3 = true;
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
const point = optionalTarget;
|
|
if (t === 1) {
|
|
point.copy(this.v2);
|
|
} else {
|
|
point.copy(this.v2).sub(this.v1);
|
|
point.multiplyScalar(t).add(this.v1);
|
|
}
|
|
return point;
|
|
}
|
|
getPointAt(u, optionalTarget) {
|
|
return this.getPoint(u, optionalTarget);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
return this;
|
|
}
|
|
};
|
|
var QuadraticBezierCurve = class extends Curve {
|
|
constructor(v02 = new Vector2(), v12 = new Vector2(), v22 = new Vector2()) {
|
|
super();
|
|
this.type = "QuadraticBezierCurve";
|
|
this.v0 = v02;
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
const point = optionalTarget;
|
|
const v02 = this.v0, v12 = this.v1, v22 = this.v2;
|
|
point.set(QuadraticBezier(t, v02.x, v12.x, v22.x), QuadraticBezier(t, v02.y, v12.y, v22.y));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v0.copy(source.v0);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v0 = this.v0.toArray();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v0.fromArray(json.v0);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
return this;
|
|
}
|
|
};
|
|
QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
|
|
var QuadraticBezierCurve3 = class extends Curve {
|
|
constructor(v02 = new Vector3(), v12 = new Vector3(), v22 = new Vector3()) {
|
|
super();
|
|
this.type = "QuadraticBezierCurve3";
|
|
this.v0 = v02;
|
|
this.v1 = v12;
|
|
this.v2 = v22;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
const point = optionalTarget;
|
|
const v02 = this.v0, v12 = this.v1, v22 = this.v2;
|
|
point.set(QuadraticBezier(t, v02.x, v12.x, v22.x), QuadraticBezier(t, v02.y, v12.y, v22.y), QuadraticBezier(t, v02.z, v12.z, v22.z));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.v0.copy(source.v0);
|
|
this.v1.copy(source.v1);
|
|
this.v2.copy(source.v2);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.v0 = this.v0.toArray();
|
|
data.v1 = this.v1.toArray();
|
|
data.v2 = this.v2.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.v0.fromArray(json.v0);
|
|
this.v1.fromArray(json.v1);
|
|
this.v2.fromArray(json.v2);
|
|
return this;
|
|
}
|
|
};
|
|
QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
|
|
var SplineCurve = class extends Curve {
|
|
constructor(points = []) {
|
|
super();
|
|
this.type = "SplineCurve";
|
|
this.points = points;
|
|
}
|
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
const point = optionalTarget;
|
|
const points = this.points;
|
|
const p2 = (points.length - 1) * t;
|
|
const intPoint = Math.floor(p2);
|
|
const weight = p2 - intPoint;
|
|
const p0 = points[intPoint === 0 ? intPoint : intPoint - 1];
|
|
const p1 = points[intPoint];
|
|
const p22 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1];
|
|
const p3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2];
|
|
point.set(CatmullRom(weight, p0.x, p1.x, p22.x, p3.x), CatmullRom(weight, p0.y, p1.y, p22.y, p3.y));
|
|
return point;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.points = [];
|
|
for (let i = 0, l = source.points.length; i < l; i++) {
|
|
const point = source.points[i];
|
|
this.points.push(point.clone());
|
|
}
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.points = [];
|
|
for (let i = 0, l = this.points.length; i < l; i++) {
|
|
const point = this.points[i];
|
|
data.points.push(point.toArray());
|
|
}
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.points = [];
|
|
for (let i = 0, l = json.points.length; i < l; i++) {
|
|
const point = json.points[i];
|
|
this.points.push(new Vector2().fromArray(point));
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
SplineCurve.prototype.isSplineCurve = true;
|
|
var Curves = /* @__PURE__ */ Object.freeze({
|
|
__proto__: null,
|
|
ArcCurve,
|
|
CatmullRomCurve3,
|
|
CubicBezierCurve,
|
|
CubicBezierCurve3,
|
|
EllipseCurve,
|
|
LineCurve,
|
|
LineCurve3,
|
|
QuadraticBezierCurve,
|
|
QuadraticBezierCurve3,
|
|
SplineCurve
|
|
});
|
|
var Earcut = {
|
|
triangulate: function(data, holeIndices, dim = 2) {
|
|
const hasHoles = holeIndices && holeIndices.length;
|
|
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
let outerNode = linkedList(data, 0, outerLen, dim, true);
|
|
const triangles = [];
|
|
if (!outerNode || outerNode.next === outerNode.prev)
|
|
return triangles;
|
|
let minX, minY, maxX, maxY, x, y, invSize;
|
|
if (hasHoles)
|
|
outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
|
|
if (data.length > 80 * dim) {
|
|
minX = maxX = data[0];
|
|
minY = maxY = data[1];
|
|
for (let i = dim; i < outerLen; i += dim) {
|
|
x = data[i];
|
|
y = data[i + 1];
|
|
if (x < minX)
|
|
minX = x;
|
|
if (y < minY)
|
|
minY = y;
|
|
if (x > maxX)
|
|
maxX = x;
|
|
if (y > maxY)
|
|
maxY = y;
|
|
}
|
|
invSize = Math.max(maxX - minX, maxY - minY);
|
|
invSize = invSize !== 0 ? 1 / invSize : 0;
|
|
}
|
|
earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
|
|
return triangles;
|
|
}
|
|
};
|
|
function linkedList(data, start, end, dim, clockwise) {
|
|
let i, last;
|
|
if (clockwise === signedArea(data, start, end, dim) > 0) {
|
|
for (i = start; i < end; i += dim)
|
|
last = insertNode(i, data[i], data[i + 1], last);
|
|
} else {
|
|
for (i = end - dim; i >= start; i -= dim)
|
|
last = insertNode(i, data[i], data[i + 1], last);
|
|
}
|
|
if (last && equals(last, last.next)) {
|
|
removeNode(last);
|
|
last = last.next;
|
|
}
|
|
return last;
|
|
}
|
|
function filterPoints(start, end) {
|
|
if (!start)
|
|
return start;
|
|
if (!end)
|
|
end = start;
|
|
let p2 = start, again;
|
|
do {
|
|
again = false;
|
|
if (!p2.steiner && (equals(p2, p2.next) || area(p2.prev, p2, p2.next) === 0)) {
|
|
removeNode(p2);
|
|
p2 = end = p2.prev;
|
|
if (p2 === p2.next)
|
|
break;
|
|
again = true;
|
|
} else {
|
|
p2 = p2.next;
|
|
}
|
|
} while (again || p2 !== end);
|
|
return end;
|
|
}
|
|
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
if (!ear)
|
|
return;
|
|
if (!pass && invSize)
|
|
indexCurve(ear, minX, minY, invSize);
|
|
let stop = ear, prev, next;
|
|
while (ear.prev !== ear.next) {
|
|
prev = ear.prev;
|
|
next = ear.next;
|
|
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
triangles.push(prev.i / dim);
|
|
triangles.push(ear.i / dim);
|
|
triangles.push(next.i / dim);
|
|
removeNode(ear);
|
|
ear = next.next;
|
|
stop = next.next;
|
|
continue;
|
|
}
|
|
ear = next;
|
|
if (ear === stop) {
|
|
if (!pass) {
|
|
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
} else if (pass === 1) {
|
|
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
} else if (pass === 2) {
|
|
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
function isEar(ear) {
|
|
const a2 = ear.prev, b2 = ear, c2 = ear.next;
|
|
if (area(a2, b2, c2) >= 0)
|
|
return false;
|
|
let p2 = ear.next.next;
|
|
while (p2 !== ear.prev) {
|
|
if (pointInTriangle(a2.x, a2.y, b2.x, b2.y, c2.x, c2.y, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0)
|
|
return false;
|
|
p2 = p2.next;
|
|
}
|
|
return true;
|
|
}
|
|
function isEarHashed(ear, minX, minY, invSize) {
|
|
const a2 = ear.prev, b2 = ear, c2 = ear.next;
|
|
if (area(a2, b2, c2) >= 0)
|
|
return false;
|
|
const minTX = a2.x < b2.x ? a2.x < c2.x ? a2.x : c2.x : b2.x < c2.x ? b2.x : c2.x, minTY = a2.y < b2.y ? a2.y < c2.y ? a2.y : c2.y : b2.y < c2.y ? b2.y : c2.y, maxTX = a2.x > b2.x ? a2.x > c2.x ? a2.x : c2.x : b2.x > c2.x ? b2.x : c2.x, maxTY = a2.y > b2.y ? a2.y > c2.y ? a2.y : c2.y : b2.y > c2.y ? b2.y : c2.y;
|
|
const minZ = zOrder(minTX, minTY, minX, minY, invSize), maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
|
|
let p2 = ear.prevZ, n = ear.nextZ;
|
|
while (p2 && p2.z >= minZ && n && n.z <= maxZ) {
|
|
if (p2 !== ear.prev && p2 !== ear.next && pointInTriangle(a2.x, a2.y, b2.x, b2.y, c2.x, c2.y, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0)
|
|
return false;
|
|
p2 = p2.prevZ;
|
|
if (n !== ear.prev && n !== ear.next && pointInTriangle(a2.x, a2.y, b2.x, b2.y, c2.x, c2.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
return false;
|
|
n = n.nextZ;
|
|
}
|
|
while (p2 && p2.z >= minZ) {
|
|
if (p2 !== ear.prev && p2 !== ear.next && pointInTriangle(a2.x, a2.y, b2.x, b2.y, c2.x, c2.y, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0)
|
|
return false;
|
|
p2 = p2.prevZ;
|
|
}
|
|
while (n && n.z <= maxZ) {
|
|
if (n !== ear.prev && n !== ear.next && pointInTriangle(a2.x, a2.y, b2.x, b2.y, c2.x, c2.y, n.x, n.y) && area(n.prev, n, n.next) >= 0)
|
|
return false;
|
|
n = n.nextZ;
|
|
}
|
|
return true;
|
|
}
|
|
function cureLocalIntersections(start, triangles, dim) {
|
|
let p2 = start;
|
|
do {
|
|
const a2 = p2.prev, b2 = p2.next.next;
|
|
if (!equals(a2, b2) && intersects(a2, p2, p2.next, b2) && locallyInside(a2, b2) && locallyInside(b2, a2)) {
|
|
triangles.push(a2.i / dim);
|
|
triangles.push(p2.i / dim);
|
|
triangles.push(b2.i / dim);
|
|
removeNode(p2);
|
|
removeNode(p2.next);
|
|
p2 = start = b2;
|
|
}
|
|
p2 = p2.next;
|
|
} while (p2 !== start);
|
|
return filterPoints(p2);
|
|
}
|
|
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
let a2 = start;
|
|
do {
|
|
let b2 = a2.next.next;
|
|
while (b2 !== a2.prev) {
|
|
if (a2.i !== b2.i && isValidDiagonal(a2, b2)) {
|
|
let c2 = splitPolygon(a2, b2);
|
|
a2 = filterPoints(a2, a2.next);
|
|
c2 = filterPoints(c2, c2.next);
|
|
earcutLinked(a2, triangles, dim, minX, minY, invSize);
|
|
earcutLinked(c2, triangles, dim, minX, minY, invSize);
|
|
return;
|
|
}
|
|
b2 = b2.next;
|
|
}
|
|
a2 = a2.next;
|
|
} while (a2 !== start);
|
|
}
|
|
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
const queue = [];
|
|
let i, len, start, end, list;
|
|
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
start = holeIndices[i] * dim;
|
|
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
list = linkedList(data, start, end, dim, false);
|
|
if (list === list.next)
|
|
list.steiner = true;
|
|
queue.push(getLeftmost(list));
|
|
}
|
|
queue.sort(compareX);
|
|
for (i = 0; i < queue.length; i++) {
|
|
eliminateHole(queue[i], outerNode);
|
|
outerNode = filterPoints(outerNode, outerNode.next);
|
|
}
|
|
return outerNode;
|
|
}
|
|
function compareX(a2, b2) {
|
|
return a2.x - b2.x;
|
|
}
|
|
function eliminateHole(hole, outerNode) {
|
|
outerNode = findHoleBridge(hole, outerNode);
|
|
if (outerNode) {
|
|
const b2 = splitPolygon(outerNode, hole);
|
|
filterPoints(outerNode, outerNode.next);
|
|
filterPoints(b2, b2.next);
|
|
}
|
|
}
|
|
function findHoleBridge(hole, outerNode) {
|
|
let p2 = outerNode;
|
|
const hx = hole.x;
|
|
const hy = hole.y;
|
|
let qx = -Infinity, m;
|
|
do {
|
|
if (hy <= p2.y && hy >= p2.next.y && p2.next.y !== p2.y) {
|
|
const x = p2.x + (hy - p2.y) * (p2.next.x - p2.x) / (p2.next.y - p2.y);
|
|
if (x <= hx && x > qx) {
|
|
qx = x;
|
|
if (x === hx) {
|
|
if (hy === p2.y)
|
|
return p2;
|
|
if (hy === p2.next.y)
|
|
return p2.next;
|
|
}
|
|
m = p2.x < p2.next.x ? p2 : p2.next;
|
|
}
|
|
}
|
|
p2 = p2.next;
|
|
} while (p2 !== outerNode);
|
|
if (!m)
|
|
return null;
|
|
if (hx === qx)
|
|
return m;
|
|
const stop = m, mx = m.x, my = m.y;
|
|
let tanMin = Infinity, tan;
|
|
p2 = m;
|
|
do {
|
|
if (hx >= p2.x && p2.x >= mx && hx !== p2.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p2.x, p2.y)) {
|
|
tan = Math.abs(hy - p2.y) / (hx - p2.x);
|
|
if (locallyInside(p2, hole) && (tan < tanMin || tan === tanMin && (p2.x > m.x || p2.x === m.x && sectorContainsSector(m, p2)))) {
|
|
m = p2;
|
|
tanMin = tan;
|
|
}
|
|
}
|
|
p2 = p2.next;
|
|
} while (p2 !== stop);
|
|
return m;
|
|
}
|
|
function sectorContainsSector(m, p2) {
|
|
return area(m.prev, m, p2.prev) < 0 && area(p2.next, m, m.next) < 0;
|
|
}
|
|
function indexCurve(start, minX, minY, invSize) {
|
|
let p2 = start;
|
|
do {
|
|
if (p2.z === null)
|
|
p2.z = zOrder(p2.x, p2.y, minX, minY, invSize);
|
|
p2.prevZ = p2.prev;
|
|
p2.nextZ = p2.next;
|
|
p2 = p2.next;
|
|
} while (p2 !== start);
|
|
p2.prevZ.nextZ = null;
|
|
p2.prevZ = null;
|
|
sortLinked(p2);
|
|
}
|
|
function sortLinked(list) {
|
|
let i, p2, q, e, tail, numMerges, pSize, qSize, inSize = 1;
|
|
do {
|
|
p2 = list;
|
|
list = null;
|
|
tail = null;
|
|
numMerges = 0;
|
|
while (p2) {
|
|
numMerges++;
|
|
q = p2;
|
|
pSize = 0;
|
|
for (i = 0; i < inSize; i++) {
|
|
pSize++;
|
|
q = q.nextZ;
|
|
if (!q)
|
|
break;
|
|
}
|
|
qSize = inSize;
|
|
while (pSize > 0 || qSize > 0 && q) {
|
|
if (pSize !== 0 && (qSize === 0 || !q || p2.z <= q.z)) {
|
|
e = p2;
|
|
p2 = p2.nextZ;
|
|
pSize--;
|
|
} else {
|
|
e = q;
|
|
q = q.nextZ;
|
|
qSize--;
|
|
}
|
|
if (tail)
|
|
tail.nextZ = e;
|
|
else
|
|
list = e;
|
|
e.prevZ = tail;
|
|
tail = e;
|
|
}
|
|
p2 = q;
|
|
}
|
|
tail.nextZ = null;
|
|
inSize *= 2;
|
|
} while (numMerges > 1);
|
|
return list;
|
|
}
|
|
function zOrder(x, y, minX, minY, invSize) {
|
|
x = 32767 * (x - minX) * invSize;
|
|
y = 32767 * (y - minY) * invSize;
|
|
x = (x | x << 8) & 16711935;
|
|
x = (x | x << 4) & 252645135;
|
|
x = (x | x << 2) & 858993459;
|
|
x = (x | x << 1) & 1431655765;
|
|
y = (y | y << 8) & 16711935;
|
|
y = (y | y << 4) & 252645135;
|
|
y = (y | y << 2) & 858993459;
|
|
y = (y | y << 1) & 1431655765;
|
|
return x | y << 1;
|
|
}
|
|
function getLeftmost(start) {
|
|
let p2 = start, leftmost = start;
|
|
do {
|
|
if (p2.x < leftmost.x || p2.x === leftmost.x && p2.y < leftmost.y)
|
|
leftmost = p2;
|
|
p2 = p2.next;
|
|
} while (p2 !== start);
|
|
return leftmost;
|
|
}
|
|
function pointInTriangle(ax, ay, bx, by, cx, cy, px2, py2) {
|
|
return (cx - px2) * (ay - py2) - (ax - px2) * (cy - py2) >= 0 && (ax - px2) * (by - py2) - (bx - px2) * (ay - py2) >= 0 && (bx - px2) * (cy - py2) - (cx - px2) * (by - py2) >= 0;
|
|
}
|
|
function isValidDiagonal(a2, b2) {
|
|
return a2.next.i !== b2.i && a2.prev.i !== b2.i && !intersectsPolygon(a2, b2) && (locallyInside(a2, b2) && locallyInside(b2, a2) && middleInside(a2, b2) && (area(a2.prev, a2, b2.prev) || area(a2, b2.prev, b2)) || equals(a2, b2) && area(a2.prev, a2, a2.next) > 0 && area(b2.prev, b2, b2.next) > 0);
|
|
}
|
|
function area(p2, q, r) {
|
|
return (q.y - p2.y) * (r.x - q.x) - (q.x - p2.x) * (r.y - q.y);
|
|
}
|
|
function equals(p1, p2) {
|
|
return p1.x === p2.x && p1.y === p2.y;
|
|
}
|
|
function intersects(p1, q1, p2, q2) {
|
|
const o1 = sign(area(p1, q1, p2));
|
|
const o2 = sign(area(p1, q1, q2));
|
|
const o3 = sign(area(p2, q2, p1));
|
|
const o4 = sign(area(p2, q2, q1));
|
|
if (o1 !== o2 && o3 !== o4)
|
|
return true;
|
|
if (o1 === 0 && onSegment(p1, p2, q1))
|
|
return true;
|
|
if (o2 === 0 && onSegment(p1, q2, q1))
|
|
return true;
|
|
if (o3 === 0 && onSegment(p2, p1, q2))
|
|
return true;
|
|
if (o4 === 0 && onSegment(p2, q1, q2))
|
|
return true;
|
|
return false;
|
|
}
|
|
function onSegment(p2, q, r) {
|
|
return q.x <= Math.max(p2.x, r.x) && q.x >= Math.min(p2.x, r.x) && q.y <= Math.max(p2.y, r.y) && q.y >= Math.min(p2.y, r.y);
|
|
}
|
|
function sign(num) {
|
|
return num > 0 ? 1 : num < 0 ? -1 : 0;
|
|
}
|
|
function intersectsPolygon(a2, b2) {
|
|
let p2 = a2;
|
|
do {
|
|
if (p2.i !== a2.i && p2.next.i !== a2.i && p2.i !== b2.i && p2.next.i !== b2.i && intersects(p2, p2.next, a2, b2))
|
|
return true;
|
|
p2 = p2.next;
|
|
} while (p2 !== a2);
|
|
return false;
|
|
}
|
|
function locallyInside(a2, b2) {
|
|
return area(a2.prev, a2, a2.next) < 0 ? area(a2, b2, a2.next) >= 0 && area(a2, a2.prev, b2) >= 0 : area(a2, b2, a2.prev) < 0 || area(a2, a2.next, b2) < 0;
|
|
}
|
|
function middleInside(a2, b2) {
|
|
let p2 = a2, inside = false;
|
|
const px2 = (a2.x + b2.x) / 2, py2 = (a2.y + b2.y) / 2;
|
|
do {
|
|
if (p2.y > py2 !== p2.next.y > py2 && p2.next.y !== p2.y && px2 < (p2.next.x - p2.x) * (py2 - p2.y) / (p2.next.y - p2.y) + p2.x)
|
|
inside = !inside;
|
|
p2 = p2.next;
|
|
} while (p2 !== a2);
|
|
return inside;
|
|
}
|
|
function splitPolygon(a2, b2) {
|
|
const a22 = new Node(a2.i, a2.x, a2.y), b22 = new Node(b2.i, b2.x, b2.y), an = a2.next, bp = b2.prev;
|
|
a2.next = b2;
|
|
b2.prev = a2;
|
|
a22.next = an;
|
|
an.prev = a22;
|
|
b22.next = a22;
|
|
a22.prev = b22;
|
|
bp.next = b22;
|
|
b22.prev = bp;
|
|
return b22;
|
|
}
|
|
function insertNode(i, x, y, last) {
|
|
const p2 = new Node(i, x, y);
|
|
if (!last) {
|
|
p2.prev = p2;
|
|
p2.next = p2;
|
|
} else {
|
|
p2.next = last.next;
|
|
p2.prev = last;
|
|
last.next.prev = p2;
|
|
last.next = p2;
|
|
}
|
|
return p2;
|
|
}
|
|
function removeNode(p2) {
|
|
p2.next.prev = p2.prev;
|
|
p2.prev.next = p2.next;
|
|
if (p2.prevZ)
|
|
p2.prevZ.nextZ = p2.nextZ;
|
|
if (p2.nextZ)
|
|
p2.nextZ.prevZ = p2.prevZ;
|
|
}
|
|
function Node(i, x, y) {
|
|
this.i = i;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.prev = null;
|
|
this.next = null;
|
|
this.z = null;
|
|
this.prevZ = null;
|
|
this.nextZ = null;
|
|
this.steiner = false;
|
|
}
|
|
function signedArea(data, start, end, dim) {
|
|
let sum = 0;
|
|
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
j = i;
|
|
}
|
|
return sum;
|
|
}
|
|
var ShapeUtils = class {
|
|
static area(contour) {
|
|
const n = contour.length;
|
|
let a2 = 0;
|
|
for (let p2 = n - 1, q = 0; q < n; p2 = q++) {
|
|
a2 += contour[p2].x * contour[q].y - contour[q].x * contour[p2].y;
|
|
}
|
|
return a2 * 0.5;
|
|
}
|
|
static isClockWise(pts) {
|
|
return ShapeUtils.area(pts) < 0;
|
|
}
|
|
static triangulateShape(contour, holes) {
|
|
const vertices = [];
|
|
const holeIndices = [];
|
|
const faces = [];
|
|
removeDupEndPts(contour);
|
|
addContour(vertices, contour);
|
|
let holeIndex = contour.length;
|
|
holes.forEach(removeDupEndPts);
|
|
for (let i = 0; i < holes.length; i++) {
|
|
holeIndices.push(holeIndex);
|
|
holeIndex += holes[i].length;
|
|
addContour(vertices, holes[i]);
|
|
}
|
|
const triangles = Earcut.triangulate(vertices, holeIndices);
|
|
for (let i = 0; i < triangles.length; i += 3) {
|
|
faces.push(triangles.slice(i, i + 3));
|
|
}
|
|
return faces;
|
|
}
|
|
};
|
|
function removeDupEndPts(points) {
|
|
const l = points.length;
|
|
if (l > 2 && points[l - 1].equals(points[0])) {
|
|
points.pop();
|
|
}
|
|
}
|
|
function addContour(vertices, contour) {
|
|
for (let i = 0; i < contour.length; i++) {
|
|
vertices.push(contour[i].x);
|
|
vertices.push(contour[i].y);
|
|
}
|
|
}
|
|
var ExtrudeGeometry = class extends BufferGeometry {
|
|
constructor(shapes, options) {
|
|
super();
|
|
this.type = "ExtrudeGeometry";
|
|
this.parameters = {
|
|
shapes,
|
|
options
|
|
};
|
|
shapes = Array.isArray(shapes) ? shapes : [shapes];
|
|
const scope = this;
|
|
const verticesArray = [];
|
|
const uvArray = [];
|
|
for (let i = 0, l = shapes.length; i < l; i++) {
|
|
const shape = shapes[i];
|
|
addShape(shape);
|
|
}
|
|
this.setAttribute("position", new Float32BufferAttribute(verticesArray, 3));
|
|
this.setAttribute("uv", new Float32BufferAttribute(uvArray, 2));
|
|
this.computeVertexNormals();
|
|
function addShape(shape) {
|
|
const placeholder = [];
|
|
const curveSegments = options.curveSegments !== void 0 ? options.curveSegments : 12;
|
|
const steps = options.steps !== void 0 ? options.steps : 1;
|
|
let depth = options.depth !== void 0 ? options.depth : 100;
|
|
let bevelEnabled = options.bevelEnabled !== void 0 ? options.bevelEnabled : true;
|
|
let bevelThickness = options.bevelThickness !== void 0 ? options.bevelThickness : 6;
|
|
let bevelSize = options.bevelSize !== void 0 ? options.bevelSize : bevelThickness - 2;
|
|
let bevelOffset = options.bevelOffset !== void 0 ? options.bevelOffset : 0;
|
|
let bevelSegments = options.bevelSegments !== void 0 ? options.bevelSegments : 3;
|
|
const extrudePath = options.extrudePath;
|
|
const uvgen = options.UVGenerator !== void 0 ? options.UVGenerator : WorldUVGenerator;
|
|
if (options.amount !== void 0) {
|
|
console.warn("THREE.ExtrudeBufferGeometry: amount has been renamed to depth.");
|
|
depth = options.amount;
|
|
}
|
|
let extrudePts, extrudeByPath = false;
|
|
let splineTube, binormal, normal, position2;
|
|
if (extrudePath) {
|
|
extrudePts = extrudePath.getSpacedPoints(steps);
|
|
extrudeByPath = true;
|
|
bevelEnabled = false;
|
|
splineTube = extrudePath.computeFrenetFrames(steps, false);
|
|
binormal = new Vector3();
|
|
normal = new Vector3();
|
|
position2 = new Vector3();
|
|
}
|
|
if (!bevelEnabled) {
|
|
bevelSegments = 0;
|
|
bevelThickness = 0;
|
|
bevelSize = 0;
|
|
bevelOffset = 0;
|
|
}
|
|
const shapePoints = shape.extractPoints(curveSegments);
|
|
let vertices = shapePoints.shape;
|
|
const holes = shapePoints.holes;
|
|
const reverse = !ShapeUtils.isClockWise(vertices);
|
|
if (reverse) {
|
|
vertices = vertices.reverse();
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
if (ShapeUtils.isClockWise(ahole)) {
|
|
holes[h] = ahole.reverse();
|
|
}
|
|
}
|
|
}
|
|
const faces = ShapeUtils.triangulateShape(vertices, holes);
|
|
const contour = vertices;
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
vertices = vertices.concat(ahole);
|
|
}
|
|
function scalePt2(pt, vec, size) {
|
|
if (!vec)
|
|
console.error("THREE.ExtrudeGeometry: vec does not exist");
|
|
return vec.clone().multiplyScalar(size).add(pt);
|
|
}
|
|
const vlen = vertices.length, flen = faces.length;
|
|
function getBevelVec(inPt, inPrev, inNext) {
|
|
let v_trans_x, v_trans_y, shrink_by;
|
|
const v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y;
|
|
const v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y;
|
|
const v_prev_lensq = v_prev_x * v_prev_x + v_prev_y * v_prev_y;
|
|
const collinear0 = v_prev_x * v_next_y - v_prev_y * v_next_x;
|
|
if (Math.abs(collinear0) > Number.EPSILON) {
|
|
const v_prev_len = Math.sqrt(v_prev_lensq);
|
|
const v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y);
|
|
const ptPrevShift_x = inPrev.x - v_prev_y / v_prev_len;
|
|
const ptPrevShift_y = inPrev.y + v_prev_x / v_prev_len;
|
|
const ptNextShift_x = inNext.x - v_next_y / v_next_len;
|
|
const ptNextShift_y = inNext.y + v_next_x / v_next_len;
|
|
const sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x);
|
|
v_trans_x = ptPrevShift_x + v_prev_x * sf - inPt.x;
|
|
v_trans_y = ptPrevShift_y + v_prev_y * sf - inPt.y;
|
|
const v_trans_lensq = v_trans_x * v_trans_x + v_trans_y * v_trans_y;
|
|
if (v_trans_lensq <= 2) {
|
|
return new Vector2(v_trans_x, v_trans_y);
|
|
} else {
|
|
shrink_by = Math.sqrt(v_trans_lensq / 2);
|
|
}
|
|
} else {
|
|
let direction_eq = false;
|
|
if (v_prev_x > Number.EPSILON) {
|
|
if (v_next_x > Number.EPSILON) {
|
|
direction_eq = true;
|
|
}
|
|
} else {
|
|
if (v_prev_x < -Number.EPSILON) {
|
|
if (v_next_x < -Number.EPSILON) {
|
|
direction_eq = true;
|
|
}
|
|
} else {
|
|
if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
|
|
direction_eq = true;
|
|
}
|
|
}
|
|
}
|
|
if (direction_eq) {
|
|
v_trans_x = -v_prev_y;
|
|
v_trans_y = v_prev_x;
|
|
shrink_by = Math.sqrt(v_prev_lensq);
|
|
} else {
|
|
v_trans_x = v_prev_x;
|
|
v_trans_y = v_prev_y;
|
|
shrink_by = Math.sqrt(v_prev_lensq / 2);
|
|
}
|
|
}
|
|
return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by);
|
|
}
|
|
const contourMovements = [];
|
|
for (let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
|
|
if (j === il)
|
|
j = 0;
|
|
if (k === il)
|
|
k = 0;
|
|
contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]);
|
|
}
|
|
const holesMovements = [];
|
|
let oneHoleMovements, verticesMovements = contourMovements.concat();
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
oneHoleMovements = [];
|
|
for (let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
|
|
if (j === il)
|
|
j = 0;
|
|
if (k === il)
|
|
k = 0;
|
|
oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]);
|
|
}
|
|
holesMovements.push(oneHoleMovements);
|
|
verticesMovements = verticesMovements.concat(oneHoleMovements);
|
|
}
|
|
for (let b2 = 0; b2 < bevelSegments; b2++) {
|
|
const t = b2 / bevelSegments;
|
|
const z = bevelThickness * Math.cos(t * Math.PI / 2);
|
|
const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
|
|
for (let i = 0, il = contour.length; i < il; i++) {
|
|
const vert = scalePt2(contour[i], contourMovements[i], bs2);
|
|
v(vert.x, vert.y, -z);
|
|
}
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
oneHoleMovements = holesMovements[h];
|
|
for (let i = 0, il = ahole.length; i < il; i++) {
|
|
const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
|
|
v(vert.x, vert.y, -z);
|
|
}
|
|
}
|
|
}
|
|
const bs = bevelSize + bevelOffset;
|
|
for (let i = 0; i < vlen; i++) {
|
|
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
if (!extrudeByPath) {
|
|
v(vert.x, vert.y, 0);
|
|
} else {
|
|
normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
|
|
binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
|
|
position2.copy(extrudePts[0]).add(normal).add(binormal);
|
|
v(position2.x, position2.y, position2.z);
|
|
}
|
|
}
|
|
for (let s = 1; s <= steps; s++) {
|
|
for (let i = 0; i < vlen; i++) {
|
|
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
if (!extrudeByPath) {
|
|
v(vert.x, vert.y, depth / steps * s);
|
|
} else {
|
|
normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
|
|
binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
|
|
position2.copy(extrudePts[s]).add(normal).add(binormal);
|
|
v(position2.x, position2.y, position2.z);
|
|
}
|
|
}
|
|
}
|
|
for (let b2 = bevelSegments - 1; b2 >= 0; b2--) {
|
|
const t = b2 / bevelSegments;
|
|
const z = bevelThickness * Math.cos(t * Math.PI / 2);
|
|
const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
|
|
for (let i = 0, il = contour.length; i < il; i++) {
|
|
const vert = scalePt2(contour[i], contourMovements[i], bs2);
|
|
v(vert.x, vert.y, depth + z);
|
|
}
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
oneHoleMovements = holesMovements[h];
|
|
for (let i = 0, il = ahole.length; i < il; i++) {
|
|
const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
|
|
if (!extrudeByPath) {
|
|
v(vert.x, vert.y, depth + z);
|
|
} else {
|
|
v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
buildLidFaces();
|
|
buildSideFaces();
|
|
function buildLidFaces() {
|
|
const start = verticesArray.length / 3;
|
|
if (bevelEnabled) {
|
|
let layer = 0;
|
|
let offset = vlen * layer;
|
|
for (let i = 0; i < flen; i++) {
|
|
const face = faces[i];
|
|
f3(face[2] + offset, face[1] + offset, face[0] + offset);
|
|
}
|
|
layer = steps + bevelSegments * 2;
|
|
offset = vlen * layer;
|
|
for (let i = 0; i < flen; i++) {
|
|
const face = faces[i];
|
|
f3(face[0] + offset, face[1] + offset, face[2] + offset);
|
|
}
|
|
} else {
|
|
for (let i = 0; i < flen; i++) {
|
|
const face = faces[i];
|
|
f3(face[2], face[1], face[0]);
|
|
}
|
|
for (let i = 0; i < flen; i++) {
|
|
const face = faces[i];
|
|
f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
|
|
}
|
|
}
|
|
scope.addGroup(start, verticesArray.length / 3 - start, 0);
|
|
}
|
|
function buildSideFaces() {
|
|
const start = verticesArray.length / 3;
|
|
let layeroffset = 0;
|
|
sidewalls(contour, layeroffset);
|
|
layeroffset += contour.length;
|
|
for (let h = 0, hl = holes.length; h < hl; h++) {
|
|
const ahole = holes[h];
|
|
sidewalls(ahole, layeroffset);
|
|
layeroffset += ahole.length;
|
|
}
|
|
scope.addGroup(start, verticesArray.length / 3 - start, 1);
|
|
}
|
|
function sidewalls(contour2, layeroffset) {
|
|
let i = contour2.length;
|
|
while (--i >= 0) {
|
|
const j = i;
|
|
let k = i - 1;
|
|
if (k < 0)
|
|
k = contour2.length - 1;
|
|
for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
|
|
const slen1 = vlen * s;
|
|
const slen2 = vlen * (s + 1);
|
|
const a2 = layeroffset + j + slen1, b2 = layeroffset + k + slen1, c2 = layeroffset + k + slen2, d = layeroffset + j + slen2;
|
|
f4(a2, b2, c2, d);
|
|
}
|
|
}
|
|
}
|
|
function v(x, y, z) {
|
|
placeholder.push(x);
|
|
placeholder.push(y);
|
|
placeholder.push(z);
|
|
}
|
|
function f3(a2, b2, c2) {
|
|
addVertex(a2);
|
|
addVertex(b2);
|
|
addVertex(c2);
|
|
const nextIndex = verticesArray.length / 3;
|
|
const uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1);
|
|
addUV(uvs[0]);
|
|
addUV(uvs[1]);
|
|
addUV(uvs[2]);
|
|
}
|
|
function f4(a2, b2, c2, d) {
|
|
addVertex(a2);
|
|
addVertex(b2);
|
|
addVertex(d);
|
|
addVertex(b2);
|
|
addVertex(c2);
|
|
addVertex(d);
|
|
const nextIndex = verticesArray.length / 3;
|
|
const uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1);
|
|
addUV(uvs[0]);
|
|
addUV(uvs[1]);
|
|
addUV(uvs[3]);
|
|
addUV(uvs[1]);
|
|
addUV(uvs[2]);
|
|
addUV(uvs[3]);
|
|
}
|
|
function addVertex(index) {
|
|
verticesArray.push(placeholder[index * 3 + 0]);
|
|
verticesArray.push(placeholder[index * 3 + 1]);
|
|
verticesArray.push(placeholder[index * 3 + 2]);
|
|
}
|
|
function addUV(vector2) {
|
|
uvArray.push(vector2.x);
|
|
uvArray.push(vector2.y);
|
|
}
|
|
}
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
const shapes = this.parameters.shapes;
|
|
const options = this.parameters.options;
|
|
return toJSON$1(shapes, options, data);
|
|
}
|
|
static fromJSON(data, shapes) {
|
|
const geometryShapes = [];
|
|
for (let j = 0, jl = data.shapes.length; j < jl; j++) {
|
|
const shape = shapes[data.shapes[j]];
|
|
geometryShapes.push(shape);
|
|
}
|
|
const extrudePath = data.options.extrudePath;
|
|
if (extrudePath !== void 0) {
|
|
data.options.extrudePath = new Curves[extrudePath.type]().fromJSON(extrudePath);
|
|
}
|
|
return new ExtrudeGeometry(geometryShapes, data.options);
|
|
}
|
|
};
|
|
var WorldUVGenerator = {
|
|
generateTopUV: function(geometry, vertices, indexA, indexB, indexC) {
|
|
const a_x = vertices[indexA * 3];
|
|
const a_y = vertices[indexA * 3 + 1];
|
|
const b_x = vertices[indexB * 3];
|
|
const b_y = vertices[indexB * 3 + 1];
|
|
const c_x = vertices[indexC * 3];
|
|
const c_y = vertices[indexC * 3 + 1];
|
|
return [
|
|
new Vector2(a_x, a_y),
|
|
new Vector2(b_x, b_y),
|
|
new Vector2(c_x, c_y)
|
|
];
|
|
},
|
|
generateSideWallUV: function(geometry, vertices, indexA, indexB, indexC, indexD) {
|
|
const a_x = vertices[indexA * 3];
|
|
const a_y = vertices[indexA * 3 + 1];
|
|
const a_z = vertices[indexA * 3 + 2];
|
|
const b_x = vertices[indexB * 3];
|
|
const b_y = vertices[indexB * 3 + 1];
|
|
const b_z = vertices[indexB * 3 + 2];
|
|
const c_x = vertices[indexC * 3];
|
|
const c_y = vertices[indexC * 3 + 1];
|
|
const c_z = vertices[indexC * 3 + 2];
|
|
const d_x = vertices[indexD * 3];
|
|
const d_y = vertices[indexD * 3 + 1];
|
|
const d_z = vertices[indexD * 3 + 2];
|
|
if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) {
|
|
return [
|
|
new Vector2(a_x, 1 - a_z),
|
|
new Vector2(b_x, 1 - b_z),
|
|
new Vector2(c_x, 1 - c_z),
|
|
new Vector2(d_x, 1 - d_z)
|
|
];
|
|
} else {
|
|
return [
|
|
new Vector2(a_y, 1 - a_z),
|
|
new Vector2(b_y, 1 - b_z),
|
|
new Vector2(c_y, 1 - c_z),
|
|
new Vector2(d_y, 1 - d_z)
|
|
];
|
|
}
|
|
}
|
|
};
|
|
function toJSON$1(shapes, options, data) {
|
|
data.shapes = [];
|
|
if (Array.isArray(shapes)) {
|
|
for (let i = 0, l = shapes.length; i < l; i++) {
|
|
const shape = shapes[i];
|
|
data.shapes.push(shape.uuid);
|
|
}
|
|
} else {
|
|
data.shapes.push(shapes.uuid);
|
|
}
|
|
if (options.extrudePath !== void 0)
|
|
data.options.extrudePath = options.extrudePath.toJSON();
|
|
return data;
|
|
}
|
|
var ShapeGeometry = class extends BufferGeometry {
|
|
constructor(shapes, curveSegments = 12) {
|
|
super();
|
|
this.type = "ShapeGeometry";
|
|
this.parameters = {
|
|
shapes,
|
|
curveSegments
|
|
};
|
|
const indices = [];
|
|
const vertices = [];
|
|
const normals = [];
|
|
const uvs = [];
|
|
let groupStart = 0;
|
|
let groupCount = 0;
|
|
if (Array.isArray(shapes) === false) {
|
|
addShape(shapes);
|
|
} else {
|
|
for (let i = 0; i < shapes.length; i++) {
|
|
addShape(shapes[i]);
|
|
this.addGroup(groupStart, groupCount, i);
|
|
groupStart += groupCount;
|
|
groupCount = 0;
|
|
}
|
|
}
|
|
this.setIndex(indices);
|
|
this.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
this.setAttribute("normal", new Float32BufferAttribute(normals, 3));
|
|
this.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
function addShape(shape) {
|
|
const indexOffset = vertices.length / 3;
|
|
const points = shape.extractPoints(curveSegments);
|
|
let shapeVertices = points.shape;
|
|
const shapeHoles = points.holes;
|
|
if (ShapeUtils.isClockWise(shapeVertices) === false) {
|
|
shapeVertices = shapeVertices.reverse();
|
|
}
|
|
for (let i = 0, l = shapeHoles.length; i < l; i++) {
|
|
const shapeHole = shapeHoles[i];
|
|
if (ShapeUtils.isClockWise(shapeHole) === true) {
|
|
shapeHoles[i] = shapeHole.reverse();
|
|
}
|
|
}
|
|
const faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles);
|
|
for (let i = 0, l = shapeHoles.length; i < l; i++) {
|
|
const shapeHole = shapeHoles[i];
|
|
shapeVertices = shapeVertices.concat(shapeHole);
|
|
}
|
|
for (let i = 0, l = shapeVertices.length; i < l; i++) {
|
|
const vertex = shapeVertices[i];
|
|
vertices.push(vertex.x, vertex.y, 0);
|
|
normals.push(0, 0, 1);
|
|
uvs.push(vertex.x, vertex.y);
|
|
}
|
|
for (let i = 0, l = faces.length; i < l; i++) {
|
|
const face = faces[i];
|
|
const a2 = face[0] + indexOffset;
|
|
const b2 = face[1] + indexOffset;
|
|
const c2 = face[2] + indexOffset;
|
|
indices.push(a2, b2, c2);
|
|
groupCount += 3;
|
|
}
|
|
}
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
const shapes = this.parameters.shapes;
|
|
return toJSON(shapes, data);
|
|
}
|
|
static fromJSON(data, shapes) {
|
|
const geometryShapes = [];
|
|
for (let j = 0, jl = data.shapes.length; j < jl; j++) {
|
|
const shape = shapes[data.shapes[j]];
|
|
geometryShapes.push(shape);
|
|
}
|
|
return new ShapeGeometry(geometryShapes, data.curveSegments);
|
|
}
|
|
};
|
|
function toJSON(shapes, data) {
|
|
data.shapes = [];
|
|
if (Array.isArray(shapes)) {
|
|
for (let i = 0, l = shapes.length; i < l; i++) {
|
|
const shape = shapes[i];
|
|
data.shapes.push(shape.uuid);
|
|
}
|
|
} else {
|
|
data.shapes.push(shapes.uuid);
|
|
}
|
|
return data;
|
|
}
|
|
var ShadowMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "ShadowMaterial";
|
|
this.color = new Color(0);
|
|
this.transparent = true;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
return this;
|
|
}
|
|
};
|
|
ShadowMaterial.prototype.isShadowMaterial = true;
|
|
var MeshStandardMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.defines = { "STANDARD": "" };
|
|
this.type = "MeshStandardMaterial";
|
|
this.color = new Color(16777215);
|
|
this.roughness = 1;
|
|
this.metalness = 0;
|
|
this.map = null;
|
|
this.lightMap = null;
|
|
this.lightMapIntensity = 1;
|
|
this.aoMap = null;
|
|
this.aoMapIntensity = 1;
|
|
this.emissive = new Color(0);
|
|
this.emissiveIntensity = 1;
|
|
this.emissiveMap = null;
|
|
this.bumpMap = null;
|
|
this.bumpScale = 1;
|
|
this.normalMap = null;
|
|
this.normalMapType = TangentSpaceNormalMap;
|
|
this.normalScale = new Vector2(1, 1);
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.roughnessMap = null;
|
|
this.metalnessMap = null;
|
|
this.alphaMap = null;
|
|
this.envMap = null;
|
|
this.envMapIntensity = 1;
|
|
this.refractionRatio = 0.98;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.wireframeLinecap = "round";
|
|
this.wireframeLinejoin = "round";
|
|
this.flatShading = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.defines = { "STANDARD": "" };
|
|
this.color.copy(source.color);
|
|
this.roughness = source.roughness;
|
|
this.metalness = source.metalness;
|
|
this.map = source.map;
|
|
this.lightMap = source.lightMap;
|
|
this.lightMapIntensity = source.lightMapIntensity;
|
|
this.aoMap = source.aoMap;
|
|
this.aoMapIntensity = source.aoMapIntensity;
|
|
this.emissive.copy(source.emissive);
|
|
this.emissiveMap = source.emissiveMap;
|
|
this.emissiveIntensity = source.emissiveIntensity;
|
|
this.bumpMap = source.bumpMap;
|
|
this.bumpScale = source.bumpScale;
|
|
this.normalMap = source.normalMap;
|
|
this.normalMapType = source.normalMapType;
|
|
this.normalScale.copy(source.normalScale);
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.roughnessMap = source.roughnessMap;
|
|
this.metalnessMap = source.metalnessMap;
|
|
this.alphaMap = source.alphaMap;
|
|
this.envMap = source.envMap;
|
|
this.envMapIntensity = source.envMapIntensity;
|
|
this.refractionRatio = source.refractionRatio;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.wireframeLinecap = source.wireframeLinecap;
|
|
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
this.flatShading = source.flatShading;
|
|
return this;
|
|
}
|
|
};
|
|
MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
|
|
var MeshPhysicalMaterial = class extends MeshStandardMaterial {
|
|
constructor(parameters) {
|
|
super();
|
|
this.defines = {
|
|
"STANDARD": "",
|
|
"PHYSICAL": ""
|
|
};
|
|
this.type = "MeshPhysicalMaterial";
|
|
this.clearcoatMap = null;
|
|
this.clearcoatRoughness = 0;
|
|
this.clearcoatRoughnessMap = null;
|
|
this.clearcoatNormalScale = new Vector2(1, 1);
|
|
this.clearcoatNormalMap = null;
|
|
this.ior = 1.5;
|
|
Object.defineProperty(this, "reflectivity", {
|
|
get: function() {
|
|
return clamp(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1);
|
|
},
|
|
set: function(reflectivity) {
|
|
this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity);
|
|
}
|
|
});
|
|
this.sheenTint = new Color(0);
|
|
this.transmission = 0;
|
|
this.transmissionMap = null;
|
|
this.thickness = 0.01;
|
|
this.thicknessMap = null;
|
|
this.attenuationDistance = 0;
|
|
this.attenuationTint = new Color(1, 1, 1);
|
|
this.specularIntensity = 1;
|
|
this.specularIntensityMap = null;
|
|
this.specularTint = new Color(1, 1, 1);
|
|
this.specularTintMap = null;
|
|
this._clearcoat = 0;
|
|
this._transmission = 0;
|
|
this.setValues(parameters);
|
|
}
|
|
get clearcoat() {
|
|
return this._clearcoat;
|
|
}
|
|
set clearcoat(value) {
|
|
if (this._clearcoat > 0 !== value > 0) {
|
|
this.version++;
|
|
}
|
|
this._clearcoat = value;
|
|
}
|
|
get transmission() {
|
|
return this._transmission;
|
|
}
|
|
set transmission(value) {
|
|
if (this._transmission > 0 !== value > 0) {
|
|
this.version++;
|
|
}
|
|
this._transmission = value;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.defines = {
|
|
"STANDARD": "",
|
|
"PHYSICAL": ""
|
|
};
|
|
this.clearcoat = source.clearcoat;
|
|
this.clearcoatMap = source.clearcoatMap;
|
|
this.clearcoatRoughness = source.clearcoatRoughness;
|
|
this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
|
|
this.clearcoatNormalMap = source.clearcoatNormalMap;
|
|
this.clearcoatNormalScale.copy(source.clearcoatNormalScale);
|
|
this.ior = source.ior;
|
|
this.sheenTint.copy(source.sheenTint);
|
|
this.transmission = source.transmission;
|
|
this.transmissionMap = source.transmissionMap;
|
|
this.thickness = source.thickness;
|
|
this.thicknessMap = source.thicknessMap;
|
|
this.attenuationDistance = source.attenuationDistance;
|
|
this.attenuationTint.copy(source.attenuationTint);
|
|
this.specularIntensity = source.specularIntensity;
|
|
this.specularIntensityMap = source.specularIntensityMap;
|
|
this.specularTint.copy(source.specularTint);
|
|
this.specularTintMap = source.specularTintMap;
|
|
return this;
|
|
}
|
|
};
|
|
MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
|
|
var MeshPhongMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshPhongMaterial";
|
|
this.color = new Color(16777215);
|
|
this.specular = new Color(1118481);
|
|
this.shininess = 30;
|
|
this.map = null;
|
|
this.lightMap = null;
|
|
this.lightMapIntensity = 1;
|
|
this.aoMap = null;
|
|
this.aoMapIntensity = 1;
|
|
this.emissive = new Color(0);
|
|
this.emissiveIntensity = 1;
|
|
this.emissiveMap = null;
|
|
this.bumpMap = null;
|
|
this.bumpScale = 1;
|
|
this.normalMap = null;
|
|
this.normalMapType = TangentSpaceNormalMap;
|
|
this.normalScale = new Vector2(1, 1);
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.specularMap = null;
|
|
this.alphaMap = null;
|
|
this.envMap = null;
|
|
this.combine = MultiplyOperation;
|
|
this.reflectivity = 1;
|
|
this.refractionRatio = 0.98;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.wireframeLinecap = "round";
|
|
this.wireframeLinejoin = "round";
|
|
this.flatShading = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.specular.copy(source.specular);
|
|
this.shininess = source.shininess;
|
|
this.map = source.map;
|
|
this.lightMap = source.lightMap;
|
|
this.lightMapIntensity = source.lightMapIntensity;
|
|
this.aoMap = source.aoMap;
|
|
this.aoMapIntensity = source.aoMapIntensity;
|
|
this.emissive.copy(source.emissive);
|
|
this.emissiveMap = source.emissiveMap;
|
|
this.emissiveIntensity = source.emissiveIntensity;
|
|
this.bumpMap = source.bumpMap;
|
|
this.bumpScale = source.bumpScale;
|
|
this.normalMap = source.normalMap;
|
|
this.normalMapType = source.normalMapType;
|
|
this.normalScale.copy(source.normalScale);
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.specularMap = source.specularMap;
|
|
this.alphaMap = source.alphaMap;
|
|
this.envMap = source.envMap;
|
|
this.combine = source.combine;
|
|
this.reflectivity = source.reflectivity;
|
|
this.refractionRatio = source.refractionRatio;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.wireframeLinecap = source.wireframeLinecap;
|
|
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
this.flatShading = source.flatShading;
|
|
return this;
|
|
}
|
|
};
|
|
MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
|
|
var MeshToonMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.defines = { "TOON": "" };
|
|
this.type = "MeshToonMaterial";
|
|
this.color = new Color(16777215);
|
|
this.map = null;
|
|
this.gradientMap = null;
|
|
this.lightMap = null;
|
|
this.lightMapIntensity = 1;
|
|
this.aoMap = null;
|
|
this.aoMapIntensity = 1;
|
|
this.emissive = new Color(0);
|
|
this.emissiveIntensity = 1;
|
|
this.emissiveMap = null;
|
|
this.bumpMap = null;
|
|
this.bumpScale = 1;
|
|
this.normalMap = null;
|
|
this.normalMapType = TangentSpaceNormalMap;
|
|
this.normalScale = new Vector2(1, 1);
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.alphaMap = null;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.wireframeLinecap = "round";
|
|
this.wireframeLinejoin = "round";
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.map = source.map;
|
|
this.gradientMap = source.gradientMap;
|
|
this.lightMap = source.lightMap;
|
|
this.lightMapIntensity = source.lightMapIntensity;
|
|
this.aoMap = source.aoMap;
|
|
this.aoMapIntensity = source.aoMapIntensity;
|
|
this.emissive.copy(source.emissive);
|
|
this.emissiveMap = source.emissiveMap;
|
|
this.emissiveIntensity = source.emissiveIntensity;
|
|
this.bumpMap = source.bumpMap;
|
|
this.bumpScale = source.bumpScale;
|
|
this.normalMap = source.normalMap;
|
|
this.normalMapType = source.normalMapType;
|
|
this.normalScale.copy(source.normalScale);
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.alphaMap = source.alphaMap;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.wireframeLinecap = source.wireframeLinecap;
|
|
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
return this;
|
|
}
|
|
};
|
|
MeshToonMaterial.prototype.isMeshToonMaterial = true;
|
|
var MeshNormalMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshNormalMaterial";
|
|
this.bumpMap = null;
|
|
this.bumpScale = 1;
|
|
this.normalMap = null;
|
|
this.normalMapType = TangentSpaceNormalMap;
|
|
this.normalScale = new Vector2(1, 1);
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.fog = false;
|
|
this.flatShading = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.bumpMap = source.bumpMap;
|
|
this.bumpScale = source.bumpScale;
|
|
this.normalMap = source.normalMap;
|
|
this.normalMapType = source.normalMapType;
|
|
this.normalScale.copy(source.normalScale);
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.flatShading = source.flatShading;
|
|
return this;
|
|
}
|
|
};
|
|
MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
|
|
var MeshLambertMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "MeshLambertMaterial";
|
|
this.color = new Color(16777215);
|
|
this.map = null;
|
|
this.lightMap = null;
|
|
this.lightMapIntensity = 1;
|
|
this.aoMap = null;
|
|
this.aoMapIntensity = 1;
|
|
this.emissive = new Color(0);
|
|
this.emissiveIntensity = 1;
|
|
this.emissiveMap = null;
|
|
this.specularMap = null;
|
|
this.alphaMap = null;
|
|
this.envMap = null;
|
|
this.combine = MultiplyOperation;
|
|
this.reflectivity = 1;
|
|
this.refractionRatio = 0.98;
|
|
this.wireframe = false;
|
|
this.wireframeLinewidth = 1;
|
|
this.wireframeLinecap = "round";
|
|
this.wireframeLinejoin = "round";
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.map = source.map;
|
|
this.lightMap = source.lightMap;
|
|
this.lightMapIntensity = source.lightMapIntensity;
|
|
this.aoMap = source.aoMap;
|
|
this.aoMapIntensity = source.aoMapIntensity;
|
|
this.emissive.copy(source.emissive);
|
|
this.emissiveMap = source.emissiveMap;
|
|
this.emissiveIntensity = source.emissiveIntensity;
|
|
this.specularMap = source.specularMap;
|
|
this.alphaMap = source.alphaMap;
|
|
this.envMap = source.envMap;
|
|
this.combine = source.combine;
|
|
this.reflectivity = source.reflectivity;
|
|
this.refractionRatio = source.refractionRatio;
|
|
this.wireframe = source.wireframe;
|
|
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
this.wireframeLinecap = source.wireframeLinecap;
|
|
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
return this;
|
|
}
|
|
};
|
|
MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
|
|
var MeshMatcapMaterial = class extends Material {
|
|
constructor(parameters) {
|
|
super();
|
|
this.defines = { "MATCAP": "" };
|
|
this.type = "MeshMatcapMaterial";
|
|
this.color = new Color(16777215);
|
|
this.matcap = null;
|
|
this.map = null;
|
|
this.bumpMap = null;
|
|
this.bumpScale = 1;
|
|
this.normalMap = null;
|
|
this.normalMapType = TangentSpaceNormalMap;
|
|
this.normalScale = new Vector2(1, 1);
|
|
this.displacementMap = null;
|
|
this.displacementScale = 1;
|
|
this.displacementBias = 0;
|
|
this.alphaMap = null;
|
|
this.flatShading = false;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.defines = { "MATCAP": "" };
|
|
this.color.copy(source.color);
|
|
this.matcap = source.matcap;
|
|
this.map = source.map;
|
|
this.bumpMap = source.bumpMap;
|
|
this.bumpScale = source.bumpScale;
|
|
this.normalMap = source.normalMap;
|
|
this.normalMapType = source.normalMapType;
|
|
this.normalScale.copy(source.normalScale);
|
|
this.displacementMap = source.displacementMap;
|
|
this.displacementScale = source.displacementScale;
|
|
this.displacementBias = source.displacementBias;
|
|
this.alphaMap = source.alphaMap;
|
|
this.flatShading = source.flatShading;
|
|
return this;
|
|
}
|
|
};
|
|
MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
|
|
var LineDashedMaterial = class extends LineBasicMaterial {
|
|
constructor(parameters) {
|
|
super();
|
|
this.type = "LineDashedMaterial";
|
|
this.scale = 1;
|
|
this.dashSize = 3;
|
|
this.gapSize = 1;
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.scale = source.scale;
|
|
this.dashSize = source.dashSize;
|
|
this.gapSize = source.gapSize;
|
|
return this;
|
|
}
|
|
};
|
|
LineDashedMaterial.prototype.isLineDashedMaterial = true;
|
|
var AnimationUtils = {
|
|
arraySlice: function(array, from, to) {
|
|
if (AnimationUtils.isTypedArray(array)) {
|
|
return new array.constructor(array.subarray(from, to !== void 0 ? to : array.length));
|
|
}
|
|
return array.slice(from, to);
|
|
},
|
|
convertArray: function(array, type, forceClone) {
|
|
if (!array || !forceClone && array.constructor === type)
|
|
return array;
|
|
if (typeof type.BYTES_PER_ELEMENT === "number") {
|
|
return new type(array);
|
|
}
|
|
return Array.prototype.slice.call(array);
|
|
},
|
|
isTypedArray: function(object) {
|
|
return ArrayBuffer.isView(object) && !(object instanceof DataView);
|
|
},
|
|
getKeyframeOrder: function(times) {
|
|
function compareTime(i, j) {
|
|
return times[i] - times[j];
|
|
}
|
|
const n = times.length;
|
|
const result = new Array(n);
|
|
for (let i = 0; i !== n; ++i)
|
|
result[i] = i;
|
|
result.sort(compareTime);
|
|
return result;
|
|
},
|
|
sortedArray: function(values, stride, order) {
|
|
const nValues = values.length;
|
|
const result = new values.constructor(nValues);
|
|
for (let i = 0, dstOffset = 0; dstOffset !== nValues; ++i) {
|
|
const srcOffset = order[i] * stride;
|
|
for (let j = 0; j !== stride; ++j) {
|
|
result[dstOffset++] = values[srcOffset + j];
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
flattenJSON: function(jsonKeys, times, values, valuePropertyName) {
|
|
let i = 1, key = jsonKeys[0];
|
|
while (key !== void 0 && key[valuePropertyName] === void 0) {
|
|
key = jsonKeys[i++];
|
|
}
|
|
if (key === void 0)
|
|
return;
|
|
let value = key[valuePropertyName];
|
|
if (value === void 0)
|
|
return;
|
|
if (Array.isArray(value)) {
|
|
do {
|
|
value = key[valuePropertyName];
|
|
if (value !== void 0) {
|
|
times.push(key.time);
|
|
values.push.apply(values, value);
|
|
}
|
|
key = jsonKeys[i++];
|
|
} while (key !== void 0);
|
|
} else if (value.toArray !== void 0) {
|
|
do {
|
|
value = key[valuePropertyName];
|
|
if (value !== void 0) {
|
|
times.push(key.time);
|
|
value.toArray(values, values.length);
|
|
}
|
|
key = jsonKeys[i++];
|
|
} while (key !== void 0);
|
|
} else {
|
|
do {
|
|
value = key[valuePropertyName];
|
|
if (value !== void 0) {
|
|
times.push(key.time);
|
|
values.push(value);
|
|
}
|
|
key = jsonKeys[i++];
|
|
} while (key !== void 0);
|
|
}
|
|
},
|
|
subclip: function(sourceClip, name, startFrame, endFrame, fps = 30) {
|
|
const clip = sourceClip.clone();
|
|
clip.name = name;
|
|
const tracks = [];
|
|
for (let i = 0; i < clip.tracks.length; ++i) {
|
|
const track = clip.tracks[i];
|
|
const valueSize = track.getValueSize();
|
|
const times = [];
|
|
const values = [];
|
|
for (let j = 0; j < track.times.length; ++j) {
|
|
const frame = track.times[j] * fps;
|
|
if (frame < startFrame || frame >= endFrame)
|
|
continue;
|
|
times.push(track.times[j]);
|
|
for (let k = 0; k < valueSize; ++k) {
|
|
values.push(track.values[j * valueSize + k]);
|
|
}
|
|
}
|
|
if (times.length === 0)
|
|
continue;
|
|
track.times = AnimationUtils.convertArray(times, track.times.constructor);
|
|
track.values = AnimationUtils.convertArray(values, track.values.constructor);
|
|
tracks.push(track);
|
|
}
|
|
clip.tracks = tracks;
|
|
let minStartTime = Infinity;
|
|
for (let i = 0; i < clip.tracks.length; ++i) {
|
|
if (minStartTime > clip.tracks[i].times[0]) {
|
|
minStartTime = clip.tracks[i].times[0];
|
|
}
|
|
}
|
|
for (let i = 0; i < clip.tracks.length; ++i) {
|
|
clip.tracks[i].shift(-1 * minStartTime);
|
|
}
|
|
clip.resetDuration();
|
|
return clip;
|
|
},
|
|
makeClipAdditive: function(targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30) {
|
|
if (fps <= 0)
|
|
fps = 30;
|
|
const numTracks = referenceClip.tracks.length;
|
|
const referenceTime = referenceFrame / fps;
|
|
for (let i = 0; i < numTracks; ++i) {
|
|
const referenceTrack = referenceClip.tracks[i];
|
|
const referenceTrackType = referenceTrack.ValueTypeName;
|
|
if (referenceTrackType === "bool" || referenceTrackType === "string")
|
|
continue;
|
|
const targetTrack = targetClip.tracks.find(function(track) {
|
|
return track.name === referenceTrack.name && track.ValueTypeName === referenceTrackType;
|
|
});
|
|
if (targetTrack === void 0)
|
|
continue;
|
|
let referenceOffset = 0;
|
|
const referenceValueSize = referenceTrack.getValueSize();
|
|
if (referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
|
|
referenceOffset = referenceValueSize / 3;
|
|
}
|
|
let targetOffset = 0;
|
|
const targetValueSize = targetTrack.getValueSize();
|
|
if (targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
|
|
targetOffset = targetValueSize / 3;
|
|
}
|
|
const lastIndex = referenceTrack.times.length - 1;
|
|
let referenceValue;
|
|
if (referenceTime <= referenceTrack.times[0]) {
|
|
const startIndex = referenceOffset;
|
|
const endIndex = referenceValueSize - referenceOffset;
|
|
referenceValue = AnimationUtils.arraySlice(referenceTrack.values, startIndex, endIndex);
|
|
} else if (referenceTime >= referenceTrack.times[lastIndex]) {
|
|
const startIndex = lastIndex * referenceValueSize + referenceOffset;
|
|
const endIndex = startIndex + referenceValueSize - referenceOffset;
|
|
referenceValue = AnimationUtils.arraySlice(referenceTrack.values, startIndex, endIndex);
|
|
} else {
|
|
const interpolant = referenceTrack.createInterpolant();
|
|
const startIndex = referenceOffset;
|
|
const endIndex = referenceValueSize - referenceOffset;
|
|
interpolant.evaluate(referenceTime);
|
|
referenceValue = AnimationUtils.arraySlice(interpolant.resultBuffer, startIndex, endIndex);
|
|
}
|
|
if (referenceTrackType === "quaternion") {
|
|
const referenceQuat = new Quaternion().fromArray(referenceValue).normalize().conjugate();
|
|
referenceQuat.toArray(referenceValue);
|
|
}
|
|
const numTimes = targetTrack.times.length;
|
|
for (let j = 0; j < numTimes; ++j) {
|
|
const valueStart = j * targetValueSize + targetOffset;
|
|
if (referenceTrackType === "quaternion") {
|
|
Quaternion.multiplyQuaternionsFlat(targetTrack.values, valueStart, referenceValue, 0, targetTrack.values, valueStart);
|
|
} else {
|
|
const valueEnd = targetValueSize - targetOffset * 2;
|
|
for (let k = 0; k < valueEnd; ++k) {
|
|
targetTrack.values[valueStart + k] -= referenceValue[k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
targetClip.blendMode = AdditiveAnimationBlendMode;
|
|
return targetClip;
|
|
}
|
|
};
|
|
var Interpolant = class {
|
|
constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
|
|
this.parameterPositions = parameterPositions;
|
|
this._cachedIndex = 0;
|
|
this.resultBuffer = resultBuffer !== void 0 ? resultBuffer : new sampleValues.constructor(sampleSize);
|
|
this.sampleValues = sampleValues;
|
|
this.valueSize = sampleSize;
|
|
this.settings = null;
|
|
this.DefaultSettings_ = {};
|
|
}
|
|
evaluate(t) {
|
|
const pp = this.parameterPositions;
|
|
let i1 = this._cachedIndex, t1 = pp[i1], t0 = pp[i1 - 1];
|
|
validate_interval: {
|
|
seek: {
|
|
let right;
|
|
linear_scan: {
|
|
forward_scan:
|
|
if (!(t < t1)) {
|
|
for (let giveUpAt = i1 + 2; ; ) {
|
|
if (t1 === void 0) {
|
|
if (t < t0)
|
|
break forward_scan;
|
|
i1 = pp.length;
|
|
this._cachedIndex = i1;
|
|
return this.afterEnd_(i1 - 1, t, t0);
|
|
}
|
|
if (i1 === giveUpAt)
|
|
break;
|
|
t0 = t1;
|
|
t1 = pp[++i1];
|
|
if (t < t1) {
|
|
break seek;
|
|
}
|
|
}
|
|
right = pp.length;
|
|
break linear_scan;
|
|
}
|
|
if (!(t >= t0)) {
|
|
const t1global = pp[1];
|
|
if (t < t1global) {
|
|
i1 = 2;
|
|
t0 = t1global;
|
|
}
|
|
for (let giveUpAt = i1 - 2; ; ) {
|
|
if (t0 === void 0) {
|
|
this._cachedIndex = 0;
|
|
return this.beforeStart_(0, t, t1);
|
|
}
|
|
if (i1 === giveUpAt)
|
|
break;
|
|
t1 = t0;
|
|
t0 = pp[--i1 - 1];
|
|
if (t >= t0) {
|
|
break seek;
|
|
}
|
|
}
|
|
right = i1;
|
|
i1 = 0;
|
|
break linear_scan;
|
|
}
|
|
break validate_interval;
|
|
}
|
|
while (i1 < right) {
|
|
const mid = i1 + right >>> 1;
|
|
if (t < pp[mid]) {
|
|
right = mid;
|
|
} else {
|
|
i1 = mid + 1;
|
|
}
|
|
}
|
|
t1 = pp[i1];
|
|
t0 = pp[i1 - 1];
|
|
if (t0 === void 0) {
|
|
this._cachedIndex = 0;
|
|
return this.beforeStart_(0, t, t1);
|
|
}
|
|
if (t1 === void 0) {
|
|
i1 = pp.length;
|
|
this._cachedIndex = i1;
|
|
return this.afterEnd_(i1 - 1, t0, t);
|
|
}
|
|
}
|
|
this._cachedIndex = i1;
|
|
this.intervalChanged_(i1, t0, t1);
|
|
}
|
|
return this.interpolate_(i1, t0, t, t1);
|
|
}
|
|
getSettings_() {
|
|
return this.settings || this.DefaultSettings_;
|
|
}
|
|
copySampleValue_(index) {
|
|
const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset = index * stride;
|
|
for (let i = 0; i !== stride; ++i) {
|
|
result[i] = values[offset + i];
|
|
}
|
|
return result;
|
|
}
|
|
interpolate_() {
|
|
throw new Error("call to abstract method");
|
|
}
|
|
intervalChanged_() {
|
|
}
|
|
};
|
|
Interpolant.prototype.beforeStart_ = Interpolant.prototype.copySampleValue_;
|
|
Interpolant.prototype.afterEnd_ = Interpolant.prototype.copySampleValue_;
|
|
var CubicInterpolant = class extends Interpolant {
|
|
constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
|
|
super(parameterPositions, sampleValues, sampleSize, resultBuffer);
|
|
this._weightPrev = -0;
|
|
this._offsetPrev = -0;
|
|
this._weightNext = -0;
|
|
this._offsetNext = -0;
|
|
this.DefaultSettings_ = {
|
|
endingStart: ZeroCurvatureEnding,
|
|
endingEnd: ZeroCurvatureEnding
|
|
};
|
|
}
|
|
intervalChanged_(i1, t0, t1) {
|
|
const pp = this.parameterPositions;
|
|
let iPrev = i1 - 2, iNext = i1 + 1, tPrev = pp[iPrev], tNext = pp[iNext];
|
|
if (tPrev === void 0) {
|
|
switch (this.getSettings_().endingStart) {
|
|
case ZeroSlopeEnding:
|
|
iPrev = i1;
|
|
tPrev = 2 * t0 - t1;
|
|
break;
|
|
case WrapAroundEnding:
|
|
iPrev = pp.length - 2;
|
|
tPrev = t0 + pp[iPrev] - pp[iPrev + 1];
|
|
break;
|
|
default:
|
|
iPrev = i1;
|
|
tPrev = t1;
|
|
}
|
|
}
|
|
if (tNext === void 0) {
|
|
switch (this.getSettings_().endingEnd) {
|
|
case ZeroSlopeEnding:
|
|
iNext = i1;
|
|
tNext = 2 * t1 - t0;
|
|
break;
|
|
case WrapAroundEnding:
|
|
iNext = 1;
|
|
tNext = t1 + pp[1] - pp[0];
|
|
break;
|
|
default:
|
|
iNext = i1 - 1;
|
|
tNext = t0;
|
|
}
|
|
}
|
|
const halfDt = (t1 - t0) * 0.5, stride = this.valueSize;
|
|
this._weightPrev = halfDt / (t0 - tPrev);
|
|
this._weightNext = halfDt / (tNext - t1);
|
|
this._offsetPrev = iPrev * stride;
|
|
this._offsetNext = iNext * stride;
|
|
}
|
|
interpolate_(i1, t0, t, t1) {
|
|
const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, o1 = i1 * stride, o0 = o1 - stride, oP = this._offsetPrev, oN = this._offsetNext, wP = this._weightPrev, wN = this._weightNext, p2 = (t - t0) / (t1 - t0), pp = p2 * p2, ppp = pp * p2;
|
|
const sP = -wP * ppp + 2 * wP * pp - wP * p2;
|
|
const s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p2 + 1;
|
|
const s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p2;
|
|
const sN = wN * ppp - wN * pp;
|
|
for (let i = 0; i !== stride; ++i) {
|
|
result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i];
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
var LinearInterpolant = class extends Interpolant {
|
|
constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
|
|
super(parameterPositions, sampleValues, sampleSize, resultBuffer);
|
|
}
|
|
interpolate_(i1, t0, t, t1) {
|
|
const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset1 = i1 * stride, offset0 = offset1 - stride, weight1 = (t - t0) / (t1 - t0), weight0 = 1 - weight1;
|
|
for (let i = 0; i !== stride; ++i) {
|
|
result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1;
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
var DiscreteInterpolant = class extends Interpolant {
|
|
constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
|
|
super(parameterPositions, sampleValues, sampleSize, resultBuffer);
|
|
}
|
|
interpolate_(i1) {
|
|
return this.copySampleValue_(i1 - 1);
|
|
}
|
|
};
|
|
var KeyframeTrack = class {
|
|
constructor(name, times, values, interpolation) {
|
|
if (name === void 0)
|
|
throw new Error("THREE.KeyframeTrack: track name is undefined");
|
|
if (times === void 0 || times.length === 0)
|
|
throw new Error("THREE.KeyframeTrack: no keyframes in track named " + name);
|
|
this.name = name;
|
|
this.times = AnimationUtils.convertArray(times, this.TimeBufferType);
|
|
this.values = AnimationUtils.convertArray(values, this.ValueBufferType);
|
|
this.setInterpolation(interpolation || this.DefaultInterpolation);
|
|
}
|
|
static toJSON(track) {
|
|
const trackType = track.constructor;
|
|
let json;
|
|
if (trackType.toJSON !== this.toJSON) {
|
|
json = trackType.toJSON(track);
|
|
} else {
|
|
json = {
|
|
"name": track.name,
|
|
"times": AnimationUtils.convertArray(track.times, Array),
|
|
"values": AnimationUtils.convertArray(track.values, Array)
|
|
};
|
|
const interpolation = track.getInterpolation();
|
|
if (interpolation !== track.DefaultInterpolation) {
|
|
json.interpolation = interpolation;
|
|
}
|
|
}
|
|
json.type = track.ValueTypeName;
|
|
return json;
|
|
}
|
|
InterpolantFactoryMethodDiscrete(result) {
|
|
return new DiscreteInterpolant(this.times, this.values, this.getValueSize(), result);
|
|
}
|
|
InterpolantFactoryMethodLinear(result) {
|
|
return new LinearInterpolant(this.times, this.values, this.getValueSize(), result);
|
|
}
|
|
InterpolantFactoryMethodSmooth(result) {
|
|
return new CubicInterpolant(this.times, this.values, this.getValueSize(), result);
|
|
}
|
|
setInterpolation(interpolation) {
|
|
let factoryMethod;
|
|
switch (interpolation) {
|
|
case InterpolateDiscrete:
|
|
factoryMethod = this.InterpolantFactoryMethodDiscrete;
|
|
break;
|
|
case InterpolateLinear:
|
|
factoryMethod = this.InterpolantFactoryMethodLinear;
|
|
break;
|
|
case InterpolateSmooth:
|
|
factoryMethod = this.InterpolantFactoryMethodSmooth;
|
|
break;
|
|
}
|
|
if (factoryMethod === void 0) {
|
|
const message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name;
|
|
if (this.createInterpolant === void 0) {
|
|
if (interpolation !== this.DefaultInterpolation) {
|
|
this.setInterpolation(this.DefaultInterpolation);
|
|
} else {
|
|
throw new Error(message);
|
|
}
|
|
}
|
|
console.warn("THREE.KeyframeTrack:", message);
|
|
return this;
|
|
}
|
|
this.createInterpolant = factoryMethod;
|
|
return this;
|
|
}
|
|
getInterpolation() {
|
|
switch (this.createInterpolant) {
|
|
case this.InterpolantFactoryMethodDiscrete:
|
|
return InterpolateDiscrete;
|
|
case this.InterpolantFactoryMethodLinear:
|
|
return InterpolateLinear;
|
|
case this.InterpolantFactoryMethodSmooth:
|
|
return InterpolateSmooth;
|
|
}
|
|
}
|
|
getValueSize() {
|
|
return this.values.length / this.times.length;
|
|
}
|
|
shift(timeOffset) {
|
|
if (timeOffset !== 0) {
|
|
const times = this.times;
|
|
for (let i = 0, n = times.length; i !== n; ++i) {
|
|
times[i] += timeOffset;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
scale(timeScale) {
|
|
if (timeScale !== 1) {
|
|
const times = this.times;
|
|
for (let i = 0, n = times.length; i !== n; ++i) {
|
|
times[i] *= timeScale;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
trim(startTime, endTime) {
|
|
const times = this.times, nKeys = times.length;
|
|
let from = 0, to = nKeys - 1;
|
|
while (from !== nKeys && times[from] < startTime) {
|
|
++from;
|
|
}
|
|
while (to !== -1 && times[to] > endTime) {
|
|
--to;
|
|
}
|
|
++to;
|
|
if (from !== 0 || to !== nKeys) {
|
|
if (from >= to) {
|
|
to = Math.max(to, 1);
|
|
from = to - 1;
|
|
}
|
|
const stride = this.getValueSize();
|
|
this.times = AnimationUtils.arraySlice(times, from, to);
|
|
this.values = AnimationUtils.arraySlice(this.values, from * stride, to * stride);
|
|
}
|
|
return this;
|
|
}
|
|
validate() {
|
|
let valid = true;
|
|
const valueSize = this.getValueSize();
|
|
if (valueSize - Math.floor(valueSize) !== 0) {
|
|
console.error("THREE.KeyframeTrack: Invalid value size in track.", this);
|
|
valid = false;
|
|
}
|
|
const times = this.times, values = this.values, nKeys = times.length;
|
|
if (nKeys === 0) {
|
|
console.error("THREE.KeyframeTrack: Track is empty.", this);
|
|
valid = false;
|
|
}
|
|
let prevTime = null;
|
|
for (let i = 0; i !== nKeys; i++) {
|
|
const currTime = times[i];
|
|
if (typeof currTime === "number" && isNaN(currTime)) {
|
|
console.error("THREE.KeyframeTrack: Time is not a valid number.", this, i, currTime);
|
|
valid = false;
|
|
break;
|
|
}
|
|
if (prevTime !== null && prevTime > currTime) {
|
|
console.error("THREE.KeyframeTrack: Out of order keys.", this, i, currTime, prevTime);
|
|
valid = false;
|
|
break;
|
|
}
|
|
prevTime = currTime;
|
|
}
|
|
if (values !== void 0) {
|
|
if (AnimationUtils.isTypedArray(values)) {
|
|
for (let i = 0, n = values.length; i !== n; ++i) {
|
|
const value = values[i];
|
|
if (isNaN(value)) {
|
|
console.error("THREE.KeyframeTrack: Value is not a valid number.", this, i, value);
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return valid;
|
|
}
|
|
optimize() {
|
|
const times = AnimationUtils.arraySlice(this.times), values = AnimationUtils.arraySlice(this.values), stride = this.getValueSize(), smoothInterpolation = this.getInterpolation() === InterpolateSmooth, lastIndex = times.length - 1;
|
|
let writeIndex = 1;
|
|
for (let i = 1; i < lastIndex; ++i) {
|
|
let keep = false;
|
|
const time = times[i];
|
|
const timeNext = times[i + 1];
|
|
if (time !== timeNext && (i !== 1 || time !== times[0])) {
|
|
if (!smoothInterpolation) {
|
|
const offset = i * stride, offsetP = offset - stride, offsetN = offset + stride;
|
|
for (let j = 0; j !== stride; ++j) {
|
|
const value = values[offset + j];
|
|
if (value !== values[offsetP + j] || value !== values[offsetN + j]) {
|
|
keep = true;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
keep = true;
|
|
}
|
|
}
|
|
if (keep) {
|
|
if (i !== writeIndex) {
|
|
times[writeIndex] = times[i];
|
|
const readOffset = i * stride, writeOffset = writeIndex * stride;
|
|
for (let j = 0; j !== stride; ++j) {
|
|
values[writeOffset + j] = values[readOffset + j];
|
|
}
|
|
}
|
|
++writeIndex;
|
|
}
|
|
}
|
|
if (lastIndex > 0) {
|
|
times[writeIndex] = times[lastIndex];
|
|
for (let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++j) {
|
|
values[writeOffset + j] = values[readOffset + j];
|
|
}
|
|
++writeIndex;
|
|
}
|
|
if (writeIndex !== times.length) {
|
|
this.times = AnimationUtils.arraySlice(times, 0, writeIndex);
|
|
this.values = AnimationUtils.arraySlice(values, 0, writeIndex * stride);
|
|
} else {
|
|
this.times = times;
|
|
this.values = values;
|
|
}
|
|
return this;
|
|
}
|
|
clone() {
|
|
const times = AnimationUtils.arraySlice(this.times, 0);
|
|
const values = AnimationUtils.arraySlice(this.values, 0);
|
|
const TypedKeyframeTrack = this.constructor;
|
|
const track = new TypedKeyframeTrack(this.name, times, values);
|
|
track.createInterpolant = this.createInterpolant;
|
|
return track;
|
|
}
|
|
};
|
|
KeyframeTrack.prototype.TimeBufferType = Float32Array;
|
|
KeyframeTrack.prototype.ValueBufferType = Float32Array;
|
|
KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
|
|
var BooleanKeyframeTrack = class extends KeyframeTrack {
|
|
};
|
|
BooleanKeyframeTrack.prototype.ValueTypeName = "bool";
|
|
BooleanKeyframeTrack.prototype.ValueBufferType = Array;
|
|
BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
|
|
BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = void 0;
|
|
BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0;
|
|
var ColorKeyframeTrack = class extends KeyframeTrack {
|
|
};
|
|
ColorKeyframeTrack.prototype.ValueTypeName = "color";
|
|
var NumberKeyframeTrack = class extends KeyframeTrack {
|
|
};
|
|
NumberKeyframeTrack.prototype.ValueTypeName = "number";
|
|
var QuaternionLinearInterpolant = class extends Interpolant {
|
|
constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
|
|
super(parameterPositions, sampleValues, sampleSize, resultBuffer);
|
|
}
|
|
interpolate_(i1, t0, t, t1) {
|
|
const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, alpha = (t - t0) / (t1 - t0);
|
|
let offset = i1 * stride;
|
|
for (let end = offset + stride; offset !== end; offset += 4) {
|
|
Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha);
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
var QuaternionKeyframeTrack = class extends KeyframeTrack {
|
|
InterpolantFactoryMethodLinear(result) {
|
|
return new QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result);
|
|
}
|
|
};
|
|
QuaternionKeyframeTrack.prototype.ValueTypeName = "quaternion";
|
|
QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
|
|
QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0;
|
|
var StringKeyframeTrack = class extends KeyframeTrack {
|
|
};
|
|
StringKeyframeTrack.prototype.ValueTypeName = "string";
|
|
StringKeyframeTrack.prototype.ValueBufferType = Array;
|
|
StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
|
|
StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = void 0;
|
|
StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0;
|
|
var VectorKeyframeTrack = class extends KeyframeTrack {
|
|
};
|
|
VectorKeyframeTrack.prototype.ValueTypeName = "vector";
|
|
var AnimationClip = class {
|
|
constructor(name, duration = -1, tracks, blendMode = NormalAnimationBlendMode) {
|
|
this.name = name;
|
|
this.tracks = tracks;
|
|
this.duration = duration;
|
|
this.blendMode = blendMode;
|
|
this.uuid = generateUUID();
|
|
if (this.duration < 0) {
|
|
this.resetDuration();
|
|
}
|
|
}
|
|
static parse(json) {
|
|
const tracks = [], jsonTracks = json.tracks, frameTime = 1 / (json.fps || 1);
|
|
for (let i = 0, n = jsonTracks.length; i !== n; ++i) {
|
|
tracks.push(parseKeyframeTrack(jsonTracks[i]).scale(frameTime));
|
|
}
|
|
const clip = new this(json.name, json.duration, tracks, json.blendMode);
|
|
clip.uuid = json.uuid;
|
|
return clip;
|
|
}
|
|
static toJSON(clip) {
|
|
const tracks = [], clipTracks = clip.tracks;
|
|
const json = {
|
|
"name": clip.name,
|
|
"duration": clip.duration,
|
|
"tracks": tracks,
|
|
"uuid": clip.uuid,
|
|
"blendMode": clip.blendMode
|
|
};
|
|
for (let i = 0, n = clipTracks.length; i !== n; ++i) {
|
|
tracks.push(KeyframeTrack.toJSON(clipTracks[i]));
|
|
}
|
|
return json;
|
|
}
|
|
static CreateFromMorphTargetSequence(name, morphTargetSequence, fps, noLoop) {
|
|
const numMorphTargets = morphTargetSequence.length;
|
|
const tracks = [];
|
|
for (let i = 0; i < numMorphTargets; i++) {
|
|
let times = [];
|
|
let values = [];
|
|
times.push((i + numMorphTargets - 1) % numMorphTargets, i, (i + 1) % numMorphTargets);
|
|
values.push(0, 1, 0);
|
|
const order = AnimationUtils.getKeyframeOrder(times);
|
|
times = AnimationUtils.sortedArray(times, 1, order);
|
|
values = AnimationUtils.sortedArray(values, 1, order);
|
|
if (!noLoop && times[0] === 0) {
|
|
times.push(numMorphTargets);
|
|
values.push(values[0]);
|
|
}
|
|
tracks.push(new NumberKeyframeTrack(".morphTargetInfluences[" + morphTargetSequence[i].name + "]", times, values).scale(1 / fps));
|
|
}
|
|
return new this(name, -1, tracks);
|
|
}
|
|
static findByName(objectOrClipArray, name) {
|
|
let clipArray = objectOrClipArray;
|
|
if (!Array.isArray(objectOrClipArray)) {
|
|
const o = objectOrClipArray;
|
|
clipArray = o.geometry && o.geometry.animations || o.animations;
|
|
}
|
|
for (let i = 0; i < clipArray.length; i++) {
|
|
if (clipArray[i].name === name) {
|
|
return clipArray[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
static CreateClipsFromMorphTargetSequences(morphTargets, fps, noLoop) {
|
|
const animationToMorphTargets = {};
|
|
const pattern = /^([\w-]*?)([\d]+)$/;
|
|
for (let i = 0, il = morphTargets.length; i < il; i++) {
|
|
const morphTarget = morphTargets[i];
|
|
const parts = morphTarget.name.match(pattern);
|
|
if (parts && parts.length > 1) {
|
|
const name = parts[1];
|
|
let animationMorphTargets = animationToMorphTargets[name];
|
|
if (!animationMorphTargets) {
|
|
animationToMorphTargets[name] = animationMorphTargets = [];
|
|
}
|
|
animationMorphTargets.push(morphTarget);
|
|
}
|
|
}
|
|
const clips = [];
|
|
for (const name in animationToMorphTargets) {
|
|
clips.push(this.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop));
|
|
}
|
|
return clips;
|
|
}
|
|
static parseAnimation(animation, bones) {
|
|
if (!animation) {
|
|
console.error("THREE.AnimationClip: No animation in JSONLoader data.");
|
|
return null;
|
|
}
|
|
const addNonemptyTrack = function(trackType, trackName, animationKeys, propertyName, destTracks) {
|
|
if (animationKeys.length !== 0) {
|
|
const times = [];
|
|
const values = [];
|
|
AnimationUtils.flattenJSON(animationKeys, times, values, propertyName);
|
|
if (times.length !== 0) {
|
|
destTracks.push(new trackType(trackName, times, values));
|
|
}
|
|
}
|
|
};
|
|
const tracks = [];
|
|
const clipName = animation.name || "default";
|
|
const fps = animation.fps || 30;
|
|
const blendMode = animation.blendMode;
|
|
let duration = animation.length || -1;
|
|
const hierarchyTracks = animation.hierarchy || [];
|
|
for (let h = 0; h < hierarchyTracks.length; h++) {
|
|
const animationKeys = hierarchyTracks[h].keys;
|
|
if (!animationKeys || animationKeys.length === 0)
|
|
continue;
|
|
if (animationKeys[0].morphTargets) {
|
|
const morphTargetNames = {};
|
|
let k;
|
|
for (k = 0; k < animationKeys.length; k++) {
|
|
if (animationKeys[k].morphTargets) {
|
|
for (let m = 0; m < animationKeys[k].morphTargets.length; m++) {
|
|
morphTargetNames[animationKeys[k].morphTargets[m]] = -1;
|
|
}
|
|
}
|
|
}
|
|
for (const morphTargetName in morphTargetNames) {
|
|
const times = [];
|
|
const values = [];
|
|
for (let m = 0; m !== animationKeys[k].morphTargets.length; ++m) {
|
|
const animationKey = animationKeys[k];
|
|
times.push(animationKey.time);
|
|
values.push(animationKey.morphTarget === morphTargetName ? 1 : 0);
|
|
}
|
|
tracks.push(new NumberKeyframeTrack(".morphTargetInfluence[" + morphTargetName + "]", times, values));
|
|
}
|
|
duration = morphTargetNames.length * (fps || 1);
|
|
} else {
|
|
const boneName = ".bones[" + bones[h].name + "]";
|
|
addNonemptyTrack(VectorKeyframeTrack, boneName + ".position", animationKeys, "pos", tracks);
|
|
addNonemptyTrack(QuaternionKeyframeTrack, boneName + ".quaternion", animationKeys, "rot", tracks);
|
|
addNonemptyTrack(VectorKeyframeTrack, boneName + ".scale", animationKeys, "scl", tracks);
|
|
}
|
|
}
|
|
if (tracks.length === 0) {
|
|
return null;
|
|
}
|
|
const clip = new this(clipName, duration, tracks, blendMode);
|
|
return clip;
|
|
}
|
|
resetDuration() {
|
|
const tracks = this.tracks;
|
|
let duration = 0;
|
|
for (let i = 0, n = tracks.length; i !== n; ++i) {
|
|
const track = this.tracks[i];
|
|
duration = Math.max(duration, track.times[track.times.length - 1]);
|
|
}
|
|
this.duration = duration;
|
|
return this;
|
|
}
|
|
trim() {
|
|
for (let i = 0; i < this.tracks.length; i++) {
|
|
this.tracks[i].trim(0, this.duration);
|
|
}
|
|
return this;
|
|
}
|
|
validate() {
|
|
let valid = true;
|
|
for (let i = 0; i < this.tracks.length; i++) {
|
|
valid = valid && this.tracks[i].validate();
|
|
}
|
|
return valid;
|
|
}
|
|
optimize() {
|
|
for (let i = 0; i < this.tracks.length; i++) {
|
|
this.tracks[i].optimize();
|
|
}
|
|
return this;
|
|
}
|
|
clone() {
|
|
const tracks = [];
|
|
for (let i = 0; i < this.tracks.length; i++) {
|
|
tracks.push(this.tracks[i].clone());
|
|
}
|
|
return new this.constructor(this.name, this.duration, tracks, this.blendMode);
|
|
}
|
|
toJSON() {
|
|
return this.constructor.toJSON(this);
|
|
}
|
|
};
|
|
function getTrackTypeForValueTypeName(typeName) {
|
|
switch (typeName.toLowerCase()) {
|
|
case "scalar":
|
|
case "double":
|
|
case "float":
|
|
case "number":
|
|
case "integer":
|
|
return NumberKeyframeTrack;
|
|
case "vector":
|
|
case "vector2":
|
|
case "vector3":
|
|
case "vector4":
|
|
return VectorKeyframeTrack;
|
|
case "color":
|
|
return ColorKeyframeTrack;
|
|
case "quaternion":
|
|
return QuaternionKeyframeTrack;
|
|
case "bool":
|
|
case "boolean":
|
|
return BooleanKeyframeTrack;
|
|
case "string":
|
|
return StringKeyframeTrack;
|
|
}
|
|
throw new Error("THREE.KeyframeTrack: Unsupported typeName: " + typeName);
|
|
}
|
|
function parseKeyframeTrack(json) {
|
|
if (json.type === void 0) {
|
|
throw new Error("THREE.KeyframeTrack: track type undefined, can not parse");
|
|
}
|
|
const trackType = getTrackTypeForValueTypeName(json.type);
|
|
if (json.times === void 0) {
|
|
const times = [], values = [];
|
|
AnimationUtils.flattenJSON(json.keys, times, values, "value");
|
|
json.times = times;
|
|
json.values = values;
|
|
}
|
|
if (trackType.parse !== void 0) {
|
|
return trackType.parse(json);
|
|
} else {
|
|
return new trackType(json.name, json.times, json.values, json.interpolation);
|
|
}
|
|
}
|
|
var Cache = {
|
|
enabled: false,
|
|
files: {},
|
|
add: function(key, file) {
|
|
if (this.enabled === false)
|
|
return;
|
|
this.files[key] = file;
|
|
},
|
|
get: function(key) {
|
|
if (this.enabled === false)
|
|
return;
|
|
return this.files[key];
|
|
},
|
|
remove: function(key) {
|
|
delete this.files[key];
|
|
},
|
|
clear: function() {
|
|
this.files = {};
|
|
}
|
|
};
|
|
var LoadingManager = class {
|
|
constructor(onLoad, onProgress, onError) {
|
|
const scope = this;
|
|
let isLoading = false;
|
|
let itemsLoaded = 0;
|
|
let itemsTotal = 0;
|
|
let urlModifier = void 0;
|
|
const handlers = [];
|
|
this.onStart = void 0;
|
|
this.onLoad = onLoad;
|
|
this.onProgress = onProgress;
|
|
this.onError = onError;
|
|
this.itemStart = function(url) {
|
|
itemsTotal++;
|
|
if (isLoading === false) {
|
|
if (scope.onStart !== void 0) {
|
|
scope.onStart(url, itemsLoaded, itemsTotal);
|
|
}
|
|
}
|
|
isLoading = true;
|
|
};
|
|
this.itemEnd = function(url) {
|
|
itemsLoaded++;
|
|
if (scope.onProgress !== void 0) {
|
|
scope.onProgress(url, itemsLoaded, itemsTotal);
|
|
}
|
|
if (itemsLoaded === itemsTotal) {
|
|
isLoading = false;
|
|
if (scope.onLoad !== void 0) {
|
|
scope.onLoad();
|
|
}
|
|
}
|
|
};
|
|
this.itemError = function(url) {
|
|
if (scope.onError !== void 0) {
|
|
scope.onError(url);
|
|
}
|
|
};
|
|
this.resolveURL = function(url) {
|
|
if (urlModifier) {
|
|
return urlModifier(url);
|
|
}
|
|
return url;
|
|
};
|
|
this.setURLModifier = function(transform) {
|
|
urlModifier = transform;
|
|
return this;
|
|
};
|
|
this.addHandler = function(regex, loader) {
|
|
handlers.push(regex, loader);
|
|
return this;
|
|
};
|
|
this.removeHandler = function(regex) {
|
|
const index = handlers.indexOf(regex);
|
|
if (index !== -1) {
|
|
handlers.splice(index, 2);
|
|
}
|
|
return this;
|
|
};
|
|
this.getHandler = function(file) {
|
|
for (let i = 0, l = handlers.length; i < l; i += 2) {
|
|
const regex = handlers[i];
|
|
const loader = handlers[i + 1];
|
|
if (regex.global)
|
|
regex.lastIndex = 0;
|
|
if (regex.test(file)) {
|
|
return loader;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
}
|
|
};
|
|
var DefaultLoadingManager = new LoadingManager();
|
|
var Loader = class {
|
|
constructor(manager) {
|
|
this.manager = manager !== void 0 ? manager : DefaultLoadingManager;
|
|
this.crossOrigin = "anonymous";
|
|
this.withCredentials = false;
|
|
this.path = "";
|
|
this.resourcePath = "";
|
|
this.requestHeader = {};
|
|
}
|
|
load() {
|
|
}
|
|
loadAsync(url, onProgress) {
|
|
const scope = this;
|
|
return new Promise(function(resolve2, reject2) {
|
|
scope.load(url, resolve2, onProgress, reject2);
|
|
});
|
|
}
|
|
parse() {
|
|
}
|
|
setCrossOrigin(crossOrigin) {
|
|
this.crossOrigin = crossOrigin;
|
|
return this;
|
|
}
|
|
setWithCredentials(value) {
|
|
this.withCredentials = value;
|
|
return this;
|
|
}
|
|
setPath(path) {
|
|
this.path = path;
|
|
return this;
|
|
}
|
|
setResourcePath(resourcePath) {
|
|
this.resourcePath = resourcePath;
|
|
return this;
|
|
}
|
|
setRequestHeader(requestHeader) {
|
|
this.requestHeader = requestHeader;
|
|
return this;
|
|
}
|
|
};
|
|
var loading = {};
|
|
var FileLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
if (url === void 0)
|
|
url = "";
|
|
if (this.path !== void 0)
|
|
url = this.path + url;
|
|
url = this.manager.resolveURL(url);
|
|
const scope = this;
|
|
const cached = Cache.get(url);
|
|
if (cached !== void 0) {
|
|
scope.manager.itemStart(url);
|
|
setTimeout(function() {
|
|
if (onLoad)
|
|
onLoad(cached);
|
|
scope.manager.itemEnd(url);
|
|
}, 0);
|
|
return cached;
|
|
}
|
|
if (loading[url] !== void 0) {
|
|
loading[url].push({
|
|
onLoad,
|
|
onProgress,
|
|
onError
|
|
});
|
|
return;
|
|
}
|
|
const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
|
|
const dataUriRegexResult = url.match(dataUriRegex);
|
|
let request;
|
|
if (dataUriRegexResult) {
|
|
const mimeType = dataUriRegexResult[1];
|
|
const isBase64 = !!dataUriRegexResult[2];
|
|
let data = dataUriRegexResult[3];
|
|
data = decodeURIComponent(data);
|
|
if (isBase64)
|
|
data = atob(data);
|
|
try {
|
|
let response;
|
|
const responseType = (this.responseType || "").toLowerCase();
|
|
switch (responseType) {
|
|
case "arraybuffer":
|
|
case "blob":
|
|
const view = new Uint8Array(data.length);
|
|
for (let i = 0; i < data.length; i++) {
|
|
view[i] = data.charCodeAt(i);
|
|
}
|
|
if (responseType === "blob") {
|
|
response = new Blob([view.buffer], { type: mimeType });
|
|
} else {
|
|
response = view.buffer;
|
|
}
|
|
break;
|
|
case "document":
|
|
const parser = new DOMParser();
|
|
response = parser.parseFromString(data, mimeType);
|
|
break;
|
|
case "json":
|
|
response = JSON.parse(data);
|
|
break;
|
|
default:
|
|
response = data;
|
|
break;
|
|
}
|
|
setTimeout(function() {
|
|
if (onLoad)
|
|
onLoad(response);
|
|
scope.manager.itemEnd(url);
|
|
}, 0);
|
|
} catch (error) {
|
|
setTimeout(function() {
|
|
if (onError)
|
|
onError(error);
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
}, 0);
|
|
}
|
|
} else {
|
|
loading[url] = [];
|
|
loading[url].push({
|
|
onLoad,
|
|
onProgress,
|
|
onError
|
|
});
|
|
request = new XMLHttpRequest();
|
|
request.open("GET", url, true);
|
|
request.addEventListener("load", function(event) {
|
|
const response = this.response;
|
|
const callbacks = loading[url];
|
|
delete loading[url];
|
|
if (this.status === 200 || this.status === 0) {
|
|
if (this.status === 0)
|
|
console.warn("THREE.FileLoader: HTTP Status 0 received.");
|
|
Cache.add(url, response);
|
|
for (let i = 0, il = callbacks.length; i < il; i++) {
|
|
const callback = callbacks[i];
|
|
if (callback.onLoad)
|
|
callback.onLoad(response);
|
|
}
|
|
scope.manager.itemEnd(url);
|
|
} else {
|
|
for (let i = 0, il = callbacks.length; i < il; i++) {
|
|
const callback = callbacks[i];
|
|
if (callback.onError)
|
|
callback.onError(event);
|
|
}
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
}
|
|
}, false);
|
|
request.addEventListener("progress", function(event) {
|
|
const callbacks = loading[url];
|
|
for (let i = 0, il = callbacks.length; i < il; i++) {
|
|
const callback = callbacks[i];
|
|
if (callback.onProgress)
|
|
callback.onProgress(event);
|
|
}
|
|
}, false);
|
|
request.addEventListener("error", function(event) {
|
|
const callbacks = loading[url];
|
|
delete loading[url];
|
|
for (let i = 0, il = callbacks.length; i < il; i++) {
|
|
const callback = callbacks[i];
|
|
if (callback.onError)
|
|
callback.onError(event);
|
|
}
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
}, false);
|
|
request.addEventListener("abort", function(event) {
|
|
const callbacks = loading[url];
|
|
delete loading[url];
|
|
for (let i = 0, il = callbacks.length; i < il; i++) {
|
|
const callback = callbacks[i];
|
|
if (callback.onError)
|
|
callback.onError(event);
|
|
}
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
}, false);
|
|
if (this.responseType !== void 0)
|
|
request.responseType = this.responseType;
|
|
if (this.withCredentials !== void 0)
|
|
request.withCredentials = this.withCredentials;
|
|
if (request.overrideMimeType)
|
|
request.overrideMimeType(this.mimeType !== void 0 ? this.mimeType : "text/plain");
|
|
for (const header in this.requestHeader) {
|
|
request.setRequestHeader(header, this.requestHeader[header]);
|
|
}
|
|
request.send(null);
|
|
}
|
|
scope.manager.itemStart(url);
|
|
return request;
|
|
}
|
|
setResponseType(value) {
|
|
this.responseType = value;
|
|
return this;
|
|
}
|
|
setMimeType(value) {
|
|
this.mimeType = value;
|
|
return this;
|
|
}
|
|
};
|
|
var ImageLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
if (this.path !== void 0)
|
|
url = this.path + url;
|
|
url = this.manager.resolveURL(url);
|
|
const scope = this;
|
|
const cached = Cache.get(url);
|
|
if (cached !== void 0) {
|
|
scope.manager.itemStart(url);
|
|
setTimeout(function() {
|
|
if (onLoad)
|
|
onLoad(cached);
|
|
scope.manager.itemEnd(url);
|
|
}, 0);
|
|
return cached;
|
|
}
|
|
const image = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
|
|
function onImageLoad() {
|
|
image.removeEventListener("load", onImageLoad, false);
|
|
image.removeEventListener("error", onImageError, false);
|
|
Cache.add(url, this);
|
|
if (onLoad)
|
|
onLoad(this);
|
|
scope.manager.itemEnd(url);
|
|
}
|
|
function onImageError(event) {
|
|
image.removeEventListener("load", onImageLoad, false);
|
|
image.removeEventListener("error", onImageError, false);
|
|
if (onError)
|
|
onError(event);
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
}
|
|
image.addEventListener("load", onImageLoad, false);
|
|
image.addEventListener("error", onImageError, false);
|
|
if (url.substr(0, 5) !== "data:") {
|
|
if (this.crossOrigin !== void 0)
|
|
image.crossOrigin = this.crossOrigin;
|
|
}
|
|
scope.manager.itemStart(url);
|
|
image.src = url;
|
|
return image;
|
|
}
|
|
};
|
|
var CubeTextureLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
}
|
|
load(urls, onLoad, onProgress, onError) {
|
|
const texture = new CubeTexture();
|
|
const loader = new ImageLoader(this.manager);
|
|
loader.setCrossOrigin(this.crossOrigin);
|
|
loader.setPath(this.path);
|
|
let loaded2 = 0;
|
|
function loadTexture(i) {
|
|
loader.load(urls[i], function(image) {
|
|
texture.images[i] = image;
|
|
loaded2++;
|
|
if (loaded2 === 6) {
|
|
texture.needsUpdate = true;
|
|
if (onLoad)
|
|
onLoad(texture);
|
|
}
|
|
}, void 0, onError);
|
|
}
|
|
for (let i = 0; i < urls.length; ++i) {
|
|
loadTexture(i);
|
|
}
|
|
return texture;
|
|
}
|
|
};
|
|
var TextureLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
const texture = new Texture();
|
|
const loader = new ImageLoader(this.manager);
|
|
loader.setCrossOrigin(this.crossOrigin);
|
|
loader.setPath(this.path);
|
|
loader.load(url, function(image) {
|
|
texture.image = image;
|
|
const isJPEG = url.search(/\.jpe?g($|\?)/i) > 0 || url.search(/^data\:image\/jpeg/) === 0;
|
|
texture.format = isJPEG ? RGBFormat : RGBAFormat;
|
|
texture.needsUpdate = true;
|
|
if (onLoad !== void 0) {
|
|
onLoad(texture);
|
|
}
|
|
}, onProgress, onError);
|
|
return texture;
|
|
}
|
|
};
|
|
var CurvePath = class extends Curve {
|
|
constructor() {
|
|
super();
|
|
this.type = "CurvePath";
|
|
this.curves = [];
|
|
this.autoClose = false;
|
|
}
|
|
add(curve) {
|
|
this.curves.push(curve);
|
|
}
|
|
closePath() {
|
|
const startPoint = this.curves[0].getPoint(0);
|
|
const endPoint = this.curves[this.curves.length - 1].getPoint(1);
|
|
if (!startPoint.equals(endPoint)) {
|
|
this.curves.push(new LineCurve(endPoint, startPoint));
|
|
}
|
|
}
|
|
getPoint(t) {
|
|
const d = t * this.getLength();
|
|
const curveLengths = this.getCurveLengths();
|
|
let i = 0;
|
|
while (i < curveLengths.length) {
|
|
if (curveLengths[i] >= d) {
|
|
const diff = curveLengths[i] - d;
|
|
const curve = this.curves[i];
|
|
const segmentLength = curve.getLength();
|
|
const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
|
|
return curve.getPointAt(u);
|
|
}
|
|
i++;
|
|
}
|
|
return null;
|
|
}
|
|
getLength() {
|
|
const lens = this.getCurveLengths();
|
|
return lens[lens.length - 1];
|
|
}
|
|
updateArcLengths() {
|
|
this.needsUpdate = true;
|
|
this.cacheLengths = null;
|
|
this.getCurveLengths();
|
|
}
|
|
getCurveLengths() {
|
|
if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
|
|
return this.cacheLengths;
|
|
}
|
|
const lengths = [];
|
|
let sums = 0;
|
|
for (let i = 0, l = this.curves.length; i < l; i++) {
|
|
sums += this.curves[i].getLength();
|
|
lengths.push(sums);
|
|
}
|
|
this.cacheLengths = lengths;
|
|
return lengths;
|
|
}
|
|
getSpacedPoints(divisions = 40) {
|
|
const points = [];
|
|
for (let i = 0; i <= divisions; i++) {
|
|
points.push(this.getPoint(i / divisions));
|
|
}
|
|
if (this.autoClose) {
|
|
points.push(points[0]);
|
|
}
|
|
return points;
|
|
}
|
|
getPoints(divisions = 12) {
|
|
const points = [];
|
|
let last;
|
|
for (let i = 0, curves = this.curves; i < curves.length; i++) {
|
|
const curve = curves[i];
|
|
const resolution = curve && curve.isEllipseCurve ? divisions * 2 : curve && (curve.isLineCurve || curve.isLineCurve3) ? 1 : curve && curve.isSplineCurve ? divisions * curve.points.length : divisions;
|
|
const pts = curve.getPoints(resolution);
|
|
for (let j = 0; j < pts.length; j++) {
|
|
const point = pts[j];
|
|
if (last && last.equals(point))
|
|
continue;
|
|
points.push(point);
|
|
last = point;
|
|
}
|
|
}
|
|
if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) {
|
|
points.push(points[0]);
|
|
}
|
|
return points;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.curves = [];
|
|
for (let i = 0, l = source.curves.length; i < l; i++) {
|
|
const curve = source.curves[i];
|
|
this.curves.push(curve.clone());
|
|
}
|
|
this.autoClose = source.autoClose;
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.autoClose = this.autoClose;
|
|
data.curves = [];
|
|
for (let i = 0, l = this.curves.length; i < l; i++) {
|
|
const curve = this.curves[i];
|
|
data.curves.push(curve.toJSON());
|
|
}
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.autoClose = json.autoClose;
|
|
this.curves = [];
|
|
for (let i = 0, l = json.curves.length; i < l; i++) {
|
|
const curve = json.curves[i];
|
|
this.curves.push(new Curves[curve.type]().fromJSON(curve));
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var Path = class extends CurvePath {
|
|
constructor(points) {
|
|
super();
|
|
this.type = "Path";
|
|
this.currentPoint = new Vector2();
|
|
if (points) {
|
|
this.setFromPoints(points);
|
|
}
|
|
}
|
|
setFromPoints(points) {
|
|
this.moveTo(points[0].x, points[0].y);
|
|
for (let i = 1, l = points.length; i < l; i++) {
|
|
this.lineTo(points[i].x, points[i].y);
|
|
}
|
|
return this;
|
|
}
|
|
moveTo(x, y) {
|
|
this.currentPoint.set(x, y);
|
|
return this;
|
|
}
|
|
lineTo(x, y) {
|
|
const curve = new LineCurve(this.currentPoint.clone(), new Vector2(x, y));
|
|
this.curves.push(curve);
|
|
this.currentPoint.set(x, y);
|
|
return this;
|
|
}
|
|
quadraticCurveTo(aCPx, aCPy, aX, aY) {
|
|
const curve = new QuadraticBezierCurve(this.currentPoint.clone(), new Vector2(aCPx, aCPy), new Vector2(aX, aY));
|
|
this.curves.push(curve);
|
|
this.currentPoint.set(aX, aY);
|
|
return this;
|
|
}
|
|
bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
|
|
const curve = new CubicBezierCurve(this.currentPoint.clone(), new Vector2(aCP1x, aCP1y), new Vector2(aCP2x, aCP2y), new Vector2(aX, aY));
|
|
this.curves.push(curve);
|
|
this.currentPoint.set(aX, aY);
|
|
return this;
|
|
}
|
|
splineThru(pts) {
|
|
const npts = [this.currentPoint.clone()].concat(pts);
|
|
const curve = new SplineCurve(npts);
|
|
this.curves.push(curve);
|
|
this.currentPoint.copy(pts[pts.length - 1]);
|
|
return this;
|
|
}
|
|
arc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
|
|
const x0 = this.currentPoint.x;
|
|
const y0 = this.currentPoint.y;
|
|
this.absarc(aX + x0, aY + y0, aRadius, aStartAngle, aEndAngle, aClockwise);
|
|
return this;
|
|
}
|
|
absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
|
|
this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
|
|
return this;
|
|
}
|
|
ellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
|
|
const x0 = this.currentPoint.x;
|
|
const y0 = this.currentPoint.y;
|
|
this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
|
|
return this;
|
|
}
|
|
absellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
|
|
const curve = new EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
|
|
if (this.curves.length > 0) {
|
|
const firstPoint = curve.getPoint(0);
|
|
if (!firstPoint.equals(this.currentPoint)) {
|
|
this.lineTo(firstPoint.x, firstPoint.y);
|
|
}
|
|
}
|
|
this.curves.push(curve);
|
|
const lastPoint = curve.getPoint(1);
|
|
this.currentPoint.copy(lastPoint);
|
|
return this;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.currentPoint.copy(source.currentPoint);
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.currentPoint = this.currentPoint.toArray();
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.currentPoint.fromArray(json.currentPoint);
|
|
return this;
|
|
}
|
|
};
|
|
var Shape = class extends Path {
|
|
constructor(points) {
|
|
super(points);
|
|
this.uuid = generateUUID();
|
|
this.type = "Shape";
|
|
this.holes = [];
|
|
}
|
|
getPointsHoles(divisions) {
|
|
const holesPts = [];
|
|
for (let i = 0, l = this.holes.length; i < l; i++) {
|
|
holesPts[i] = this.holes[i].getPoints(divisions);
|
|
}
|
|
return holesPts;
|
|
}
|
|
extractPoints(divisions) {
|
|
return {
|
|
shape: this.getPoints(divisions),
|
|
holes: this.getPointsHoles(divisions)
|
|
};
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.holes = [];
|
|
for (let i = 0, l = source.holes.length; i < l; i++) {
|
|
const hole = source.holes[i];
|
|
this.holes.push(hole.clone());
|
|
}
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON();
|
|
data.uuid = this.uuid;
|
|
data.holes = [];
|
|
for (let i = 0, l = this.holes.length; i < l; i++) {
|
|
const hole = this.holes[i];
|
|
data.holes.push(hole.toJSON());
|
|
}
|
|
return data;
|
|
}
|
|
fromJSON(json) {
|
|
super.fromJSON(json);
|
|
this.uuid = json.uuid;
|
|
this.holes = [];
|
|
for (let i = 0, l = json.holes.length; i < l; i++) {
|
|
const hole = json.holes[i];
|
|
this.holes.push(new Path().fromJSON(hole));
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var Light = class extends Object3D {
|
|
constructor(color, intensity = 1) {
|
|
super();
|
|
this.type = "Light";
|
|
this.color = new Color(color);
|
|
this.intensity = intensity;
|
|
}
|
|
dispose() {
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.color.copy(source.color);
|
|
this.intensity = source.intensity;
|
|
return this;
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.object.color = this.color.getHex();
|
|
data.object.intensity = this.intensity;
|
|
if (this.groundColor !== void 0)
|
|
data.object.groundColor = this.groundColor.getHex();
|
|
if (this.distance !== void 0)
|
|
data.object.distance = this.distance;
|
|
if (this.angle !== void 0)
|
|
data.object.angle = this.angle;
|
|
if (this.decay !== void 0)
|
|
data.object.decay = this.decay;
|
|
if (this.penumbra !== void 0)
|
|
data.object.penumbra = this.penumbra;
|
|
if (this.shadow !== void 0)
|
|
data.object.shadow = this.shadow.toJSON();
|
|
return data;
|
|
}
|
|
};
|
|
Light.prototype.isLight = true;
|
|
var HemisphereLight = class extends Light {
|
|
constructor(skyColor, groundColor, intensity) {
|
|
super(skyColor, intensity);
|
|
this.type = "HemisphereLight";
|
|
this.position.copy(Object3D.DefaultUp);
|
|
this.updateMatrix();
|
|
this.groundColor = new Color(groundColor);
|
|
}
|
|
copy(source) {
|
|
Light.prototype.copy.call(this, source);
|
|
this.groundColor.copy(source.groundColor);
|
|
return this;
|
|
}
|
|
};
|
|
HemisphereLight.prototype.isHemisphereLight = true;
|
|
var _projScreenMatrix$1 = /* @__PURE__ */ new Matrix4();
|
|
var _lightPositionWorld$1 = /* @__PURE__ */ new Vector3();
|
|
var _lookTarget$1 = /* @__PURE__ */ new Vector3();
|
|
var LightShadow = class {
|
|
constructor(camera) {
|
|
this.camera = camera;
|
|
this.bias = 0;
|
|
this.normalBias = 0;
|
|
this.radius = 1;
|
|
this.blurSamples = 8;
|
|
this.mapSize = new Vector2(512, 512);
|
|
this.map = null;
|
|
this.mapPass = null;
|
|
this.matrix = new Matrix4();
|
|
this.autoUpdate = true;
|
|
this.needsUpdate = false;
|
|
this._frustum = new Frustum();
|
|
this._frameExtents = new Vector2(1, 1);
|
|
this._viewportCount = 1;
|
|
this._viewports = [
|
|
new Vector4(0, 0, 1, 1)
|
|
];
|
|
}
|
|
getViewportCount() {
|
|
return this._viewportCount;
|
|
}
|
|
getFrustum() {
|
|
return this._frustum;
|
|
}
|
|
updateMatrices(light) {
|
|
const shadowCamera = this.camera;
|
|
const shadowMatrix = this.matrix;
|
|
_lightPositionWorld$1.setFromMatrixPosition(light.matrixWorld);
|
|
shadowCamera.position.copy(_lightPositionWorld$1);
|
|
_lookTarget$1.setFromMatrixPosition(light.target.matrixWorld);
|
|
shadowCamera.lookAt(_lookTarget$1);
|
|
shadowCamera.updateMatrixWorld();
|
|
_projScreenMatrix$1.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
|
|
this._frustum.setFromProjectionMatrix(_projScreenMatrix$1);
|
|
shadowMatrix.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1);
|
|
shadowMatrix.multiply(shadowCamera.projectionMatrix);
|
|
shadowMatrix.multiply(shadowCamera.matrixWorldInverse);
|
|
}
|
|
getViewport(viewportIndex) {
|
|
return this._viewports[viewportIndex];
|
|
}
|
|
getFrameExtents() {
|
|
return this._frameExtents;
|
|
}
|
|
dispose() {
|
|
if (this.map) {
|
|
this.map.dispose();
|
|
}
|
|
if (this.mapPass) {
|
|
this.mapPass.dispose();
|
|
}
|
|
}
|
|
copy(source) {
|
|
this.camera = source.camera.clone();
|
|
this.bias = source.bias;
|
|
this.radius = source.radius;
|
|
this.mapSize.copy(source.mapSize);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
toJSON() {
|
|
const object = {};
|
|
if (this.bias !== 0)
|
|
object.bias = this.bias;
|
|
if (this.normalBias !== 0)
|
|
object.normalBias = this.normalBias;
|
|
if (this.radius !== 1)
|
|
object.radius = this.radius;
|
|
if (this.mapSize.x !== 512 || this.mapSize.y !== 512)
|
|
object.mapSize = this.mapSize.toArray();
|
|
object.camera = this.camera.toJSON(false).object;
|
|
delete object.camera.matrix;
|
|
return object;
|
|
}
|
|
};
|
|
var SpotLightShadow = class extends LightShadow {
|
|
constructor() {
|
|
super(new PerspectiveCamera(50, 1, 0.5, 500));
|
|
this.focus = 1;
|
|
}
|
|
updateMatrices(light) {
|
|
const camera = this.camera;
|
|
const fov2 = RAD2DEG * 2 * light.angle * this.focus;
|
|
const aspect2 = this.mapSize.width / this.mapSize.height;
|
|
const far = light.distance || camera.far;
|
|
if (fov2 !== camera.fov || aspect2 !== camera.aspect || far !== camera.far) {
|
|
camera.fov = fov2;
|
|
camera.aspect = aspect2;
|
|
camera.far = far;
|
|
camera.updateProjectionMatrix();
|
|
}
|
|
super.updateMatrices(light);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.focus = source.focus;
|
|
return this;
|
|
}
|
|
};
|
|
SpotLightShadow.prototype.isSpotLightShadow = true;
|
|
var SpotLight = class extends Light {
|
|
constructor(color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 1) {
|
|
super(color, intensity);
|
|
this.type = "SpotLight";
|
|
this.position.copy(Object3D.DefaultUp);
|
|
this.updateMatrix();
|
|
this.target = new Object3D();
|
|
this.distance = distance;
|
|
this.angle = angle;
|
|
this.penumbra = penumbra;
|
|
this.decay = decay;
|
|
this.shadow = new SpotLightShadow();
|
|
}
|
|
get power() {
|
|
return this.intensity * Math.PI;
|
|
}
|
|
set power(power) {
|
|
this.intensity = power / Math.PI;
|
|
}
|
|
dispose() {
|
|
this.shadow.dispose();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.distance = source.distance;
|
|
this.angle = source.angle;
|
|
this.penumbra = source.penumbra;
|
|
this.decay = source.decay;
|
|
this.target = source.target.clone();
|
|
this.shadow = source.shadow.clone();
|
|
return this;
|
|
}
|
|
};
|
|
SpotLight.prototype.isSpotLight = true;
|
|
var _projScreenMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _lightPositionWorld = /* @__PURE__ */ new Vector3();
|
|
var _lookTarget = /* @__PURE__ */ new Vector3();
|
|
var PointLightShadow = class extends LightShadow {
|
|
constructor() {
|
|
super(new PerspectiveCamera(90, 1, 0.5, 500));
|
|
this._frameExtents = new Vector2(4, 2);
|
|
this._viewportCount = 6;
|
|
this._viewports = [
|
|
new Vector4(2, 1, 1, 1),
|
|
new Vector4(0, 1, 1, 1),
|
|
new Vector4(3, 1, 1, 1),
|
|
new Vector4(1, 1, 1, 1),
|
|
new Vector4(3, 0, 1, 1),
|
|
new Vector4(1, 0, 1, 1)
|
|
];
|
|
this._cubeDirections = [
|
|
new Vector3(1, 0, 0),
|
|
new Vector3(-1, 0, 0),
|
|
new Vector3(0, 0, 1),
|
|
new Vector3(0, 0, -1),
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(0, -1, 0)
|
|
];
|
|
this._cubeUps = [
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(0, 0, 1),
|
|
new Vector3(0, 0, -1)
|
|
];
|
|
}
|
|
updateMatrices(light, viewportIndex = 0) {
|
|
const camera = this.camera;
|
|
const shadowMatrix = this.matrix;
|
|
const far = light.distance || camera.far;
|
|
if (far !== camera.far) {
|
|
camera.far = far;
|
|
camera.updateProjectionMatrix();
|
|
}
|
|
_lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
|
|
camera.position.copy(_lightPositionWorld);
|
|
_lookTarget.copy(camera.position);
|
|
_lookTarget.add(this._cubeDirections[viewportIndex]);
|
|
camera.up.copy(this._cubeUps[viewportIndex]);
|
|
camera.lookAt(_lookTarget);
|
|
camera.updateMatrixWorld();
|
|
shadowMatrix.makeTranslation(-_lightPositionWorld.x, -_lightPositionWorld.y, -_lightPositionWorld.z);
|
|
_projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
this._frustum.setFromProjectionMatrix(_projScreenMatrix);
|
|
}
|
|
};
|
|
PointLightShadow.prototype.isPointLightShadow = true;
|
|
var PointLight = class extends Light {
|
|
constructor(color, intensity, distance = 0, decay = 1) {
|
|
super(color, intensity);
|
|
this.type = "PointLight";
|
|
this.distance = distance;
|
|
this.decay = decay;
|
|
this.shadow = new PointLightShadow();
|
|
}
|
|
get power() {
|
|
return this.intensity * 4 * Math.PI;
|
|
}
|
|
set power(power) {
|
|
this.intensity = power / (4 * Math.PI);
|
|
}
|
|
dispose() {
|
|
this.shadow.dispose();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.distance = source.distance;
|
|
this.decay = source.decay;
|
|
this.shadow = source.shadow.clone();
|
|
return this;
|
|
}
|
|
};
|
|
PointLight.prototype.isPointLight = true;
|
|
var DirectionalLightShadow = class extends LightShadow {
|
|
constructor() {
|
|
super(new OrthographicCamera(-5, 5, 5, -5, 0.5, 500));
|
|
}
|
|
};
|
|
DirectionalLightShadow.prototype.isDirectionalLightShadow = true;
|
|
var DirectionalLight = class extends Light {
|
|
constructor(color, intensity) {
|
|
super(color, intensity);
|
|
this.type = "DirectionalLight";
|
|
this.position.copy(Object3D.DefaultUp);
|
|
this.updateMatrix();
|
|
this.target = new Object3D();
|
|
this.shadow = new DirectionalLightShadow();
|
|
}
|
|
dispose() {
|
|
this.shadow.dispose();
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.target = source.target.clone();
|
|
this.shadow = source.shadow.clone();
|
|
return this;
|
|
}
|
|
};
|
|
DirectionalLight.prototype.isDirectionalLight = true;
|
|
var AmbientLight = class extends Light {
|
|
constructor(color, intensity) {
|
|
super(color, intensity);
|
|
this.type = "AmbientLight";
|
|
}
|
|
};
|
|
AmbientLight.prototype.isAmbientLight = true;
|
|
var RectAreaLight = class extends Light {
|
|
constructor(color, intensity, width = 10, height = 10) {
|
|
super(color, intensity);
|
|
this.type = "RectAreaLight";
|
|
this.width = width;
|
|
this.height = height;
|
|
}
|
|
get power() {
|
|
return this.intensity * this.width * this.height * Math.PI;
|
|
}
|
|
set power(power) {
|
|
this.intensity = power / (this.width * this.height * Math.PI);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.width = source.width;
|
|
this.height = source.height;
|
|
return this;
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.object.width = this.width;
|
|
data.object.height = this.height;
|
|
return data;
|
|
}
|
|
};
|
|
RectAreaLight.prototype.isRectAreaLight = true;
|
|
var SphericalHarmonics3 = class {
|
|
constructor() {
|
|
this.coefficients = [];
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients.push(new Vector3());
|
|
}
|
|
}
|
|
set(coefficients) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].copy(coefficients[i]);
|
|
}
|
|
return this;
|
|
}
|
|
zero() {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].set(0, 0, 0);
|
|
}
|
|
return this;
|
|
}
|
|
getAt(normal, target) {
|
|
const x = normal.x, y = normal.y, z = normal.z;
|
|
const coeff = this.coefficients;
|
|
target.copy(coeff[0]).multiplyScalar(0.282095);
|
|
target.addScaledVector(coeff[1], 0.488603 * y);
|
|
target.addScaledVector(coeff[2], 0.488603 * z);
|
|
target.addScaledVector(coeff[3], 0.488603 * x);
|
|
target.addScaledVector(coeff[4], 1.092548 * (x * y));
|
|
target.addScaledVector(coeff[5], 1.092548 * (y * z));
|
|
target.addScaledVector(coeff[6], 0.315392 * (3 * z * z - 1));
|
|
target.addScaledVector(coeff[7], 1.092548 * (x * z));
|
|
target.addScaledVector(coeff[8], 0.546274 * (x * x - y * y));
|
|
return target;
|
|
}
|
|
getIrradianceAt(normal, target) {
|
|
const x = normal.x, y = normal.y, z = normal.z;
|
|
const coeff = this.coefficients;
|
|
target.copy(coeff[0]).multiplyScalar(0.886227);
|
|
target.addScaledVector(coeff[1], 2 * 0.511664 * y);
|
|
target.addScaledVector(coeff[2], 2 * 0.511664 * z);
|
|
target.addScaledVector(coeff[3], 2 * 0.511664 * x);
|
|
target.addScaledVector(coeff[4], 2 * 0.429043 * x * y);
|
|
target.addScaledVector(coeff[5], 2 * 0.429043 * y * z);
|
|
target.addScaledVector(coeff[6], 0.743125 * z * z - 0.247708);
|
|
target.addScaledVector(coeff[7], 2 * 0.429043 * x * z);
|
|
target.addScaledVector(coeff[8], 0.429043 * (x * x - y * y));
|
|
return target;
|
|
}
|
|
add(sh) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].add(sh.coefficients[i]);
|
|
}
|
|
return this;
|
|
}
|
|
addScaledSH(sh, s) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].addScaledVector(sh.coefficients[i], s);
|
|
}
|
|
return this;
|
|
}
|
|
scale(s) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].multiplyScalar(s);
|
|
}
|
|
return this;
|
|
}
|
|
lerp(sh, alpha) {
|
|
for (let i = 0; i < 9; i++) {
|
|
this.coefficients[i].lerp(sh.coefficients[i], alpha);
|
|
}
|
|
return this;
|
|
}
|
|
equals(sh) {
|
|
for (let i = 0; i < 9; i++) {
|
|
if (!this.coefficients[i].equals(sh.coefficients[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
copy(sh) {
|
|
return this.set(sh.coefficients);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
fromArray(array, offset = 0) {
|
|
const coefficients = this.coefficients;
|
|
for (let i = 0; i < 9; i++) {
|
|
coefficients[i].fromArray(array, offset + i * 3);
|
|
}
|
|
return this;
|
|
}
|
|
toArray(array = [], offset = 0) {
|
|
const coefficients = this.coefficients;
|
|
for (let i = 0; i < 9; i++) {
|
|
coefficients[i].toArray(array, offset + i * 3);
|
|
}
|
|
return array;
|
|
}
|
|
static getBasisAt(normal, shBasis) {
|
|
const x = normal.x, y = normal.y, z = normal.z;
|
|
shBasis[0] = 0.282095;
|
|
shBasis[1] = 0.488603 * y;
|
|
shBasis[2] = 0.488603 * z;
|
|
shBasis[3] = 0.488603 * x;
|
|
shBasis[4] = 1.092548 * x * y;
|
|
shBasis[5] = 1.092548 * y * z;
|
|
shBasis[6] = 0.315392 * (3 * z * z - 1);
|
|
shBasis[7] = 1.092548 * x * z;
|
|
shBasis[8] = 0.546274 * (x * x - y * y);
|
|
}
|
|
};
|
|
SphericalHarmonics3.prototype.isSphericalHarmonics3 = true;
|
|
var LightProbe = class extends Light {
|
|
constructor(sh = new SphericalHarmonics3(), intensity = 1) {
|
|
super(void 0, intensity);
|
|
this.sh = sh;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.sh.copy(source.sh);
|
|
return this;
|
|
}
|
|
fromJSON(json) {
|
|
this.intensity = json.intensity;
|
|
this.sh.fromArray(json.sh);
|
|
return this;
|
|
}
|
|
toJSON(meta) {
|
|
const data = super.toJSON(meta);
|
|
data.object.sh = this.sh.toArray();
|
|
return data;
|
|
}
|
|
};
|
|
LightProbe.prototype.isLightProbe = true;
|
|
var LoaderUtils = class {
|
|
static decodeText(array) {
|
|
if (typeof TextDecoder !== "undefined") {
|
|
return new TextDecoder().decode(array);
|
|
}
|
|
let s = "";
|
|
for (let i = 0, il = array.length; i < il; i++) {
|
|
s += String.fromCharCode(array[i]);
|
|
}
|
|
try {
|
|
return decodeURIComponent(escape(s));
|
|
} catch (e) {
|
|
return s;
|
|
}
|
|
}
|
|
static extractUrlBase(url) {
|
|
const index = url.lastIndexOf("/");
|
|
if (index === -1)
|
|
return "./";
|
|
return url.substr(0, index + 1);
|
|
}
|
|
};
|
|
var InstancedBufferGeometry = class extends BufferGeometry {
|
|
constructor() {
|
|
super();
|
|
this.type = "InstancedBufferGeometry";
|
|
this.instanceCount = Infinity;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.instanceCount = source.instanceCount;
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
toJSON() {
|
|
const data = super.toJSON(this);
|
|
data.instanceCount = this.instanceCount;
|
|
data.isInstancedBufferGeometry = true;
|
|
return data;
|
|
}
|
|
};
|
|
InstancedBufferGeometry.prototype.isInstancedBufferGeometry = true;
|
|
var ImageBitmapLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
if (typeof createImageBitmap === "undefined") {
|
|
console.warn("THREE.ImageBitmapLoader: createImageBitmap() not supported.");
|
|
}
|
|
if (typeof fetch === "undefined") {
|
|
console.warn("THREE.ImageBitmapLoader: fetch() not supported.");
|
|
}
|
|
this.options = { premultiplyAlpha: "none" };
|
|
}
|
|
setOptions(options) {
|
|
this.options = options;
|
|
return this;
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
if (url === void 0)
|
|
url = "";
|
|
if (this.path !== void 0)
|
|
url = this.path + url;
|
|
url = this.manager.resolveURL(url);
|
|
const scope = this;
|
|
const cached = Cache.get(url);
|
|
if (cached !== void 0) {
|
|
scope.manager.itemStart(url);
|
|
setTimeout(function() {
|
|
if (onLoad)
|
|
onLoad(cached);
|
|
scope.manager.itemEnd(url);
|
|
}, 0);
|
|
return cached;
|
|
}
|
|
const fetchOptions = {};
|
|
fetchOptions.credentials = this.crossOrigin === "anonymous" ? "same-origin" : "include";
|
|
fetchOptions.headers = this.requestHeader;
|
|
fetch(url, fetchOptions).then(function(res) {
|
|
return res.blob();
|
|
}).then(function(blob) {
|
|
return createImageBitmap(blob, Object.assign(scope.options, { colorSpaceConversion: "none" }));
|
|
}).then(function(imageBitmap) {
|
|
Cache.add(url, imageBitmap);
|
|
if (onLoad)
|
|
onLoad(imageBitmap);
|
|
scope.manager.itemEnd(url);
|
|
}).catch(function(e) {
|
|
if (onError)
|
|
onError(e);
|
|
scope.manager.itemError(url);
|
|
scope.manager.itemEnd(url);
|
|
});
|
|
scope.manager.itemStart(url);
|
|
}
|
|
};
|
|
ImageBitmapLoader.prototype.isImageBitmapLoader = true;
|
|
var ShapePath = class {
|
|
constructor() {
|
|
this.type = "ShapePath";
|
|
this.color = new Color();
|
|
this.subPaths = [];
|
|
this.currentPath = null;
|
|
}
|
|
moveTo(x, y) {
|
|
this.currentPath = new Path();
|
|
this.subPaths.push(this.currentPath);
|
|
this.currentPath.moveTo(x, y);
|
|
return this;
|
|
}
|
|
lineTo(x, y) {
|
|
this.currentPath.lineTo(x, y);
|
|
return this;
|
|
}
|
|
quadraticCurveTo(aCPx, aCPy, aX, aY) {
|
|
this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY);
|
|
return this;
|
|
}
|
|
bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
|
|
this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY);
|
|
return this;
|
|
}
|
|
splineThru(pts) {
|
|
this.currentPath.splineThru(pts);
|
|
return this;
|
|
}
|
|
toShapes(isCCW, noHoles) {
|
|
function toShapesNoHoles(inSubpaths) {
|
|
const shapes2 = [];
|
|
for (let i = 0, l = inSubpaths.length; i < l; i++) {
|
|
const tmpPath2 = inSubpaths[i];
|
|
const tmpShape2 = new Shape();
|
|
tmpShape2.curves = tmpPath2.curves;
|
|
shapes2.push(tmpShape2);
|
|
}
|
|
return shapes2;
|
|
}
|
|
function isPointInsidePolygon(inPt, inPolygon) {
|
|
const polyLen = inPolygon.length;
|
|
let inside = false;
|
|
for (let p2 = polyLen - 1, q = 0; q < polyLen; p2 = q++) {
|
|
let edgeLowPt = inPolygon[p2];
|
|
let edgeHighPt = inPolygon[q];
|
|
let edgeDx = edgeHighPt.x - edgeLowPt.x;
|
|
let edgeDy = edgeHighPt.y - edgeLowPt.y;
|
|
if (Math.abs(edgeDy) > Number.EPSILON) {
|
|
if (edgeDy < 0) {
|
|
edgeLowPt = inPolygon[q];
|
|
edgeDx = -edgeDx;
|
|
edgeHighPt = inPolygon[p2];
|
|
edgeDy = -edgeDy;
|
|
}
|
|
if (inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y)
|
|
continue;
|
|
if (inPt.y === edgeLowPt.y) {
|
|
if (inPt.x === edgeLowPt.x)
|
|
return true;
|
|
} else {
|
|
const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
|
|
if (perpEdge === 0)
|
|
return true;
|
|
if (perpEdge < 0)
|
|
continue;
|
|
inside = !inside;
|
|
}
|
|
} else {
|
|
if (inPt.y !== edgeLowPt.y)
|
|
continue;
|
|
if (edgeHighPt.x <= inPt.x && inPt.x <= edgeLowPt.x || edgeLowPt.x <= inPt.x && inPt.x <= edgeHighPt.x)
|
|
return true;
|
|
}
|
|
}
|
|
return inside;
|
|
}
|
|
const isClockWise = ShapeUtils.isClockWise;
|
|
const subPaths = this.subPaths;
|
|
if (subPaths.length === 0)
|
|
return [];
|
|
if (noHoles === true)
|
|
return toShapesNoHoles(subPaths);
|
|
let solid, tmpPath, tmpShape;
|
|
const shapes = [];
|
|
if (subPaths.length === 1) {
|
|
tmpPath = subPaths[0];
|
|
tmpShape = new Shape();
|
|
tmpShape.curves = tmpPath.curves;
|
|
shapes.push(tmpShape);
|
|
return shapes;
|
|
}
|
|
let holesFirst = !isClockWise(subPaths[0].getPoints());
|
|
holesFirst = isCCW ? !holesFirst : holesFirst;
|
|
const betterShapeHoles = [];
|
|
const newShapes = [];
|
|
let newShapeHoles = [];
|
|
let mainIdx = 0;
|
|
let tmpPoints;
|
|
newShapes[mainIdx] = void 0;
|
|
newShapeHoles[mainIdx] = [];
|
|
for (let i = 0, l = subPaths.length; i < l; i++) {
|
|
tmpPath = subPaths[i];
|
|
tmpPoints = tmpPath.getPoints();
|
|
solid = isClockWise(tmpPoints);
|
|
solid = isCCW ? !solid : solid;
|
|
if (solid) {
|
|
if (!holesFirst && newShapes[mainIdx])
|
|
mainIdx++;
|
|
newShapes[mainIdx] = { s: new Shape(), p: tmpPoints };
|
|
newShapes[mainIdx].s.curves = tmpPath.curves;
|
|
if (holesFirst)
|
|
mainIdx++;
|
|
newShapeHoles[mainIdx] = [];
|
|
} else {
|
|
newShapeHoles[mainIdx].push({ h: tmpPath, p: tmpPoints[0] });
|
|
}
|
|
}
|
|
if (!newShapes[0])
|
|
return toShapesNoHoles(subPaths);
|
|
if (newShapes.length > 1) {
|
|
let ambiguous = false;
|
|
const toChange = [];
|
|
for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
betterShapeHoles[sIdx] = [];
|
|
}
|
|
for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
const sho = newShapeHoles[sIdx];
|
|
for (let hIdx = 0; hIdx < sho.length; hIdx++) {
|
|
const ho = sho[hIdx];
|
|
let hole_unassigned = true;
|
|
for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
|
|
if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
|
|
if (sIdx !== s2Idx)
|
|
toChange.push({ froms: sIdx, tos: s2Idx, hole: hIdx });
|
|
if (hole_unassigned) {
|
|
hole_unassigned = false;
|
|
betterShapeHoles[s2Idx].push(ho);
|
|
} else {
|
|
ambiguous = true;
|
|
}
|
|
}
|
|
}
|
|
if (hole_unassigned) {
|
|
betterShapeHoles[sIdx].push(ho);
|
|
}
|
|
}
|
|
}
|
|
if (toChange.length > 0) {
|
|
if (!ambiguous)
|
|
newShapeHoles = betterShapeHoles;
|
|
}
|
|
}
|
|
let tmpHoles;
|
|
for (let i = 0, il = newShapes.length; i < il; i++) {
|
|
tmpShape = newShapes[i].s;
|
|
shapes.push(tmpShape);
|
|
tmpHoles = newShapeHoles[i];
|
|
for (let j = 0, jl = tmpHoles.length; j < jl; j++) {
|
|
tmpShape.holes.push(tmpHoles[j].h);
|
|
}
|
|
}
|
|
return shapes;
|
|
}
|
|
};
|
|
var Font = class {
|
|
constructor(data) {
|
|
this.type = "Font";
|
|
this.data = data;
|
|
}
|
|
generateShapes(text, size = 100) {
|
|
const shapes = [];
|
|
const paths = createPaths(text, size, this.data);
|
|
for (let p2 = 0, pl = paths.length; p2 < pl; p2++) {
|
|
Array.prototype.push.apply(shapes, paths[p2].toShapes());
|
|
}
|
|
return shapes;
|
|
}
|
|
};
|
|
function createPaths(text, size, data) {
|
|
const chars = Array.from(text);
|
|
const scale = size / data.resolution;
|
|
const line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
|
|
const paths = [];
|
|
let offsetX = 0, offsetY = 0;
|
|
for (let i = 0; i < chars.length; i++) {
|
|
const char = chars[i];
|
|
if (char === "\n") {
|
|
offsetX = 0;
|
|
offsetY -= line_height;
|
|
} else {
|
|
const ret = createPath(char, scale, offsetX, offsetY, data);
|
|
offsetX += ret.offsetX;
|
|
paths.push(ret.path);
|
|
}
|
|
}
|
|
return paths;
|
|
}
|
|
function createPath(char, scale, offsetX, offsetY, data) {
|
|
const glyph = data.glyphs[char] || data.glyphs["?"];
|
|
if (!glyph) {
|
|
console.error('THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + ".");
|
|
return;
|
|
}
|
|
const path = new ShapePath();
|
|
let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
|
|
if (glyph.o) {
|
|
const outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(" "));
|
|
for (let i = 0, l = outline.length; i < l; ) {
|
|
const action = outline[i++];
|
|
switch (action) {
|
|
case "m":
|
|
x = outline[i++] * scale + offsetX;
|
|
y = outline[i++] * scale + offsetY;
|
|
path.moveTo(x, y);
|
|
break;
|
|
case "l":
|
|
x = outline[i++] * scale + offsetX;
|
|
y = outline[i++] * scale + offsetY;
|
|
path.lineTo(x, y);
|
|
break;
|
|
case "q":
|
|
cpx = outline[i++] * scale + offsetX;
|
|
cpy = outline[i++] * scale + offsetY;
|
|
cpx1 = outline[i++] * scale + offsetX;
|
|
cpy1 = outline[i++] * scale + offsetY;
|
|
path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
|
|
break;
|
|
case "b":
|
|
cpx = outline[i++] * scale + offsetX;
|
|
cpy = outline[i++] * scale + offsetY;
|
|
cpx1 = outline[i++] * scale + offsetX;
|
|
cpy1 = outline[i++] * scale + offsetY;
|
|
cpx2 = outline[i++] * scale + offsetX;
|
|
cpy2 = outline[i++] * scale + offsetY;
|
|
path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return { offsetX: glyph.ha * scale, path };
|
|
}
|
|
Font.prototype.isFont = true;
|
|
var _context;
|
|
var AudioContext = {
|
|
getContext: function() {
|
|
if (_context === void 0) {
|
|
_context = new (window.AudioContext || window.webkitAudioContext)();
|
|
}
|
|
return _context;
|
|
},
|
|
setContext: function(value) {
|
|
_context = value;
|
|
}
|
|
};
|
|
var AudioLoader = class extends Loader {
|
|
constructor(manager) {
|
|
super(manager);
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
const scope = this;
|
|
const loader = new FileLoader(this.manager);
|
|
loader.setResponseType("arraybuffer");
|
|
loader.setPath(this.path);
|
|
loader.setRequestHeader(this.requestHeader);
|
|
loader.setWithCredentials(this.withCredentials);
|
|
loader.load(url, function(buffer) {
|
|
try {
|
|
const bufferCopy = buffer.slice(0);
|
|
const context = AudioContext.getContext();
|
|
context.decodeAudioData(bufferCopy, function(audioBuffer) {
|
|
onLoad(audioBuffer);
|
|
});
|
|
} catch (e) {
|
|
if (onError) {
|
|
onError(e);
|
|
} else {
|
|
console.error(e);
|
|
}
|
|
scope.manager.itemError(url);
|
|
}
|
|
}, onProgress, onError);
|
|
}
|
|
};
|
|
var HemisphereLightProbe = class extends LightProbe {
|
|
constructor(skyColor, groundColor, intensity = 1) {
|
|
super(void 0, intensity);
|
|
const color1 = new Color().set(skyColor);
|
|
const color2 = new Color().set(groundColor);
|
|
const sky = new Vector3(color1.r, color1.g, color1.b);
|
|
const ground = new Vector3(color2.r, color2.g, color2.b);
|
|
const c0 = Math.sqrt(Math.PI);
|
|
const c1 = c0 * Math.sqrt(0.75);
|
|
this.sh.coefficients[0].copy(sky).add(ground).multiplyScalar(c0);
|
|
this.sh.coefficients[1].copy(sky).sub(ground).multiplyScalar(c1);
|
|
}
|
|
};
|
|
HemisphereLightProbe.prototype.isHemisphereLightProbe = true;
|
|
var AmbientLightProbe = class extends LightProbe {
|
|
constructor(color, intensity = 1) {
|
|
super(void 0, intensity);
|
|
const color1 = new Color().set(color);
|
|
this.sh.coefficients[0].set(color1.r, color1.g, color1.b).multiplyScalar(2 * Math.sqrt(Math.PI));
|
|
}
|
|
};
|
|
AmbientLightProbe.prototype.isAmbientLightProbe = true;
|
|
var Audio = class extends Object3D {
|
|
constructor(listener3) {
|
|
super();
|
|
this.type = "Audio";
|
|
this.listener = listener3;
|
|
this.context = listener3.context;
|
|
this.gain = this.context.createGain();
|
|
this.gain.connect(listener3.getInput());
|
|
this.autoplay = false;
|
|
this.buffer = null;
|
|
this.detune = 0;
|
|
this.loop = false;
|
|
this.loopStart = 0;
|
|
this.loopEnd = 0;
|
|
this.offset = 0;
|
|
this.duration = void 0;
|
|
this.playbackRate = 1;
|
|
this.isPlaying = false;
|
|
this.hasPlaybackControl = true;
|
|
this.source = null;
|
|
this.sourceType = "empty";
|
|
this._startedAt = 0;
|
|
this._progress = 0;
|
|
this._connected = false;
|
|
this.filters = [];
|
|
}
|
|
getOutput() {
|
|
return this.gain;
|
|
}
|
|
setNodeSource(audioNode) {
|
|
this.hasPlaybackControl = false;
|
|
this.sourceType = "audioNode";
|
|
this.source = audioNode;
|
|
this.connect();
|
|
return this;
|
|
}
|
|
setMediaElementSource(mediaElement) {
|
|
this.hasPlaybackControl = false;
|
|
this.sourceType = "mediaNode";
|
|
this.source = this.context.createMediaElementSource(mediaElement);
|
|
this.connect();
|
|
return this;
|
|
}
|
|
setMediaStreamSource(mediaStream) {
|
|
this.hasPlaybackControl = false;
|
|
this.sourceType = "mediaStreamNode";
|
|
this.source = this.context.createMediaStreamSource(mediaStream);
|
|
this.connect();
|
|
return this;
|
|
}
|
|
setBuffer(audioBuffer) {
|
|
this.buffer = audioBuffer;
|
|
this.sourceType = "buffer";
|
|
if (this.autoplay)
|
|
this.play();
|
|
return this;
|
|
}
|
|
play(delay = 0) {
|
|
if (this.isPlaying === true) {
|
|
console.warn("THREE.Audio: Audio is already playing.");
|
|
return;
|
|
}
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return;
|
|
}
|
|
this._startedAt = this.context.currentTime + delay;
|
|
const source = this.context.createBufferSource();
|
|
source.buffer = this.buffer;
|
|
source.loop = this.loop;
|
|
source.loopStart = this.loopStart;
|
|
source.loopEnd = this.loopEnd;
|
|
source.onended = this.onEnded.bind(this);
|
|
source.start(this._startedAt, this._progress + this.offset, this.duration);
|
|
this.isPlaying = true;
|
|
this.source = source;
|
|
this.setDetune(this.detune);
|
|
this.setPlaybackRate(this.playbackRate);
|
|
return this.connect();
|
|
}
|
|
pause() {
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return;
|
|
}
|
|
if (this.isPlaying === true) {
|
|
this._progress += Math.max(this.context.currentTime - this._startedAt, 0) * this.playbackRate;
|
|
if (this.loop === true) {
|
|
this._progress = this._progress % (this.duration || this.buffer.duration);
|
|
}
|
|
this.source.stop();
|
|
this.source.onended = null;
|
|
this.isPlaying = false;
|
|
}
|
|
return this;
|
|
}
|
|
stop() {
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return;
|
|
}
|
|
this._progress = 0;
|
|
this.source.stop();
|
|
this.source.onended = null;
|
|
this.isPlaying = false;
|
|
return this;
|
|
}
|
|
connect() {
|
|
if (this.filters.length > 0) {
|
|
this.source.connect(this.filters[0]);
|
|
for (let i = 1, l = this.filters.length; i < l; i++) {
|
|
this.filters[i - 1].connect(this.filters[i]);
|
|
}
|
|
this.filters[this.filters.length - 1].connect(this.getOutput());
|
|
} else {
|
|
this.source.connect(this.getOutput());
|
|
}
|
|
this._connected = true;
|
|
return this;
|
|
}
|
|
disconnect() {
|
|
if (this.filters.length > 0) {
|
|
this.source.disconnect(this.filters[0]);
|
|
for (let i = 1, l = this.filters.length; i < l; i++) {
|
|
this.filters[i - 1].disconnect(this.filters[i]);
|
|
}
|
|
this.filters[this.filters.length - 1].disconnect(this.getOutput());
|
|
} else {
|
|
this.source.disconnect(this.getOutput());
|
|
}
|
|
this._connected = false;
|
|
return this;
|
|
}
|
|
getFilters() {
|
|
return this.filters;
|
|
}
|
|
setFilters(value) {
|
|
if (!value)
|
|
value = [];
|
|
if (this._connected === true) {
|
|
this.disconnect();
|
|
this.filters = value.slice();
|
|
this.connect();
|
|
} else {
|
|
this.filters = value.slice();
|
|
}
|
|
return this;
|
|
}
|
|
setDetune(value) {
|
|
this.detune = value;
|
|
if (this.source.detune === void 0)
|
|
return;
|
|
if (this.isPlaying === true) {
|
|
this.source.detune.setTargetAtTime(this.detune, this.context.currentTime, 0.01);
|
|
}
|
|
return this;
|
|
}
|
|
getDetune() {
|
|
return this.detune;
|
|
}
|
|
getFilter() {
|
|
return this.getFilters()[0];
|
|
}
|
|
setFilter(filter) {
|
|
return this.setFilters(filter ? [filter] : []);
|
|
}
|
|
setPlaybackRate(value) {
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return;
|
|
}
|
|
this.playbackRate = value;
|
|
if (this.isPlaying === true) {
|
|
this.source.playbackRate.setTargetAtTime(this.playbackRate, this.context.currentTime, 0.01);
|
|
}
|
|
return this;
|
|
}
|
|
getPlaybackRate() {
|
|
return this.playbackRate;
|
|
}
|
|
onEnded() {
|
|
this.isPlaying = false;
|
|
}
|
|
getLoop() {
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return false;
|
|
}
|
|
return this.loop;
|
|
}
|
|
setLoop(value) {
|
|
if (this.hasPlaybackControl === false) {
|
|
console.warn("THREE.Audio: this Audio has no playback control.");
|
|
return;
|
|
}
|
|
this.loop = value;
|
|
if (this.isPlaying === true) {
|
|
this.source.loop = this.loop;
|
|
}
|
|
return this;
|
|
}
|
|
setLoopStart(value) {
|
|
this.loopStart = value;
|
|
return this;
|
|
}
|
|
setLoopEnd(value) {
|
|
this.loopEnd = value;
|
|
return this;
|
|
}
|
|
getVolume() {
|
|
return this.gain.gain.value;
|
|
}
|
|
setVolume(value) {
|
|
this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01);
|
|
return this;
|
|
}
|
|
};
|
|
var AudioAnalyser = class {
|
|
constructor(audio, fftSize = 2048) {
|
|
this.analyser = audio.context.createAnalyser();
|
|
this.analyser.fftSize = fftSize;
|
|
this.data = new Uint8Array(this.analyser.frequencyBinCount);
|
|
audio.getOutput().connect(this.analyser);
|
|
}
|
|
getFrequencyData() {
|
|
this.analyser.getByteFrequencyData(this.data);
|
|
return this.data;
|
|
}
|
|
getAverageFrequency() {
|
|
let value = 0;
|
|
const data = this.getFrequencyData();
|
|
for (let i = 0; i < data.length; i++) {
|
|
value += data[i];
|
|
}
|
|
return value / data.length;
|
|
}
|
|
};
|
|
var PropertyMixer = class {
|
|
constructor(binding, typeName, valueSize) {
|
|
this.binding = binding;
|
|
this.valueSize = valueSize;
|
|
let mixFunction, mixFunctionAdditive, setIdentity;
|
|
switch (typeName) {
|
|
case "quaternion":
|
|
mixFunction = this._slerp;
|
|
mixFunctionAdditive = this._slerpAdditive;
|
|
setIdentity = this._setAdditiveIdentityQuaternion;
|
|
this.buffer = new Float64Array(valueSize * 6);
|
|
this._workIndex = 5;
|
|
break;
|
|
case "string":
|
|
case "bool":
|
|
mixFunction = this._select;
|
|
mixFunctionAdditive = this._select;
|
|
setIdentity = this._setAdditiveIdentityOther;
|
|
this.buffer = new Array(valueSize * 5);
|
|
break;
|
|
default:
|
|
mixFunction = this._lerp;
|
|
mixFunctionAdditive = this._lerpAdditive;
|
|
setIdentity = this._setAdditiveIdentityNumeric;
|
|
this.buffer = new Float64Array(valueSize * 5);
|
|
}
|
|
this._mixBufferRegion = mixFunction;
|
|
this._mixBufferRegionAdditive = mixFunctionAdditive;
|
|
this._setIdentity = setIdentity;
|
|
this._origIndex = 3;
|
|
this._addIndex = 4;
|
|
this.cumulativeWeight = 0;
|
|
this.cumulativeWeightAdditive = 0;
|
|
this.useCount = 0;
|
|
this.referenceCount = 0;
|
|
}
|
|
accumulate(accuIndex, weight) {
|
|
const buffer = this.buffer, stride = this.valueSize, offset = accuIndex * stride + stride;
|
|
let currentWeight = this.cumulativeWeight;
|
|
if (currentWeight === 0) {
|
|
for (let i = 0; i !== stride; ++i) {
|
|
buffer[offset + i] = buffer[i];
|
|
}
|
|
currentWeight = weight;
|
|
} else {
|
|
currentWeight += weight;
|
|
const mix = weight / currentWeight;
|
|
this._mixBufferRegion(buffer, offset, 0, mix, stride);
|
|
}
|
|
this.cumulativeWeight = currentWeight;
|
|
}
|
|
accumulateAdditive(weight) {
|
|
const buffer = this.buffer, stride = this.valueSize, offset = stride * this._addIndex;
|
|
if (this.cumulativeWeightAdditive === 0) {
|
|
this._setIdentity();
|
|
}
|
|
this._mixBufferRegionAdditive(buffer, offset, 0, weight, stride);
|
|
this.cumulativeWeightAdditive += weight;
|
|
}
|
|
apply(accuIndex) {
|
|
const stride = this.valueSize, buffer = this.buffer, offset = accuIndex * stride + stride, weight = this.cumulativeWeight, weightAdditive = this.cumulativeWeightAdditive, binding = this.binding;
|
|
this.cumulativeWeight = 0;
|
|
this.cumulativeWeightAdditive = 0;
|
|
if (weight < 1) {
|
|
const originalValueOffset = stride * this._origIndex;
|
|
this._mixBufferRegion(buffer, offset, originalValueOffset, 1 - weight, stride);
|
|
}
|
|
if (weightAdditive > 0) {
|
|
this._mixBufferRegionAdditive(buffer, offset, this._addIndex * stride, 1, stride);
|
|
}
|
|
for (let i = stride, e = stride + stride; i !== e; ++i) {
|
|
if (buffer[i] !== buffer[i + stride]) {
|
|
binding.setValue(buffer, offset);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
saveOriginalState() {
|
|
const binding = this.binding;
|
|
const buffer = this.buffer, stride = this.valueSize, originalValueOffset = stride * this._origIndex;
|
|
binding.getValue(buffer, originalValueOffset);
|
|
for (let i = stride, e = originalValueOffset; i !== e; ++i) {
|
|
buffer[i] = buffer[originalValueOffset + i % stride];
|
|
}
|
|
this._setIdentity();
|
|
this.cumulativeWeight = 0;
|
|
this.cumulativeWeightAdditive = 0;
|
|
}
|
|
restoreOriginalState() {
|
|
const originalValueOffset = this.valueSize * 3;
|
|
this.binding.setValue(this.buffer, originalValueOffset);
|
|
}
|
|
_setAdditiveIdentityNumeric() {
|
|
const startIndex = this._addIndex * this.valueSize;
|
|
const endIndex = startIndex + this.valueSize;
|
|
for (let i = startIndex; i < endIndex; i++) {
|
|
this.buffer[i] = 0;
|
|
}
|
|
}
|
|
_setAdditiveIdentityQuaternion() {
|
|
this._setAdditiveIdentityNumeric();
|
|
this.buffer[this._addIndex * this.valueSize + 3] = 1;
|
|
}
|
|
_setAdditiveIdentityOther() {
|
|
const startIndex = this._origIndex * this.valueSize;
|
|
const targetIndex = this._addIndex * this.valueSize;
|
|
for (let i = 0; i < this.valueSize; i++) {
|
|
this.buffer[targetIndex + i] = this.buffer[startIndex + i];
|
|
}
|
|
}
|
|
_select(buffer, dstOffset, srcOffset, t, stride) {
|
|
if (t >= 0.5) {
|
|
for (let i = 0; i !== stride; ++i) {
|
|
buffer[dstOffset + i] = buffer[srcOffset + i];
|
|
}
|
|
}
|
|
}
|
|
_slerp(buffer, dstOffset, srcOffset, t) {
|
|
Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t);
|
|
}
|
|
_slerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
|
|
const workOffset = this._workIndex * stride;
|
|
Quaternion.multiplyQuaternionsFlat(buffer, workOffset, buffer, dstOffset, buffer, srcOffset);
|
|
Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t);
|
|
}
|
|
_lerp(buffer, dstOffset, srcOffset, t, stride) {
|
|
const s = 1 - t;
|
|
for (let i = 0; i !== stride; ++i) {
|
|
const j = dstOffset + i;
|
|
buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t;
|
|
}
|
|
}
|
|
_lerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
|
|
for (let i = 0; i !== stride; ++i) {
|
|
const j = dstOffset + i;
|
|
buffer[j] = buffer[j] + buffer[srcOffset + i] * t;
|
|
}
|
|
}
|
|
};
|
|
var _RESERVED_CHARS_RE = "\\[\\]\\.:\\/";
|
|
var _reservedRe = new RegExp("[" + _RESERVED_CHARS_RE + "]", "g");
|
|
var _wordChar = "[^" + _RESERVED_CHARS_RE + "]";
|
|
var _wordCharOrDot = "[^" + _RESERVED_CHARS_RE.replace("\\.", "") + "]";
|
|
var _directoryRe = /((?:WC+[\/:])*)/.source.replace("WC", _wordChar);
|
|
var _nodeRe = /(WCOD+)?/.source.replace("WCOD", _wordCharOrDot);
|
|
var _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC", _wordChar);
|
|
var _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace("WC", _wordChar);
|
|
var _trackRe = new RegExp("^" + _directoryRe + _nodeRe + _objectRe + _propertyRe + "$");
|
|
var _supportedObjectNames = ["material", "materials", "bones"];
|
|
var Composite = class {
|
|
constructor(targetGroup, path, optionalParsedPath) {
|
|
const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path);
|
|
this._targetGroup = targetGroup;
|
|
this._bindings = targetGroup.subscribe_(path, parsedPath);
|
|
}
|
|
getValue(array, offset) {
|
|
this.bind();
|
|
const firstValidIndex = this._targetGroup.nCachedObjects_, binding = this._bindings[firstValidIndex];
|
|
if (binding !== void 0)
|
|
binding.getValue(array, offset);
|
|
}
|
|
setValue(array, offset) {
|
|
const bindings = this._bindings;
|
|
for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
|
|
bindings[i].setValue(array, offset);
|
|
}
|
|
}
|
|
bind() {
|
|
const bindings = this._bindings;
|
|
for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
|
|
bindings[i].bind();
|
|
}
|
|
}
|
|
unbind() {
|
|
const bindings = this._bindings;
|
|
for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
|
|
bindings[i].unbind();
|
|
}
|
|
}
|
|
};
|
|
var PropertyBinding = class {
|
|
constructor(rootNode, path, parsedPath) {
|
|
this.path = path;
|
|
this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path);
|
|
this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode;
|
|
this.rootNode = rootNode;
|
|
this.getValue = this._getValue_unbound;
|
|
this.setValue = this._setValue_unbound;
|
|
}
|
|
static create(root, path, parsedPath) {
|
|
if (!(root && root.isAnimationObjectGroup)) {
|
|
return new PropertyBinding(root, path, parsedPath);
|
|
} else {
|
|
return new PropertyBinding.Composite(root, path, parsedPath);
|
|
}
|
|
}
|
|
static sanitizeNodeName(name) {
|
|
return name.replace(/\s/g, "_").replace(_reservedRe, "");
|
|
}
|
|
static parseTrackName(trackName) {
|
|
const matches = _trackRe.exec(trackName);
|
|
if (!matches) {
|
|
throw new Error("PropertyBinding: Cannot parse trackName: " + trackName);
|
|
}
|
|
const results = {
|
|
nodeName: matches[2],
|
|
objectName: matches[3],
|
|
objectIndex: matches[4],
|
|
propertyName: matches[5],
|
|
propertyIndex: matches[6]
|
|
};
|
|
const lastDot = results.nodeName && results.nodeName.lastIndexOf(".");
|
|
if (lastDot !== void 0 && lastDot !== -1) {
|
|
const objectName = results.nodeName.substring(lastDot + 1);
|
|
if (_supportedObjectNames.indexOf(objectName) !== -1) {
|
|
results.nodeName = results.nodeName.substring(0, lastDot);
|
|
results.objectName = objectName;
|
|
}
|
|
}
|
|
if (results.propertyName === null || results.propertyName.length === 0) {
|
|
throw new Error("PropertyBinding: can not parse propertyName from trackName: " + trackName);
|
|
}
|
|
return results;
|
|
}
|
|
static findNode(root, nodeName) {
|
|
if (!nodeName || nodeName === "" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
|
|
return root;
|
|
}
|
|
if (root.skeleton) {
|
|
const bone = root.skeleton.getBoneByName(nodeName);
|
|
if (bone !== void 0) {
|
|
return bone;
|
|
}
|
|
}
|
|
if (root.children) {
|
|
const searchNodeSubtree = function(children) {
|
|
for (let i = 0; i < children.length; i++) {
|
|
const childNode = children[i];
|
|
if (childNode.name === nodeName || childNode.uuid === nodeName) {
|
|
return childNode;
|
|
}
|
|
const result = searchNodeSubtree(childNode.children);
|
|
if (result)
|
|
return result;
|
|
}
|
|
return null;
|
|
};
|
|
const subTreeNode = searchNodeSubtree(root.children);
|
|
if (subTreeNode) {
|
|
return subTreeNode;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
_getValue_unavailable() {
|
|
}
|
|
_setValue_unavailable() {
|
|
}
|
|
_getValue_direct(buffer, offset) {
|
|
buffer[offset] = this.targetObject[this.propertyName];
|
|
}
|
|
_getValue_array(buffer, offset) {
|
|
const source = this.resolvedProperty;
|
|
for (let i = 0, n = source.length; i !== n; ++i) {
|
|
buffer[offset++] = source[i];
|
|
}
|
|
}
|
|
_getValue_arrayElement(buffer, offset) {
|
|
buffer[offset] = this.resolvedProperty[this.propertyIndex];
|
|
}
|
|
_getValue_toArray(buffer, offset) {
|
|
this.resolvedProperty.toArray(buffer, offset);
|
|
}
|
|
_setValue_direct(buffer, offset) {
|
|
this.targetObject[this.propertyName] = buffer[offset];
|
|
}
|
|
_setValue_direct_setNeedsUpdate(buffer, offset) {
|
|
this.targetObject[this.propertyName] = buffer[offset];
|
|
this.targetObject.needsUpdate = true;
|
|
}
|
|
_setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) {
|
|
this.targetObject[this.propertyName] = buffer[offset];
|
|
this.targetObject.matrixWorldNeedsUpdate = true;
|
|
}
|
|
_setValue_array(buffer, offset) {
|
|
const dest = this.resolvedProperty;
|
|
for (let i = 0, n = dest.length; i !== n; ++i) {
|
|
dest[i] = buffer[offset++];
|
|
}
|
|
}
|
|
_setValue_array_setNeedsUpdate(buffer, offset) {
|
|
const dest = this.resolvedProperty;
|
|
for (let i = 0, n = dest.length; i !== n; ++i) {
|
|
dest[i] = buffer[offset++];
|
|
}
|
|
this.targetObject.needsUpdate = true;
|
|
}
|
|
_setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) {
|
|
const dest = this.resolvedProperty;
|
|
for (let i = 0, n = dest.length; i !== n; ++i) {
|
|
dest[i] = buffer[offset++];
|
|
}
|
|
this.targetObject.matrixWorldNeedsUpdate = true;
|
|
}
|
|
_setValue_arrayElement(buffer, offset) {
|
|
this.resolvedProperty[this.propertyIndex] = buffer[offset];
|
|
}
|
|
_setValue_arrayElement_setNeedsUpdate(buffer, offset) {
|
|
this.resolvedProperty[this.propertyIndex] = buffer[offset];
|
|
this.targetObject.needsUpdate = true;
|
|
}
|
|
_setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) {
|
|
this.resolvedProperty[this.propertyIndex] = buffer[offset];
|
|
this.targetObject.matrixWorldNeedsUpdate = true;
|
|
}
|
|
_setValue_fromArray(buffer, offset) {
|
|
this.resolvedProperty.fromArray(buffer, offset);
|
|
}
|
|
_setValue_fromArray_setNeedsUpdate(buffer, offset) {
|
|
this.resolvedProperty.fromArray(buffer, offset);
|
|
this.targetObject.needsUpdate = true;
|
|
}
|
|
_setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) {
|
|
this.resolvedProperty.fromArray(buffer, offset);
|
|
this.targetObject.matrixWorldNeedsUpdate = true;
|
|
}
|
|
_getValue_unbound(targetArray, offset) {
|
|
this.bind();
|
|
this.getValue(targetArray, offset);
|
|
}
|
|
_setValue_unbound(sourceArray, offset) {
|
|
this.bind();
|
|
this.setValue(sourceArray, offset);
|
|
}
|
|
bind() {
|
|
let targetObject = this.node;
|
|
const parsedPath = this.parsedPath;
|
|
const objectName = parsedPath.objectName;
|
|
const propertyName = parsedPath.propertyName;
|
|
let propertyIndex = parsedPath.propertyIndex;
|
|
if (!targetObject) {
|
|
targetObject = PropertyBinding.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode;
|
|
this.node = targetObject;
|
|
}
|
|
this.getValue = this._getValue_unavailable;
|
|
this.setValue = this._setValue_unavailable;
|
|
if (!targetObject) {
|
|
console.error("THREE.PropertyBinding: Trying to update node for track: " + this.path + " but it wasn't found.");
|
|
return;
|
|
}
|
|
if (objectName) {
|
|
let objectIndex = parsedPath.objectIndex;
|
|
switch (objectName) {
|
|
case "materials":
|
|
if (!targetObject.material) {
|
|
console.error("THREE.PropertyBinding: Can not bind to material as node does not have a material.", this);
|
|
return;
|
|
}
|
|
if (!targetObject.material.materials) {
|
|
console.error("THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.", this);
|
|
return;
|
|
}
|
|
targetObject = targetObject.material.materials;
|
|
break;
|
|
case "bones":
|
|
if (!targetObject.skeleton) {
|
|
console.error("THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.", this);
|
|
return;
|
|
}
|
|
targetObject = targetObject.skeleton.bones;
|
|
for (let i = 0; i < targetObject.length; i++) {
|
|
if (targetObject[i].name === objectIndex) {
|
|
objectIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if (targetObject[objectName] === void 0) {
|
|
console.error("THREE.PropertyBinding: Can not bind to objectName of node undefined.", this);
|
|
return;
|
|
}
|
|
targetObject = targetObject[objectName];
|
|
}
|
|
if (objectIndex !== void 0) {
|
|
if (targetObject[objectIndex] === void 0) {
|
|
console.error("THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.", this, targetObject);
|
|
return;
|
|
}
|
|
targetObject = targetObject[objectIndex];
|
|
}
|
|
}
|
|
const nodeProperty = targetObject[propertyName];
|
|
if (nodeProperty === void 0) {
|
|
const nodeName = parsedPath.nodeName;
|
|
console.error("THREE.PropertyBinding: Trying to update property for track: " + nodeName + "." + propertyName + " but it wasn't found.", targetObject);
|
|
return;
|
|
}
|
|
let versioning = this.Versioning.None;
|
|
this.targetObject = targetObject;
|
|
if (targetObject.needsUpdate !== void 0) {
|
|
versioning = this.Versioning.NeedsUpdate;
|
|
} else if (targetObject.matrixWorldNeedsUpdate !== void 0) {
|
|
versioning = this.Versioning.MatrixWorldNeedsUpdate;
|
|
}
|
|
let bindingType = this.BindingType.Direct;
|
|
if (propertyIndex !== void 0) {
|
|
if (propertyName === "morphTargetInfluences") {
|
|
if (!targetObject.geometry) {
|
|
console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.", this);
|
|
return;
|
|
}
|
|
if (targetObject.geometry.isBufferGeometry) {
|
|
if (!targetObject.geometry.morphAttributes) {
|
|
console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.", this);
|
|
return;
|
|
}
|
|
if (targetObject.morphTargetDictionary[propertyIndex] !== void 0) {
|
|
propertyIndex = targetObject.morphTargetDictionary[propertyIndex];
|
|
}
|
|
} else {
|
|
console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.", this);
|
|
return;
|
|
}
|
|
}
|
|
bindingType = this.BindingType.ArrayElement;
|
|
this.resolvedProperty = nodeProperty;
|
|
this.propertyIndex = propertyIndex;
|
|
} else if (nodeProperty.fromArray !== void 0 && nodeProperty.toArray !== void 0) {
|
|
bindingType = this.BindingType.HasFromToArray;
|
|
this.resolvedProperty = nodeProperty;
|
|
} else if (Array.isArray(nodeProperty)) {
|
|
bindingType = this.BindingType.EntireArray;
|
|
this.resolvedProperty = nodeProperty;
|
|
} else {
|
|
this.propertyName = propertyName;
|
|
}
|
|
this.getValue = this.GetterByBindingType[bindingType];
|
|
this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning];
|
|
}
|
|
unbind() {
|
|
this.node = null;
|
|
this.getValue = this._getValue_unbound;
|
|
this.setValue = this._setValue_unbound;
|
|
}
|
|
};
|
|
PropertyBinding.Composite = Composite;
|
|
PropertyBinding.prototype.BindingType = {
|
|
Direct: 0,
|
|
EntireArray: 1,
|
|
ArrayElement: 2,
|
|
HasFromToArray: 3
|
|
};
|
|
PropertyBinding.prototype.Versioning = {
|
|
None: 0,
|
|
NeedsUpdate: 1,
|
|
MatrixWorldNeedsUpdate: 2
|
|
};
|
|
PropertyBinding.prototype.GetterByBindingType = [
|
|
PropertyBinding.prototype._getValue_direct,
|
|
PropertyBinding.prototype._getValue_array,
|
|
PropertyBinding.prototype._getValue_arrayElement,
|
|
PropertyBinding.prototype._getValue_toArray
|
|
];
|
|
PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
|
|
[
|
|
PropertyBinding.prototype._setValue_direct,
|
|
PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
|
|
PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate
|
|
],
|
|
[
|
|
PropertyBinding.prototype._setValue_array,
|
|
PropertyBinding.prototype._setValue_array_setNeedsUpdate,
|
|
PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate
|
|
],
|
|
[
|
|
PropertyBinding.prototype._setValue_arrayElement,
|
|
PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
|
|
PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate
|
|
],
|
|
[
|
|
PropertyBinding.prototype._setValue_fromArray,
|
|
PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
|
|
PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate
|
|
]
|
|
];
|
|
var AnimationObjectGroup = class {
|
|
constructor() {
|
|
this.uuid = generateUUID();
|
|
this._objects = Array.prototype.slice.call(arguments);
|
|
this.nCachedObjects_ = 0;
|
|
const indices = {};
|
|
this._indicesByUUID = indices;
|
|
for (let i = 0, n = arguments.length; i !== n; ++i) {
|
|
indices[arguments[i].uuid] = i;
|
|
}
|
|
this._paths = [];
|
|
this._parsedPaths = [];
|
|
this._bindings = [];
|
|
this._bindingsIndicesByPath = {};
|
|
const scope = this;
|
|
this.stats = {
|
|
objects: {
|
|
get total() {
|
|
return scope._objects.length;
|
|
},
|
|
get inUse() {
|
|
return this.total - scope.nCachedObjects_;
|
|
}
|
|
},
|
|
get bindingsPerObject() {
|
|
return scope._bindings.length;
|
|
}
|
|
};
|
|
}
|
|
add() {
|
|
const objects = this._objects, indicesByUUID = this._indicesByUUID, paths = this._paths, parsedPaths = this._parsedPaths, bindings = this._bindings, nBindings = bindings.length;
|
|
let knownObject = void 0, nObjects = objects.length, nCachedObjects = this.nCachedObjects_;
|
|
for (let i = 0, n = arguments.length; i !== n; ++i) {
|
|
const object = arguments[i], uuid = object.uuid;
|
|
let index = indicesByUUID[uuid];
|
|
if (index === void 0) {
|
|
index = nObjects++;
|
|
indicesByUUID[uuid] = index;
|
|
objects.push(object);
|
|
for (let j = 0, m = nBindings; j !== m; ++j) {
|
|
bindings[j].push(new PropertyBinding(object, paths[j], parsedPaths[j]));
|
|
}
|
|
} else if (index < nCachedObjects) {
|
|
knownObject = objects[index];
|
|
const firstActiveIndex = --nCachedObjects, lastCachedObject = objects[firstActiveIndex];
|
|
indicesByUUID[lastCachedObject.uuid] = index;
|
|
objects[index] = lastCachedObject;
|
|
indicesByUUID[uuid] = firstActiveIndex;
|
|
objects[firstActiveIndex] = object;
|
|
for (let j = 0, m = nBindings; j !== m; ++j) {
|
|
const bindingsForPath = bindings[j], lastCached = bindingsForPath[firstActiveIndex];
|
|
let binding = bindingsForPath[index];
|
|
bindingsForPath[index] = lastCached;
|
|
if (binding === void 0) {
|
|
binding = new PropertyBinding(object, paths[j], parsedPaths[j]);
|
|
}
|
|
bindingsForPath[firstActiveIndex] = binding;
|
|
}
|
|
} else if (objects[index] !== knownObject) {
|
|
console.error("THREE.AnimationObjectGroup: Different objects with the same UUID detected. Clean the caches or recreate your infrastructure when reloading scenes.");
|
|
}
|
|
}
|
|
this.nCachedObjects_ = nCachedObjects;
|
|
}
|
|
remove() {
|
|
const objects = this._objects, indicesByUUID = this._indicesByUUID, bindings = this._bindings, nBindings = bindings.length;
|
|
let nCachedObjects = this.nCachedObjects_;
|
|
for (let i = 0, n = arguments.length; i !== n; ++i) {
|
|
const object = arguments[i], uuid = object.uuid, index = indicesByUUID[uuid];
|
|
if (index !== void 0 && index >= nCachedObjects) {
|
|
const lastCachedIndex = nCachedObjects++, firstActiveObject = objects[lastCachedIndex];
|
|
indicesByUUID[firstActiveObject.uuid] = index;
|
|
objects[index] = firstActiveObject;
|
|
indicesByUUID[uuid] = lastCachedIndex;
|
|
objects[lastCachedIndex] = object;
|
|
for (let j = 0, m = nBindings; j !== m; ++j) {
|
|
const bindingsForPath = bindings[j], firstActive = bindingsForPath[lastCachedIndex], binding = bindingsForPath[index];
|
|
bindingsForPath[index] = firstActive;
|
|
bindingsForPath[lastCachedIndex] = binding;
|
|
}
|
|
}
|
|
}
|
|
this.nCachedObjects_ = nCachedObjects;
|
|
}
|
|
uncache() {
|
|
const objects = this._objects, indicesByUUID = this._indicesByUUID, bindings = this._bindings, nBindings = bindings.length;
|
|
let nCachedObjects = this.nCachedObjects_, nObjects = objects.length;
|
|
for (let i = 0, n = arguments.length; i !== n; ++i) {
|
|
const object = arguments[i], uuid = object.uuid, index = indicesByUUID[uuid];
|
|
if (index !== void 0) {
|
|
delete indicesByUUID[uuid];
|
|
if (index < nCachedObjects) {
|
|
const firstActiveIndex = --nCachedObjects, lastCachedObject = objects[firstActiveIndex], lastIndex = --nObjects, lastObject = objects[lastIndex];
|
|
indicesByUUID[lastCachedObject.uuid] = index;
|
|
objects[index] = lastCachedObject;
|
|
indicesByUUID[lastObject.uuid] = firstActiveIndex;
|
|
objects[firstActiveIndex] = lastObject;
|
|
objects.pop();
|
|
for (let j = 0, m = nBindings; j !== m; ++j) {
|
|
const bindingsForPath = bindings[j], lastCached = bindingsForPath[firstActiveIndex], last = bindingsForPath[lastIndex];
|
|
bindingsForPath[index] = lastCached;
|
|
bindingsForPath[firstActiveIndex] = last;
|
|
bindingsForPath.pop();
|
|
}
|
|
} else {
|
|
const lastIndex = --nObjects, lastObject = objects[lastIndex];
|
|
if (lastIndex > 0) {
|
|
indicesByUUID[lastObject.uuid] = index;
|
|
}
|
|
objects[index] = lastObject;
|
|
objects.pop();
|
|
for (let j = 0, m = nBindings; j !== m; ++j) {
|
|
const bindingsForPath = bindings[j];
|
|
bindingsForPath[index] = bindingsForPath[lastIndex];
|
|
bindingsForPath.pop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.nCachedObjects_ = nCachedObjects;
|
|
}
|
|
subscribe_(path, parsedPath) {
|
|
const indicesByPath = this._bindingsIndicesByPath;
|
|
let index = indicesByPath[path];
|
|
const bindings = this._bindings;
|
|
if (index !== void 0)
|
|
return bindings[index];
|
|
const paths = this._paths, parsedPaths = this._parsedPaths, objects = this._objects, nObjects = objects.length, nCachedObjects = this.nCachedObjects_, bindingsForPath = new Array(nObjects);
|
|
index = bindings.length;
|
|
indicesByPath[path] = index;
|
|
paths.push(path);
|
|
parsedPaths.push(parsedPath);
|
|
bindings.push(bindingsForPath);
|
|
for (let i = nCachedObjects, n = objects.length; i !== n; ++i) {
|
|
const object = objects[i];
|
|
bindingsForPath[i] = new PropertyBinding(object, path, parsedPath);
|
|
}
|
|
return bindingsForPath;
|
|
}
|
|
unsubscribe_(path) {
|
|
const indicesByPath = this._bindingsIndicesByPath, index = indicesByPath[path];
|
|
if (index !== void 0) {
|
|
const paths = this._paths, parsedPaths = this._parsedPaths, bindings = this._bindings, lastBindingsIndex = bindings.length - 1, lastBindings = bindings[lastBindingsIndex], lastBindingsPath = path[lastBindingsIndex];
|
|
indicesByPath[lastBindingsPath] = index;
|
|
bindings[index] = lastBindings;
|
|
bindings.pop();
|
|
parsedPaths[index] = parsedPaths[lastBindingsIndex];
|
|
parsedPaths.pop();
|
|
paths[index] = paths[lastBindingsIndex];
|
|
paths.pop();
|
|
}
|
|
}
|
|
};
|
|
AnimationObjectGroup.prototype.isAnimationObjectGroup = true;
|
|
var AnimationAction = class {
|
|
constructor(mixer, clip, localRoot = null, blendMode = clip.blendMode) {
|
|
this._mixer = mixer;
|
|
this._clip = clip;
|
|
this._localRoot = localRoot;
|
|
this.blendMode = blendMode;
|
|
const tracks = clip.tracks, nTracks = tracks.length, interpolants = new Array(nTracks);
|
|
const interpolantSettings = {
|
|
endingStart: ZeroCurvatureEnding,
|
|
endingEnd: ZeroCurvatureEnding
|
|
};
|
|
for (let i = 0; i !== nTracks; ++i) {
|
|
const interpolant = tracks[i].createInterpolant(null);
|
|
interpolants[i] = interpolant;
|
|
interpolant.settings = interpolantSettings;
|
|
}
|
|
this._interpolantSettings = interpolantSettings;
|
|
this._interpolants = interpolants;
|
|
this._propertyBindings = new Array(nTracks);
|
|
this._cacheIndex = null;
|
|
this._byClipCacheIndex = null;
|
|
this._timeScaleInterpolant = null;
|
|
this._weightInterpolant = null;
|
|
this.loop = LoopRepeat;
|
|
this._loopCount = -1;
|
|
this._startTime = null;
|
|
this.time = 0;
|
|
this.timeScale = 1;
|
|
this._effectiveTimeScale = 1;
|
|
this.weight = 1;
|
|
this._effectiveWeight = 1;
|
|
this.repetitions = Infinity;
|
|
this.paused = false;
|
|
this.enabled = true;
|
|
this.clampWhenFinished = false;
|
|
this.zeroSlopeAtStart = true;
|
|
this.zeroSlopeAtEnd = true;
|
|
}
|
|
play() {
|
|
this._mixer._activateAction(this);
|
|
return this;
|
|
}
|
|
stop() {
|
|
this._mixer._deactivateAction(this);
|
|
return this.reset();
|
|
}
|
|
reset() {
|
|
this.paused = false;
|
|
this.enabled = true;
|
|
this.time = 0;
|
|
this._loopCount = -1;
|
|
this._startTime = null;
|
|
return this.stopFading().stopWarping();
|
|
}
|
|
isRunning() {
|
|
return this.enabled && !this.paused && this.timeScale !== 0 && this._startTime === null && this._mixer._isActiveAction(this);
|
|
}
|
|
isScheduled() {
|
|
return this._mixer._isActiveAction(this);
|
|
}
|
|
startAt(time) {
|
|
this._startTime = time;
|
|
return this;
|
|
}
|
|
setLoop(mode, repetitions) {
|
|
this.loop = mode;
|
|
this.repetitions = repetitions;
|
|
return this;
|
|
}
|
|
setEffectiveWeight(weight) {
|
|
this.weight = weight;
|
|
this._effectiveWeight = this.enabled ? weight : 0;
|
|
return this.stopFading();
|
|
}
|
|
getEffectiveWeight() {
|
|
return this._effectiveWeight;
|
|
}
|
|
fadeIn(duration) {
|
|
return this._scheduleFading(duration, 0, 1);
|
|
}
|
|
fadeOut(duration) {
|
|
return this._scheduleFading(duration, 1, 0);
|
|
}
|
|
crossFadeFrom(fadeOutAction, duration, warp) {
|
|
fadeOutAction.fadeOut(duration);
|
|
this.fadeIn(duration);
|
|
if (warp) {
|
|
const fadeInDuration = this._clip.duration, fadeOutDuration = fadeOutAction._clip.duration, startEndRatio = fadeOutDuration / fadeInDuration, endStartRatio = fadeInDuration / fadeOutDuration;
|
|
fadeOutAction.warp(1, startEndRatio, duration);
|
|
this.warp(endStartRatio, 1, duration);
|
|
}
|
|
return this;
|
|
}
|
|
crossFadeTo(fadeInAction, duration, warp) {
|
|
return fadeInAction.crossFadeFrom(this, duration, warp);
|
|
}
|
|
stopFading() {
|
|
const weightInterpolant = this._weightInterpolant;
|
|
if (weightInterpolant !== null) {
|
|
this._weightInterpolant = null;
|
|
this._mixer._takeBackControlInterpolant(weightInterpolant);
|
|
}
|
|
return this;
|
|
}
|
|
setEffectiveTimeScale(timeScale) {
|
|
this.timeScale = timeScale;
|
|
this._effectiveTimeScale = this.paused ? 0 : timeScale;
|
|
return this.stopWarping();
|
|
}
|
|
getEffectiveTimeScale() {
|
|
return this._effectiveTimeScale;
|
|
}
|
|
setDuration(duration) {
|
|
this.timeScale = this._clip.duration / duration;
|
|
return this.stopWarping();
|
|
}
|
|
syncWith(action) {
|
|
this.time = action.time;
|
|
this.timeScale = action.timeScale;
|
|
return this.stopWarping();
|
|
}
|
|
halt(duration) {
|
|
return this.warp(this._effectiveTimeScale, 0, duration);
|
|
}
|
|
warp(startTimeScale, endTimeScale, duration) {
|
|
const mixer = this._mixer, now = mixer.time, timeScale = this.timeScale;
|
|
let interpolant = this._timeScaleInterpolant;
|
|
if (interpolant === null) {
|
|
interpolant = mixer._lendControlInterpolant();
|
|
this._timeScaleInterpolant = interpolant;
|
|
}
|
|
const times = interpolant.parameterPositions, values = interpolant.sampleValues;
|
|
times[0] = now;
|
|
times[1] = now + duration;
|
|
values[0] = startTimeScale / timeScale;
|
|
values[1] = endTimeScale / timeScale;
|
|
return this;
|
|
}
|
|
stopWarping() {
|
|
const timeScaleInterpolant = this._timeScaleInterpolant;
|
|
if (timeScaleInterpolant !== null) {
|
|
this._timeScaleInterpolant = null;
|
|
this._mixer._takeBackControlInterpolant(timeScaleInterpolant);
|
|
}
|
|
return this;
|
|
}
|
|
getMixer() {
|
|
return this._mixer;
|
|
}
|
|
getClip() {
|
|
return this._clip;
|
|
}
|
|
getRoot() {
|
|
return this._localRoot || this._mixer._root;
|
|
}
|
|
_update(time, deltaTime, timeDirection, accuIndex) {
|
|
if (!this.enabled) {
|
|
this._updateWeight(time);
|
|
return;
|
|
}
|
|
const startTime = this._startTime;
|
|
if (startTime !== null) {
|
|
const timeRunning = (time - startTime) * timeDirection;
|
|
if (timeRunning < 0 || timeDirection === 0) {
|
|
return;
|
|
}
|
|
this._startTime = null;
|
|
deltaTime = timeDirection * timeRunning;
|
|
}
|
|
deltaTime *= this._updateTimeScale(time);
|
|
const clipTime = this._updateTime(deltaTime);
|
|
const weight = this._updateWeight(time);
|
|
if (weight > 0) {
|
|
const interpolants = this._interpolants;
|
|
const propertyMixers = this._propertyBindings;
|
|
switch (this.blendMode) {
|
|
case AdditiveAnimationBlendMode:
|
|
for (let j = 0, m = interpolants.length; j !== m; ++j) {
|
|
interpolants[j].evaluate(clipTime);
|
|
propertyMixers[j].accumulateAdditive(weight);
|
|
}
|
|
break;
|
|
case NormalAnimationBlendMode:
|
|
default:
|
|
for (let j = 0, m = interpolants.length; j !== m; ++j) {
|
|
interpolants[j].evaluate(clipTime);
|
|
propertyMixers[j].accumulate(accuIndex, weight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_updateWeight(time) {
|
|
let weight = 0;
|
|
if (this.enabled) {
|
|
weight = this.weight;
|
|
const interpolant = this._weightInterpolant;
|
|
if (interpolant !== null) {
|
|
const interpolantValue = interpolant.evaluate(time)[0];
|
|
weight *= interpolantValue;
|
|
if (time > interpolant.parameterPositions[1]) {
|
|
this.stopFading();
|
|
if (interpolantValue === 0) {
|
|
this.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this._effectiveWeight = weight;
|
|
return weight;
|
|
}
|
|
_updateTimeScale(time) {
|
|
let timeScale = 0;
|
|
if (!this.paused) {
|
|
timeScale = this.timeScale;
|
|
const interpolant = this._timeScaleInterpolant;
|
|
if (interpolant !== null) {
|
|
const interpolantValue = interpolant.evaluate(time)[0];
|
|
timeScale *= interpolantValue;
|
|
if (time > interpolant.parameterPositions[1]) {
|
|
this.stopWarping();
|
|
if (timeScale === 0) {
|
|
this.paused = true;
|
|
} else {
|
|
this.timeScale = timeScale;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this._effectiveTimeScale = timeScale;
|
|
return timeScale;
|
|
}
|
|
_updateTime(deltaTime) {
|
|
const duration = this._clip.duration;
|
|
const loop = this.loop;
|
|
let time = this.time + deltaTime;
|
|
let loopCount = this._loopCount;
|
|
const pingPong = loop === LoopPingPong;
|
|
if (deltaTime === 0) {
|
|
if (loopCount === -1)
|
|
return time;
|
|
return pingPong && (loopCount & 1) === 1 ? duration - time : time;
|
|
}
|
|
if (loop === LoopOnce) {
|
|
if (loopCount === -1) {
|
|
this._loopCount = 0;
|
|
this._setEndings(true, true, false);
|
|
}
|
|
handle_stop: {
|
|
if (time >= duration) {
|
|
time = duration;
|
|
} else if (time < 0) {
|
|
time = 0;
|
|
} else {
|
|
this.time = time;
|
|
break handle_stop;
|
|
}
|
|
if (this.clampWhenFinished)
|
|
this.paused = true;
|
|
else
|
|
this.enabled = false;
|
|
this.time = time;
|
|
this._mixer.dispatchEvent({
|
|
type: "finished",
|
|
action: this,
|
|
direction: deltaTime < 0 ? -1 : 1
|
|
});
|
|
}
|
|
} else {
|
|
if (loopCount === -1) {
|
|
if (deltaTime >= 0) {
|
|
loopCount = 0;
|
|
this._setEndings(true, this.repetitions === 0, pingPong);
|
|
} else {
|
|
this._setEndings(this.repetitions === 0, true, pingPong);
|
|
}
|
|
}
|
|
if (time >= duration || time < 0) {
|
|
const loopDelta = Math.floor(time / duration);
|
|
time -= duration * loopDelta;
|
|
loopCount += Math.abs(loopDelta);
|
|
const pending = this.repetitions - loopCount;
|
|
if (pending <= 0) {
|
|
if (this.clampWhenFinished)
|
|
this.paused = true;
|
|
else
|
|
this.enabled = false;
|
|
time = deltaTime > 0 ? duration : 0;
|
|
this.time = time;
|
|
this._mixer.dispatchEvent({
|
|
type: "finished",
|
|
action: this,
|
|
direction: deltaTime > 0 ? 1 : -1
|
|
});
|
|
} else {
|
|
if (pending === 1) {
|
|
const atStart = deltaTime < 0;
|
|
this._setEndings(atStart, !atStart, pingPong);
|
|
} else {
|
|
this._setEndings(false, false, pingPong);
|
|
}
|
|
this._loopCount = loopCount;
|
|
this.time = time;
|
|
this._mixer.dispatchEvent({
|
|
type: "loop",
|
|
action: this,
|
|
loopDelta
|
|
});
|
|
}
|
|
} else {
|
|
this.time = time;
|
|
}
|
|
if (pingPong && (loopCount & 1) === 1) {
|
|
return duration - time;
|
|
}
|
|
}
|
|
return time;
|
|
}
|
|
_setEndings(atStart, atEnd, pingPong) {
|
|
const settings = this._interpolantSettings;
|
|
if (pingPong) {
|
|
settings.endingStart = ZeroSlopeEnding;
|
|
settings.endingEnd = ZeroSlopeEnding;
|
|
} else {
|
|
if (atStart) {
|
|
settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
|
|
} else {
|
|
settings.endingStart = WrapAroundEnding;
|
|
}
|
|
if (atEnd) {
|
|
settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
|
|
} else {
|
|
settings.endingEnd = WrapAroundEnding;
|
|
}
|
|
}
|
|
}
|
|
_scheduleFading(duration, weightNow, weightThen) {
|
|
const mixer = this._mixer, now = mixer.time;
|
|
let interpolant = this._weightInterpolant;
|
|
if (interpolant === null) {
|
|
interpolant = mixer._lendControlInterpolant();
|
|
this._weightInterpolant = interpolant;
|
|
}
|
|
const times = interpolant.parameterPositions, values = interpolant.sampleValues;
|
|
times[0] = now;
|
|
values[0] = weightNow;
|
|
times[1] = now + duration;
|
|
values[1] = weightThen;
|
|
return this;
|
|
}
|
|
};
|
|
var AnimationMixer = class extends EventDispatcher {
|
|
constructor(root) {
|
|
super();
|
|
this._root = root;
|
|
this._initMemoryManager();
|
|
this._accuIndex = 0;
|
|
this.time = 0;
|
|
this.timeScale = 1;
|
|
}
|
|
_bindAction(action, prototypeAction) {
|
|
const root = action._localRoot || this._root, tracks = action._clip.tracks, nTracks = tracks.length, bindings = action._propertyBindings, interpolants = action._interpolants, rootUuid = root.uuid, bindingsByRoot = this._bindingsByRootAndName;
|
|
let bindingsByName = bindingsByRoot[rootUuid];
|
|
if (bindingsByName === void 0) {
|
|
bindingsByName = {};
|
|
bindingsByRoot[rootUuid] = bindingsByName;
|
|
}
|
|
for (let i = 0; i !== nTracks; ++i) {
|
|
const track = tracks[i], trackName = track.name;
|
|
let binding = bindingsByName[trackName];
|
|
if (binding !== void 0) {
|
|
bindings[i] = binding;
|
|
} else {
|
|
binding = bindings[i];
|
|
if (binding !== void 0) {
|
|
if (binding._cacheIndex === null) {
|
|
++binding.referenceCount;
|
|
this._addInactiveBinding(binding, rootUuid, trackName);
|
|
}
|
|
continue;
|
|
}
|
|
const path = prototypeAction && prototypeAction._propertyBindings[i].binding.parsedPath;
|
|
binding = new PropertyMixer(PropertyBinding.create(root, trackName, path), track.ValueTypeName, track.getValueSize());
|
|
++binding.referenceCount;
|
|
this._addInactiveBinding(binding, rootUuid, trackName);
|
|
bindings[i] = binding;
|
|
}
|
|
interpolants[i].resultBuffer = binding.buffer;
|
|
}
|
|
}
|
|
_activateAction(action) {
|
|
if (!this._isActiveAction(action)) {
|
|
if (action._cacheIndex === null) {
|
|
const rootUuid = (action._localRoot || this._root).uuid, clipUuid = action._clip.uuid, actionsForClip = this._actionsByClip[clipUuid];
|
|
this._bindAction(action, actionsForClip && actionsForClip.knownActions[0]);
|
|
this._addInactiveAction(action, clipUuid, rootUuid);
|
|
}
|
|
const bindings = action._propertyBindings;
|
|
for (let i = 0, n = bindings.length; i !== n; ++i) {
|
|
const binding = bindings[i];
|
|
if (binding.useCount++ === 0) {
|
|
this._lendBinding(binding);
|
|
binding.saveOriginalState();
|
|
}
|
|
}
|
|
this._lendAction(action);
|
|
}
|
|
}
|
|
_deactivateAction(action) {
|
|
if (this._isActiveAction(action)) {
|
|
const bindings = action._propertyBindings;
|
|
for (let i = 0, n = bindings.length; i !== n; ++i) {
|
|
const binding = bindings[i];
|
|
if (--binding.useCount === 0) {
|
|
binding.restoreOriginalState();
|
|
this._takeBackBinding(binding);
|
|
}
|
|
}
|
|
this._takeBackAction(action);
|
|
}
|
|
}
|
|
_initMemoryManager() {
|
|
this._actions = [];
|
|
this._nActiveActions = 0;
|
|
this._actionsByClip = {};
|
|
this._bindings = [];
|
|
this._nActiveBindings = 0;
|
|
this._bindingsByRootAndName = {};
|
|
this._controlInterpolants = [];
|
|
this._nActiveControlInterpolants = 0;
|
|
const scope = this;
|
|
this.stats = {
|
|
actions: {
|
|
get total() {
|
|
return scope._actions.length;
|
|
},
|
|
get inUse() {
|
|
return scope._nActiveActions;
|
|
}
|
|
},
|
|
bindings: {
|
|
get total() {
|
|
return scope._bindings.length;
|
|
},
|
|
get inUse() {
|
|
return scope._nActiveBindings;
|
|
}
|
|
},
|
|
controlInterpolants: {
|
|
get total() {
|
|
return scope._controlInterpolants.length;
|
|
},
|
|
get inUse() {
|
|
return scope._nActiveControlInterpolants;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
_isActiveAction(action) {
|
|
const index = action._cacheIndex;
|
|
return index !== null && index < this._nActiveActions;
|
|
}
|
|
_addInactiveAction(action, clipUuid, rootUuid) {
|
|
const actions = this._actions, actionsByClip = this._actionsByClip;
|
|
let actionsForClip = actionsByClip[clipUuid];
|
|
if (actionsForClip === void 0) {
|
|
actionsForClip = {
|
|
knownActions: [action],
|
|
actionByRoot: {}
|
|
};
|
|
action._byClipCacheIndex = 0;
|
|
actionsByClip[clipUuid] = actionsForClip;
|
|
} else {
|
|
const knownActions = actionsForClip.knownActions;
|
|
action._byClipCacheIndex = knownActions.length;
|
|
knownActions.push(action);
|
|
}
|
|
action._cacheIndex = actions.length;
|
|
actions.push(action);
|
|
actionsForClip.actionByRoot[rootUuid] = action;
|
|
}
|
|
_removeInactiveAction(action) {
|
|
const actions = this._actions, lastInactiveAction = actions[actions.length - 1], cacheIndex = action._cacheIndex;
|
|
lastInactiveAction._cacheIndex = cacheIndex;
|
|
actions[cacheIndex] = lastInactiveAction;
|
|
actions.pop();
|
|
action._cacheIndex = null;
|
|
const clipUuid = action._clip.uuid, actionsByClip = this._actionsByClip, actionsForClip = actionsByClip[clipUuid], knownActionsForClip = actionsForClip.knownActions, lastKnownAction = knownActionsForClip[knownActionsForClip.length - 1], byClipCacheIndex = action._byClipCacheIndex;
|
|
lastKnownAction._byClipCacheIndex = byClipCacheIndex;
|
|
knownActionsForClip[byClipCacheIndex] = lastKnownAction;
|
|
knownActionsForClip.pop();
|
|
action._byClipCacheIndex = null;
|
|
const actionByRoot = actionsForClip.actionByRoot, rootUuid = (action._localRoot || this._root).uuid;
|
|
delete actionByRoot[rootUuid];
|
|
if (knownActionsForClip.length === 0) {
|
|
delete actionsByClip[clipUuid];
|
|
}
|
|
this._removeInactiveBindingsForAction(action);
|
|
}
|
|
_removeInactiveBindingsForAction(action) {
|
|
const bindings = action._propertyBindings;
|
|
for (let i = 0, n = bindings.length; i !== n; ++i) {
|
|
const binding = bindings[i];
|
|
if (--binding.referenceCount === 0) {
|
|
this._removeInactiveBinding(binding);
|
|
}
|
|
}
|
|
}
|
|
_lendAction(action) {
|
|
const actions = this._actions, prevIndex = action._cacheIndex, lastActiveIndex = this._nActiveActions++, firstInactiveAction = actions[lastActiveIndex];
|
|
action._cacheIndex = lastActiveIndex;
|
|
actions[lastActiveIndex] = action;
|
|
firstInactiveAction._cacheIndex = prevIndex;
|
|
actions[prevIndex] = firstInactiveAction;
|
|
}
|
|
_takeBackAction(action) {
|
|
const actions = this._actions, prevIndex = action._cacheIndex, firstInactiveIndex = --this._nActiveActions, lastActiveAction = actions[firstInactiveIndex];
|
|
action._cacheIndex = firstInactiveIndex;
|
|
actions[firstInactiveIndex] = action;
|
|
lastActiveAction._cacheIndex = prevIndex;
|
|
actions[prevIndex] = lastActiveAction;
|
|
}
|
|
_addInactiveBinding(binding, rootUuid, trackName) {
|
|
const bindingsByRoot = this._bindingsByRootAndName, bindings = this._bindings;
|
|
let bindingByName = bindingsByRoot[rootUuid];
|
|
if (bindingByName === void 0) {
|
|
bindingByName = {};
|
|
bindingsByRoot[rootUuid] = bindingByName;
|
|
}
|
|
bindingByName[trackName] = binding;
|
|
binding._cacheIndex = bindings.length;
|
|
bindings.push(binding);
|
|
}
|
|
_removeInactiveBinding(binding) {
|
|
const bindings = this._bindings, propBinding = binding.binding, rootUuid = propBinding.rootNode.uuid, trackName = propBinding.path, bindingsByRoot = this._bindingsByRootAndName, bindingByName = bindingsByRoot[rootUuid], lastInactiveBinding = bindings[bindings.length - 1], cacheIndex = binding._cacheIndex;
|
|
lastInactiveBinding._cacheIndex = cacheIndex;
|
|
bindings[cacheIndex] = lastInactiveBinding;
|
|
bindings.pop();
|
|
delete bindingByName[trackName];
|
|
if (Object.keys(bindingByName).length === 0) {
|
|
delete bindingsByRoot[rootUuid];
|
|
}
|
|
}
|
|
_lendBinding(binding) {
|
|
const bindings = this._bindings, prevIndex = binding._cacheIndex, lastActiveIndex = this._nActiveBindings++, firstInactiveBinding = bindings[lastActiveIndex];
|
|
binding._cacheIndex = lastActiveIndex;
|
|
bindings[lastActiveIndex] = binding;
|
|
firstInactiveBinding._cacheIndex = prevIndex;
|
|
bindings[prevIndex] = firstInactiveBinding;
|
|
}
|
|
_takeBackBinding(binding) {
|
|
const bindings = this._bindings, prevIndex = binding._cacheIndex, firstInactiveIndex = --this._nActiveBindings, lastActiveBinding = bindings[firstInactiveIndex];
|
|
binding._cacheIndex = firstInactiveIndex;
|
|
bindings[firstInactiveIndex] = binding;
|
|
lastActiveBinding._cacheIndex = prevIndex;
|
|
bindings[prevIndex] = lastActiveBinding;
|
|
}
|
|
_lendControlInterpolant() {
|
|
const interpolants = this._controlInterpolants, lastActiveIndex = this._nActiveControlInterpolants++;
|
|
let interpolant = interpolants[lastActiveIndex];
|
|
if (interpolant === void 0) {
|
|
interpolant = new LinearInterpolant(new Float32Array(2), new Float32Array(2), 1, this._controlInterpolantsResultBuffer);
|
|
interpolant.__cacheIndex = lastActiveIndex;
|
|
interpolants[lastActiveIndex] = interpolant;
|
|
}
|
|
return interpolant;
|
|
}
|
|
_takeBackControlInterpolant(interpolant) {
|
|
const interpolants = this._controlInterpolants, prevIndex = interpolant.__cacheIndex, firstInactiveIndex = --this._nActiveControlInterpolants, lastActiveInterpolant = interpolants[firstInactiveIndex];
|
|
interpolant.__cacheIndex = firstInactiveIndex;
|
|
interpolants[firstInactiveIndex] = interpolant;
|
|
lastActiveInterpolant.__cacheIndex = prevIndex;
|
|
interpolants[prevIndex] = lastActiveInterpolant;
|
|
}
|
|
clipAction(clip, optionalRoot, blendMode) {
|
|
const root = optionalRoot || this._root, rootUuid = root.uuid;
|
|
let clipObject = typeof clip === "string" ? AnimationClip.findByName(root, clip) : clip;
|
|
const clipUuid = clipObject !== null ? clipObject.uuid : clip;
|
|
const actionsForClip = this._actionsByClip[clipUuid];
|
|
let prototypeAction = null;
|
|
if (blendMode === void 0) {
|
|
if (clipObject !== null) {
|
|
blendMode = clipObject.blendMode;
|
|
} else {
|
|
blendMode = NormalAnimationBlendMode;
|
|
}
|
|
}
|
|
if (actionsForClip !== void 0) {
|
|
const existingAction = actionsForClip.actionByRoot[rootUuid];
|
|
if (existingAction !== void 0 && existingAction.blendMode === blendMode) {
|
|
return existingAction;
|
|
}
|
|
prototypeAction = actionsForClip.knownActions[0];
|
|
if (clipObject === null)
|
|
clipObject = prototypeAction._clip;
|
|
}
|
|
if (clipObject === null)
|
|
return null;
|
|
const newAction = new AnimationAction(this, clipObject, optionalRoot, blendMode);
|
|
this._bindAction(newAction, prototypeAction);
|
|
this._addInactiveAction(newAction, clipUuid, rootUuid);
|
|
return newAction;
|
|
}
|
|
existingAction(clip, optionalRoot) {
|
|
const root = optionalRoot || this._root, rootUuid = root.uuid, clipObject = typeof clip === "string" ? AnimationClip.findByName(root, clip) : clip, clipUuid = clipObject ? clipObject.uuid : clip, actionsForClip = this._actionsByClip[clipUuid];
|
|
if (actionsForClip !== void 0) {
|
|
return actionsForClip.actionByRoot[rootUuid] || null;
|
|
}
|
|
return null;
|
|
}
|
|
stopAllAction() {
|
|
const actions = this._actions, nActions = this._nActiveActions;
|
|
for (let i = nActions - 1; i >= 0; --i) {
|
|
actions[i].stop();
|
|
}
|
|
return this;
|
|
}
|
|
update(deltaTime) {
|
|
deltaTime *= this.timeScale;
|
|
const actions = this._actions, nActions = this._nActiveActions, time = this.time += deltaTime, timeDirection = Math.sign(deltaTime), accuIndex = this._accuIndex ^= 1;
|
|
for (let i = 0; i !== nActions; ++i) {
|
|
const action = actions[i];
|
|
action._update(time, deltaTime, timeDirection, accuIndex);
|
|
}
|
|
const bindings = this._bindings, nBindings = this._nActiveBindings;
|
|
for (let i = 0; i !== nBindings; ++i) {
|
|
bindings[i].apply(accuIndex);
|
|
}
|
|
return this;
|
|
}
|
|
setTime(timeInSeconds) {
|
|
this.time = 0;
|
|
for (let i = 0; i < this._actions.length; i++) {
|
|
this._actions[i].time = 0;
|
|
}
|
|
return this.update(timeInSeconds);
|
|
}
|
|
getRoot() {
|
|
return this._root;
|
|
}
|
|
uncacheClip(clip) {
|
|
const actions = this._actions, clipUuid = clip.uuid, actionsByClip = this._actionsByClip, actionsForClip = actionsByClip[clipUuid];
|
|
if (actionsForClip !== void 0) {
|
|
const actionsToRemove = actionsForClip.knownActions;
|
|
for (let i = 0, n = actionsToRemove.length; i !== n; ++i) {
|
|
const action = actionsToRemove[i];
|
|
this._deactivateAction(action);
|
|
const cacheIndex = action._cacheIndex, lastInactiveAction = actions[actions.length - 1];
|
|
action._cacheIndex = null;
|
|
action._byClipCacheIndex = null;
|
|
lastInactiveAction._cacheIndex = cacheIndex;
|
|
actions[cacheIndex] = lastInactiveAction;
|
|
actions.pop();
|
|
this._removeInactiveBindingsForAction(action);
|
|
}
|
|
delete actionsByClip[clipUuid];
|
|
}
|
|
}
|
|
uncacheRoot(root) {
|
|
const rootUuid = root.uuid, actionsByClip = this._actionsByClip;
|
|
for (const clipUuid in actionsByClip) {
|
|
const actionByRoot = actionsByClip[clipUuid].actionByRoot, action = actionByRoot[rootUuid];
|
|
if (action !== void 0) {
|
|
this._deactivateAction(action);
|
|
this._removeInactiveAction(action);
|
|
}
|
|
}
|
|
const bindingsByRoot = this._bindingsByRootAndName, bindingByName = bindingsByRoot[rootUuid];
|
|
if (bindingByName !== void 0) {
|
|
for (const trackName in bindingByName) {
|
|
const binding = bindingByName[trackName];
|
|
binding.restoreOriginalState();
|
|
this._removeInactiveBinding(binding);
|
|
}
|
|
}
|
|
}
|
|
uncacheAction(clip, optionalRoot) {
|
|
const action = this.existingAction(clip, optionalRoot);
|
|
if (action !== null) {
|
|
this._deactivateAction(action);
|
|
this._removeInactiveAction(action);
|
|
}
|
|
}
|
|
};
|
|
AnimationMixer.prototype._controlInterpolantsResultBuffer = new Float32Array(1);
|
|
var Uniform = class {
|
|
constructor(value) {
|
|
if (typeof value === "string") {
|
|
console.warn("THREE.Uniform: Type parameter is no longer needed.");
|
|
value = arguments[1];
|
|
}
|
|
this.value = value;
|
|
}
|
|
clone() {
|
|
return new Uniform(this.value.clone === void 0 ? this.value : this.value.clone());
|
|
}
|
|
};
|
|
var InstancedInterleavedBuffer = class extends InterleavedBuffer {
|
|
constructor(array, stride, meshPerAttribute = 1) {
|
|
super(array, stride);
|
|
this.meshPerAttribute = meshPerAttribute;
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.meshPerAttribute = source.meshPerAttribute;
|
|
return this;
|
|
}
|
|
clone(data) {
|
|
const ib = super.clone(data);
|
|
ib.meshPerAttribute = this.meshPerAttribute;
|
|
return ib;
|
|
}
|
|
toJSON(data) {
|
|
const json = super.toJSON(data);
|
|
json.isInstancedInterleavedBuffer = true;
|
|
json.meshPerAttribute = this.meshPerAttribute;
|
|
return json;
|
|
}
|
|
};
|
|
InstancedInterleavedBuffer.prototype.isInstancedInterleavedBuffer = true;
|
|
var GLBufferAttribute = class {
|
|
constructor(buffer, type, itemSize, elementSize, count) {
|
|
this.buffer = buffer;
|
|
this.type = type;
|
|
this.itemSize = itemSize;
|
|
this.elementSize = elementSize;
|
|
this.count = count;
|
|
this.version = 0;
|
|
}
|
|
set needsUpdate(value) {
|
|
if (value === true)
|
|
this.version++;
|
|
}
|
|
setBuffer(buffer) {
|
|
this.buffer = buffer;
|
|
return this;
|
|
}
|
|
setType(type, elementSize) {
|
|
this.type = type;
|
|
this.elementSize = elementSize;
|
|
return this;
|
|
}
|
|
setItemSize(itemSize) {
|
|
this.itemSize = itemSize;
|
|
return this;
|
|
}
|
|
setCount(count) {
|
|
this.count = count;
|
|
return this;
|
|
}
|
|
};
|
|
GLBufferAttribute.prototype.isGLBufferAttribute = true;
|
|
var _vector$4 = /* @__PURE__ */ new Vector2();
|
|
var Box2 = class {
|
|
constructor(min = new Vector2(Infinity, Infinity), max = new Vector2(-Infinity, -Infinity)) {
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
set(min, max) {
|
|
this.min.copy(min);
|
|
this.max.copy(max);
|
|
return this;
|
|
}
|
|
setFromPoints(points) {
|
|
this.makeEmpty();
|
|
for (let i = 0, il = points.length; i < il; i++) {
|
|
this.expandByPoint(points[i]);
|
|
}
|
|
return this;
|
|
}
|
|
setFromCenterAndSize(center, size) {
|
|
const halfSize = _vector$4.copy(size).multiplyScalar(0.5);
|
|
this.min.copy(center).sub(halfSize);
|
|
this.max.copy(center).add(halfSize);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
copy(box) {
|
|
this.min.copy(box.min);
|
|
this.max.copy(box.max);
|
|
return this;
|
|
}
|
|
makeEmpty() {
|
|
this.min.x = this.min.y = Infinity;
|
|
this.max.x = this.max.y = -Infinity;
|
|
return this;
|
|
}
|
|
isEmpty() {
|
|
return this.max.x < this.min.x || this.max.y < this.min.y;
|
|
}
|
|
getCenter(target) {
|
|
return this.isEmpty() ? target.set(0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);
|
|
}
|
|
getSize(target) {
|
|
return this.isEmpty() ? target.set(0, 0) : target.subVectors(this.max, this.min);
|
|
}
|
|
expandByPoint(point) {
|
|
this.min.min(point);
|
|
this.max.max(point);
|
|
return this;
|
|
}
|
|
expandByVector(vector) {
|
|
this.min.sub(vector);
|
|
this.max.add(vector);
|
|
return this;
|
|
}
|
|
expandByScalar(scalar) {
|
|
this.min.addScalar(-scalar);
|
|
this.max.addScalar(scalar);
|
|
return this;
|
|
}
|
|
containsPoint(point) {
|
|
return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y ? false : true;
|
|
}
|
|
containsBox(box) {
|
|
return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y;
|
|
}
|
|
getParameter(point, target) {
|
|
return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y));
|
|
}
|
|
intersectsBox(box) {
|
|
return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
|
|
}
|
|
clampPoint(point, target) {
|
|
return target.copy(point).clamp(this.min, this.max);
|
|
}
|
|
distanceToPoint(point) {
|
|
const clampedPoint = _vector$4.copy(point).clamp(this.min, this.max);
|
|
return clampedPoint.sub(point).length();
|
|
}
|
|
intersect(box) {
|
|
this.min.max(box.min);
|
|
this.max.min(box.max);
|
|
return this;
|
|
}
|
|
union(box) {
|
|
this.min.min(box.min);
|
|
this.max.max(box.max);
|
|
return this;
|
|
}
|
|
translate(offset) {
|
|
this.min.add(offset);
|
|
this.max.add(offset);
|
|
return this;
|
|
}
|
|
equals(box) {
|
|
return box.min.equals(this.min) && box.max.equals(this.max);
|
|
}
|
|
};
|
|
Box2.prototype.isBox2 = true;
|
|
var _startP = /* @__PURE__ */ new Vector3();
|
|
var _startEnd = /* @__PURE__ */ new Vector3();
|
|
var Line3 = class {
|
|
constructor(start = new Vector3(), end = new Vector3()) {
|
|
this.start = start;
|
|
this.end = end;
|
|
}
|
|
set(start, end) {
|
|
this.start.copy(start);
|
|
this.end.copy(end);
|
|
return this;
|
|
}
|
|
copy(line) {
|
|
this.start.copy(line.start);
|
|
this.end.copy(line.end);
|
|
return this;
|
|
}
|
|
getCenter(target) {
|
|
return target.addVectors(this.start, this.end).multiplyScalar(0.5);
|
|
}
|
|
delta(target) {
|
|
return target.subVectors(this.end, this.start);
|
|
}
|
|
distanceSq() {
|
|
return this.start.distanceToSquared(this.end);
|
|
}
|
|
distance() {
|
|
return this.start.distanceTo(this.end);
|
|
}
|
|
at(t, target) {
|
|
return this.delta(target).multiplyScalar(t).add(this.start);
|
|
}
|
|
closestPointToPointParameter(point, clampToLine) {
|
|
_startP.subVectors(point, this.start);
|
|
_startEnd.subVectors(this.end, this.start);
|
|
const startEnd2 = _startEnd.dot(_startEnd);
|
|
const startEnd_startP = _startEnd.dot(_startP);
|
|
let t = startEnd_startP / startEnd2;
|
|
if (clampToLine) {
|
|
t = clamp(t, 0, 1);
|
|
}
|
|
return t;
|
|
}
|
|
closestPointToPoint(point, clampToLine, target) {
|
|
const t = this.closestPointToPointParameter(point, clampToLine);
|
|
return this.delta(target).multiplyScalar(t).add(this.start);
|
|
}
|
|
applyMatrix4(matrix) {
|
|
this.start.applyMatrix4(matrix);
|
|
this.end.applyMatrix4(matrix);
|
|
return this;
|
|
}
|
|
equals(line) {
|
|
return line.start.equals(this.start) && line.end.equals(this.end);
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
var ImmediateRenderObject = class extends Object3D {
|
|
constructor(material) {
|
|
super();
|
|
this.material = material;
|
|
this.render = function() {
|
|
};
|
|
this.hasPositions = false;
|
|
this.hasNormals = false;
|
|
this.hasColors = false;
|
|
this.hasUvs = false;
|
|
this.positionArray = null;
|
|
this.normalArray = null;
|
|
this.colorArray = null;
|
|
this.uvArray = null;
|
|
this.count = 0;
|
|
}
|
|
};
|
|
ImmediateRenderObject.prototype.isImmediateRenderObject = true;
|
|
var _vector$2 = /* @__PURE__ */ new Vector3();
|
|
var _boneMatrix = /* @__PURE__ */ new Matrix4();
|
|
var _matrixWorldInv = /* @__PURE__ */ new Matrix4();
|
|
var SkeletonHelper = class extends LineSegments {
|
|
constructor(object) {
|
|
const bones = getBoneList(object);
|
|
const geometry = new BufferGeometry();
|
|
const vertices = [];
|
|
const colors = [];
|
|
const color1 = new Color(0, 0, 1);
|
|
const color2 = new Color(0, 1, 0);
|
|
for (let i = 0; i < bones.length; i++) {
|
|
const bone = bones[i];
|
|
if (bone.parent && bone.parent.isBone) {
|
|
vertices.push(0, 0, 0);
|
|
vertices.push(0, 0, 0);
|
|
colors.push(color1.r, color1.g, color1.b);
|
|
colors.push(color2.r, color2.g, color2.b);
|
|
}
|
|
}
|
|
geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
|
|
const material = new LineBasicMaterial({ vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true });
|
|
super(geometry, material);
|
|
this.type = "SkeletonHelper";
|
|
this.isSkeletonHelper = true;
|
|
this.root = object;
|
|
this.bones = bones;
|
|
this.matrix = object.matrixWorld;
|
|
this.matrixAutoUpdate = false;
|
|
}
|
|
updateMatrixWorld(force) {
|
|
const bones = this.bones;
|
|
const geometry = this.geometry;
|
|
const position = geometry.getAttribute("position");
|
|
_matrixWorldInv.copy(this.root.matrixWorld).invert();
|
|
for (let i = 0, j = 0; i < bones.length; i++) {
|
|
const bone = bones[i];
|
|
if (bone.parent && bone.parent.isBone) {
|
|
_boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld);
|
|
_vector$2.setFromMatrixPosition(_boneMatrix);
|
|
position.setXYZ(j, _vector$2.x, _vector$2.y, _vector$2.z);
|
|
_boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld);
|
|
_vector$2.setFromMatrixPosition(_boneMatrix);
|
|
position.setXYZ(j + 1, _vector$2.x, _vector$2.y, _vector$2.z);
|
|
j += 2;
|
|
}
|
|
}
|
|
geometry.getAttribute("position").needsUpdate = true;
|
|
super.updateMatrixWorld(force);
|
|
}
|
|
};
|
|
function getBoneList(object) {
|
|
const boneList = [];
|
|
if (object && object.isBone) {
|
|
boneList.push(object);
|
|
}
|
|
for (let i = 0; i < object.children.length; i++) {
|
|
boneList.push.apply(boneList, getBoneList(object.children[i]));
|
|
}
|
|
return boneList;
|
|
}
|
|
var GridHelper = class extends LineSegments {
|
|
constructor(size = 10, divisions = 10, color1 = 4473924, color2 = 8947848) {
|
|
color1 = new Color(color1);
|
|
color2 = new Color(color2);
|
|
const center = divisions / 2;
|
|
const step = size / divisions;
|
|
const halfSize = size / 2;
|
|
const vertices = [], colors = [];
|
|
for (let i = 0, j = 0, k = -halfSize; i <= divisions; i++, k += step) {
|
|
vertices.push(-halfSize, 0, k, halfSize, 0, k);
|
|
vertices.push(k, 0, -halfSize, k, 0, halfSize);
|
|
const color = i === center ? color1 : color2;
|
|
color.toArray(colors, j);
|
|
j += 3;
|
|
color.toArray(colors, j);
|
|
j += 3;
|
|
color.toArray(colors, j);
|
|
j += 3;
|
|
color.toArray(colors, j);
|
|
j += 3;
|
|
}
|
|
const geometry = new BufferGeometry();
|
|
geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
|
|
const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false });
|
|
super(geometry, material);
|
|
this.type = "GridHelper";
|
|
}
|
|
};
|
|
var _floatView = new Float32Array(1);
|
|
var _int32View = new Int32Array(_floatView.buffer);
|
|
Curve.create = function(construct, getPoint) {
|
|
console.log("THREE.Curve.create() has been deprecated");
|
|
construct.prototype = Object.create(Curve.prototype);
|
|
construct.prototype.constructor = construct;
|
|
construct.prototype.getPoint = getPoint;
|
|
return construct;
|
|
};
|
|
Path.prototype.fromPoints = function(points) {
|
|
console.warn("THREE.Path: .fromPoints() has been renamed to .setFromPoints().");
|
|
return this.setFromPoints(points);
|
|
};
|
|
GridHelper.prototype.setColors = function() {
|
|
console.error("THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.");
|
|
};
|
|
SkeletonHelper.prototype.update = function() {
|
|
console.error("THREE.SkeletonHelper: update() no longer needs to be called.");
|
|
};
|
|
Loader.prototype.extractUrlBase = function(url) {
|
|
console.warn("THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.");
|
|
return LoaderUtils.extractUrlBase(url);
|
|
};
|
|
Loader.Handlers = {
|
|
add: function() {
|
|
console.error("THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.");
|
|
},
|
|
get: function() {
|
|
console.error("THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.");
|
|
}
|
|
};
|
|
Box2.prototype.center = function(optionalTarget) {
|
|
console.warn("THREE.Box2: .center() has been renamed to .getCenter().");
|
|
return this.getCenter(optionalTarget);
|
|
};
|
|
Box2.prototype.empty = function() {
|
|
console.warn("THREE.Box2: .empty() has been renamed to .isEmpty().");
|
|
return this.isEmpty();
|
|
};
|
|
Box2.prototype.isIntersectionBox = function(box) {
|
|
console.warn("THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().");
|
|
return this.intersectsBox(box);
|
|
};
|
|
Box2.prototype.size = function(optionalTarget) {
|
|
console.warn("THREE.Box2: .size() has been renamed to .getSize().");
|
|
return this.getSize(optionalTarget);
|
|
};
|
|
Box3.prototype.center = function(optionalTarget) {
|
|
console.warn("THREE.Box3: .center() has been renamed to .getCenter().");
|
|
return this.getCenter(optionalTarget);
|
|
};
|
|
Box3.prototype.empty = function() {
|
|
console.warn("THREE.Box3: .empty() has been renamed to .isEmpty().");
|
|
return this.isEmpty();
|
|
};
|
|
Box3.prototype.isIntersectionBox = function(box) {
|
|
console.warn("THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().");
|
|
return this.intersectsBox(box);
|
|
};
|
|
Box3.prototype.isIntersectionSphere = function(sphere) {
|
|
console.warn("THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().");
|
|
return this.intersectsSphere(sphere);
|
|
};
|
|
Box3.prototype.size = function(optionalTarget) {
|
|
console.warn("THREE.Box3: .size() has been renamed to .getSize().");
|
|
return this.getSize(optionalTarget);
|
|
};
|
|
Sphere.prototype.empty = function() {
|
|
console.warn("THREE.Sphere: .empty() has been renamed to .isEmpty().");
|
|
return this.isEmpty();
|
|
};
|
|
Frustum.prototype.setFromMatrix = function(m) {
|
|
console.warn("THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().");
|
|
return this.setFromProjectionMatrix(m);
|
|
};
|
|
Line3.prototype.center = function(optionalTarget) {
|
|
console.warn("THREE.Line3: .center() has been renamed to .getCenter().");
|
|
return this.getCenter(optionalTarget);
|
|
};
|
|
Matrix3.prototype.flattenToArrayOffset = function(array, offset) {
|
|
console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
|
|
return this.toArray(array, offset);
|
|
};
|
|
Matrix3.prototype.multiplyVector3 = function(vector) {
|
|
console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");
|
|
return vector.applyMatrix3(this);
|
|
};
|
|
Matrix3.prototype.multiplyVector3Array = function() {
|
|
console.error("THREE.Matrix3: .multiplyVector3Array() has been removed.");
|
|
};
|
|
Matrix3.prototype.applyToBufferAttribute = function(attribute) {
|
|
console.warn("THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.");
|
|
return attribute.applyMatrix3(this);
|
|
};
|
|
Matrix3.prototype.applyToVector3Array = function() {
|
|
console.error("THREE.Matrix3: .applyToVector3Array() has been removed.");
|
|
};
|
|
Matrix3.prototype.getInverse = function(matrix) {
|
|
console.warn("THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.");
|
|
return this.copy(matrix).invert();
|
|
};
|
|
Matrix4.prototype.extractPosition = function(m) {
|
|
console.warn("THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().");
|
|
return this.copyPosition(m);
|
|
};
|
|
Matrix4.prototype.flattenToArrayOffset = function(array, offset) {
|
|
console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
|
|
return this.toArray(array, offset);
|
|
};
|
|
Matrix4.prototype.getPosition = function() {
|
|
console.warn("THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.");
|
|
return new Vector3().setFromMatrixColumn(this, 3);
|
|
};
|
|
Matrix4.prototype.setRotationFromQuaternion = function(q) {
|
|
console.warn("THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().");
|
|
return this.makeRotationFromQuaternion(q);
|
|
};
|
|
Matrix4.prototype.multiplyToArray = function() {
|
|
console.warn("THREE.Matrix4: .multiplyToArray() has been removed.");
|
|
};
|
|
Matrix4.prototype.multiplyVector3 = function(vector) {
|
|
console.warn("THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.");
|
|
return vector.applyMatrix4(this);
|
|
};
|
|
Matrix4.prototype.multiplyVector4 = function(vector) {
|
|
console.warn("THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.");
|
|
return vector.applyMatrix4(this);
|
|
};
|
|
Matrix4.prototype.multiplyVector3Array = function() {
|
|
console.error("THREE.Matrix4: .multiplyVector3Array() has been removed.");
|
|
};
|
|
Matrix4.prototype.rotateAxis = function(v) {
|
|
console.warn("THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.");
|
|
v.transformDirection(this);
|
|
};
|
|
Matrix4.prototype.crossVector = function(vector) {
|
|
console.warn("THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.");
|
|
return vector.applyMatrix4(this);
|
|
};
|
|
Matrix4.prototype.translate = function() {
|
|
console.error("THREE.Matrix4: .translate() has been removed.");
|
|
};
|
|
Matrix4.prototype.rotateX = function() {
|
|
console.error("THREE.Matrix4: .rotateX() has been removed.");
|
|
};
|
|
Matrix4.prototype.rotateY = function() {
|
|
console.error("THREE.Matrix4: .rotateY() has been removed.");
|
|
};
|
|
Matrix4.prototype.rotateZ = function() {
|
|
console.error("THREE.Matrix4: .rotateZ() has been removed.");
|
|
};
|
|
Matrix4.prototype.rotateByAxis = function() {
|
|
console.error("THREE.Matrix4: .rotateByAxis() has been removed.");
|
|
};
|
|
Matrix4.prototype.applyToBufferAttribute = function(attribute) {
|
|
console.warn("THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.");
|
|
return attribute.applyMatrix4(this);
|
|
};
|
|
Matrix4.prototype.applyToVector3Array = function() {
|
|
console.error("THREE.Matrix4: .applyToVector3Array() has been removed.");
|
|
};
|
|
Matrix4.prototype.makeFrustum = function(left, right, bottom, top, near, far) {
|
|
console.warn("THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.");
|
|
return this.makePerspective(left, right, top, bottom, near, far);
|
|
};
|
|
Matrix4.prototype.getInverse = function(matrix) {
|
|
console.warn("THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.");
|
|
return this.copy(matrix).invert();
|
|
};
|
|
Plane.prototype.isIntersectionLine = function(line) {
|
|
console.warn("THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().");
|
|
return this.intersectsLine(line);
|
|
};
|
|
Quaternion.prototype.multiplyVector3 = function(vector) {
|
|
console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.");
|
|
return vector.applyQuaternion(this);
|
|
};
|
|
Quaternion.prototype.inverse = function() {
|
|
console.warn("THREE.Quaternion: .inverse() has been renamed to invert().");
|
|
return this.invert();
|
|
};
|
|
Ray.prototype.isIntersectionBox = function(box) {
|
|
console.warn("THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().");
|
|
return this.intersectsBox(box);
|
|
};
|
|
Ray.prototype.isIntersectionPlane = function(plane) {
|
|
console.warn("THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().");
|
|
return this.intersectsPlane(plane);
|
|
};
|
|
Ray.prototype.isIntersectionSphere = function(sphere) {
|
|
console.warn("THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().");
|
|
return this.intersectsSphere(sphere);
|
|
};
|
|
Triangle.prototype.area = function() {
|
|
console.warn("THREE.Triangle: .area() has been renamed to .getArea().");
|
|
return this.getArea();
|
|
};
|
|
Triangle.prototype.barycoordFromPoint = function(point, target) {
|
|
console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().");
|
|
return this.getBarycoord(point, target);
|
|
};
|
|
Triangle.prototype.midpoint = function(target) {
|
|
console.warn("THREE.Triangle: .midpoint() has been renamed to .getMidpoint().");
|
|
return this.getMidpoint(target);
|
|
};
|
|
Triangle.prototypenormal = function(target) {
|
|
console.warn("THREE.Triangle: .normal() has been renamed to .getNormal().");
|
|
return this.getNormal(target);
|
|
};
|
|
Triangle.prototype.plane = function(target) {
|
|
console.warn("THREE.Triangle: .plane() has been renamed to .getPlane().");
|
|
return this.getPlane(target);
|
|
};
|
|
Triangle.barycoordFromPoint = function(point, a2, b2, c2, target) {
|
|
console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().");
|
|
return Triangle.getBarycoord(point, a2, b2, c2, target);
|
|
};
|
|
Triangle.normal = function(a2, b2, c2, target) {
|
|
console.warn("THREE.Triangle: .normal() has been renamed to .getNormal().");
|
|
return Triangle.getNormal(a2, b2, c2, target);
|
|
};
|
|
Shape.prototype.extractAllPoints = function(divisions) {
|
|
console.warn("THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.");
|
|
return this.extractPoints(divisions);
|
|
};
|
|
Shape.prototype.extrude = function(options) {
|
|
console.warn("THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.");
|
|
return new ExtrudeGeometry(this, options);
|
|
};
|
|
Shape.prototype.makeGeometry = function(options) {
|
|
console.warn("THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.");
|
|
return new ShapeGeometry(this, options);
|
|
};
|
|
Vector2.prototype.fromAttribute = function(attribute, index, offset) {
|
|
console.warn("THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().");
|
|
return this.fromBufferAttribute(attribute, index, offset);
|
|
};
|
|
Vector2.prototype.distanceToManhattan = function(v) {
|
|
console.warn("THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().");
|
|
return this.manhattanDistanceTo(v);
|
|
};
|
|
Vector2.prototype.lengthManhattan = function() {
|
|
console.warn("THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().");
|
|
return this.manhattanLength();
|
|
};
|
|
Vector3.prototype.setEulerFromRotationMatrix = function() {
|
|
console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.");
|
|
};
|
|
Vector3.prototype.setEulerFromQuaternion = function() {
|
|
console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.");
|
|
};
|
|
Vector3.prototype.getPositionFromMatrix = function(m) {
|
|
console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().");
|
|
return this.setFromMatrixPosition(m);
|
|
};
|
|
Vector3.prototype.getScaleFromMatrix = function(m) {
|
|
console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().");
|
|
return this.setFromMatrixScale(m);
|
|
};
|
|
Vector3.prototype.getColumnFromMatrix = function(index, matrix) {
|
|
console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().");
|
|
return this.setFromMatrixColumn(matrix, index);
|
|
};
|
|
Vector3.prototype.applyProjection = function(m) {
|
|
console.warn("THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.");
|
|
return this.applyMatrix4(m);
|
|
};
|
|
Vector3.prototype.fromAttribute = function(attribute, index, offset) {
|
|
console.warn("THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().");
|
|
return this.fromBufferAttribute(attribute, index, offset);
|
|
};
|
|
Vector3.prototype.distanceToManhattan = function(v) {
|
|
console.warn("THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().");
|
|
return this.manhattanDistanceTo(v);
|
|
};
|
|
Vector3.prototype.lengthManhattan = function() {
|
|
console.warn("THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().");
|
|
return this.manhattanLength();
|
|
};
|
|
Vector4.prototype.fromAttribute = function(attribute, index, offset) {
|
|
console.warn("THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().");
|
|
return this.fromBufferAttribute(attribute, index, offset);
|
|
};
|
|
Vector4.prototype.lengthManhattan = function() {
|
|
console.warn("THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().");
|
|
return this.manhattanLength();
|
|
};
|
|
Object3D.prototype.getChildByName = function(name) {
|
|
console.warn("THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().");
|
|
return this.getObjectByName(name);
|
|
};
|
|
Object3D.prototype.renderDepth = function() {
|
|
console.warn("THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.");
|
|
};
|
|
Object3D.prototype.translate = function(distance, axis) {
|
|
console.warn("THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.");
|
|
return this.translateOnAxis(axis, distance);
|
|
};
|
|
Object3D.prototype.getWorldRotation = function() {
|
|
console.error("THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.");
|
|
};
|
|
Object3D.prototype.applyMatrix = function(matrix) {
|
|
console.warn("THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().");
|
|
return this.applyMatrix4(matrix);
|
|
};
|
|
Object.defineProperties(Object3D.prototype, {
|
|
eulerOrder: {
|
|
get: function() {
|
|
console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");
|
|
return this.rotation.order;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");
|
|
this.rotation.order = value;
|
|
}
|
|
},
|
|
useQuaternion: {
|
|
get: function() {
|
|
console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.");
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.");
|
|
}
|
|
}
|
|
});
|
|
Mesh.prototype.setDrawMode = function() {
|
|
console.error("THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.");
|
|
};
|
|
Object.defineProperties(Mesh.prototype, {
|
|
drawMode: {
|
|
get: function() {
|
|
console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.");
|
|
return TrianglesDrawMode;
|
|
},
|
|
set: function() {
|
|
console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.");
|
|
}
|
|
}
|
|
});
|
|
SkinnedMesh.prototype.initBones = function() {
|
|
console.error("THREE.SkinnedMesh: initBones() has been removed.");
|
|
};
|
|
PerspectiveCamera.prototype.setLens = function(focalLength, filmGauge) {
|
|
console.warn("THREE.PerspectiveCamera.setLens is deprecated. Use .setFocalLength and .filmGauge for a photographic setup.");
|
|
if (filmGauge !== void 0)
|
|
this.filmGauge = filmGauge;
|
|
this.setFocalLength(focalLength);
|
|
};
|
|
Object.defineProperties(Light.prototype, {
|
|
onlyShadow: {
|
|
set: function() {
|
|
console.warn("THREE.Light: .onlyShadow has been removed.");
|
|
}
|
|
},
|
|
shadowCameraFov: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraFov is now .shadow.camera.fov.");
|
|
this.shadow.camera.fov = value;
|
|
}
|
|
},
|
|
shadowCameraLeft: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraLeft is now .shadow.camera.left.");
|
|
this.shadow.camera.left = value;
|
|
}
|
|
},
|
|
shadowCameraRight: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraRight is now .shadow.camera.right.");
|
|
this.shadow.camera.right = value;
|
|
}
|
|
},
|
|
shadowCameraTop: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraTop is now .shadow.camera.top.");
|
|
this.shadow.camera.top = value;
|
|
}
|
|
},
|
|
shadowCameraBottom: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.");
|
|
this.shadow.camera.bottom = value;
|
|
}
|
|
},
|
|
shadowCameraNear: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraNear is now .shadow.camera.near.");
|
|
this.shadow.camera.near = value;
|
|
}
|
|
},
|
|
shadowCameraFar: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowCameraFar is now .shadow.camera.far.");
|
|
this.shadow.camera.far = value;
|
|
}
|
|
},
|
|
shadowCameraVisible: {
|
|
set: function() {
|
|
console.warn("THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.");
|
|
}
|
|
},
|
|
shadowBias: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowBias is now .shadow.bias.");
|
|
this.shadow.bias = value;
|
|
}
|
|
},
|
|
shadowDarkness: {
|
|
set: function() {
|
|
console.warn("THREE.Light: .shadowDarkness has been removed.");
|
|
}
|
|
},
|
|
shadowMapWidth: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.");
|
|
this.shadow.mapSize.width = value;
|
|
}
|
|
},
|
|
shadowMapHeight: {
|
|
set: function(value) {
|
|
console.warn("THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.");
|
|
this.shadow.mapSize.height = value;
|
|
}
|
|
}
|
|
});
|
|
Object.defineProperties(BufferAttribute.prototype, {
|
|
length: {
|
|
get: function() {
|
|
console.warn("THREE.BufferAttribute: .length has been deprecated. Use .count instead.");
|
|
return this.array.length;
|
|
}
|
|
},
|
|
dynamic: {
|
|
get: function() {
|
|
console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.");
|
|
return this.usage === DynamicDrawUsage;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.");
|
|
this.setUsage(DynamicDrawUsage);
|
|
}
|
|
}
|
|
});
|
|
BufferAttribute.prototype.setDynamic = function(value) {
|
|
console.warn("THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.");
|
|
this.setUsage(value === true ? DynamicDrawUsage : StaticDrawUsage);
|
|
return this;
|
|
};
|
|
BufferAttribute.prototype.copyIndicesArray = function() {
|
|
console.error("THREE.BufferAttribute: .copyIndicesArray() has been removed.");
|
|
}, BufferAttribute.prototype.setArray = function() {
|
|
console.error("THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers");
|
|
};
|
|
BufferGeometry.prototype.addIndex = function(index) {
|
|
console.warn("THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().");
|
|
this.setIndex(index);
|
|
};
|
|
BufferGeometry.prototype.addAttribute = function(name, attribute) {
|
|
console.warn("THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().");
|
|
if (!(attribute && attribute.isBufferAttribute) && !(attribute && attribute.isInterleavedBufferAttribute)) {
|
|
console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).");
|
|
return this.setAttribute(name, new BufferAttribute(arguments[1], arguments[2]));
|
|
}
|
|
if (name === "index") {
|
|
console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.");
|
|
this.setIndex(attribute);
|
|
return this;
|
|
}
|
|
return this.setAttribute(name, attribute);
|
|
};
|
|
BufferGeometry.prototype.addDrawCall = function(start, count, indexOffset) {
|
|
if (indexOffset !== void 0) {
|
|
console.warn("THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.");
|
|
}
|
|
console.warn("THREE.BufferGeometry: .addDrawCall() is now .addGroup().");
|
|
this.addGroup(start, count);
|
|
};
|
|
BufferGeometry.prototype.clearDrawCalls = function() {
|
|
console.warn("THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().");
|
|
this.clearGroups();
|
|
};
|
|
BufferGeometry.prototype.computeOffsets = function() {
|
|
console.warn("THREE.BufferGeometry: .computeOffsets() has been removed.");
|
|
};
|
|
BufferGeometry.prototype.removeAttribute = function(name) {
|
|
console.warn("THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().");
|
|
return this.deleteAttribute(name);
|
|
};
|
|
BufferGeometry.prototype.applyMatrix = function(matrix) {
|
|
console.warn("THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().");
|
|
return this.applyMatrix4(matrix);
|
|
};
|
|
Object.defineProperties(BufferGeometry.prototype, {
|
|
drawcalls: {
|
|
get: function() {
|
|
console.error("THREE.BufferGeometry: .drawcalls has been renamed to .groups.");
|
|
return this.groups;
|
|
}
|
|
},
|
|
offsets: {
|
|
get: function() {
|
|
console.warn("THREE.BufferGeometry: .offsets has been renamed to .groups.");
|
|
return this.groups;
|
|
}
|
|
}
|
|
});
|
|
InterleavedBuffer.prototype.setDynamic = function(value) {
|
|
console.warn("THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.");
|
|
this.setUsage(value === true ? DynamicDrawUsage : StaticDrawUsage);
|
|
return this;
|
|
};
|
|
InterleavedBuffer.prototype.setArray = function() {
|
|
console.error("THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers");
|
|
};
|
|
ExtrudeGeometry.prototype.getArrays = function() {
|
|
console.error("THREE.ExtrudeGeometry: .getArrays() has been removed.");
|
|
};
|
|
ExtrudeGeometry.prototype.addShapeList = function() {
|
|
console.error("THREE.ExtrudeGeometry: .addShapeList() has been removed.");
|
|
};
|
|
ExtrudeGeometry.prototype.addShape = function() {
|
|
console.error("THREE.ExtrudeGeometry: .addShape() has been removed.");
|
|
};
|
|
Scene.prototype.dispose = function() {
|
|
console.error("THREE.Scene: .dispose() has been removed.");
|
|
};
|
|
Uniform.prototype.onUpdate = function() {
|
|
console.warn("THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.");
|
|
return this;
|
|
};
|
|
Object.defineProperties(Material.prototype, {
|
|
wrapAround: {
|
|
get: function() {
|
|
console.warn("THREE.Material: .wrapAround has been removed.");
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.Material: .wrapAround has been removed.");
|
|
}
|
|
},
|
|
overdraw: {
|
|
get: function() {
|
|
console.warn("THREE.Material: .overdraw has been removed.");
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.Material: .overdraw has been removed.");
|
|
}
|
|
},
|
|
wrapRGB: {
|
|
get: function() {
|
|
console.warn("THREE.Material: .wrapRGB has been removed.");
|
|
return new Color();
|
|
}
|
|
},
|
|
shading: {
|
|
get: function() {
|
|
console.error("THREE." + this.type + ": .shading has been removed. Use the boolean .flatShading instead.");
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE." + this.type + ": .shading has been removed. Use the boolean .flatShading instead.");
|
|
this.flatShading = value === FlatShading;
|
|
}
|
|
},
|
|
stencilMask: {
|
|
get: function() {
|
|
console.warn("THREE." + this.type + ": .stencilMask has been removed. Use .stencilFuncMask instead.");
|
|
return this.stencilFuncMask;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE." + this.type + ": .stencilMask has been removed. Use .stencilFuncMask instead.");
|
|
this.stencilFuncMask = value;
|
|
}
|
|
},
|
|
vertexTangents: {
|
|
get: function() {
|
|
console.warn("THREE." + this.type + ": .vertexTangents has been removed.");
|
|
},
|
|
set: function() {
|
|
console.warn("THREE." + this.type + ": .vertexTangents has been removed.");
|
|
}
|
|
}
|
|
});
|
|
Object.defineProperties(ShaderMaterial.prototype, {
|
|
derivatives: {
|
|
get: function() {
|
|
console.warn("THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.");
|
|
return this.extensions.derivatives;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.");
|
|
this.extensions.derivatives = value;
|
|
}
|
|
}
|
|
});
|
|
WebGLRenderer.prototype.clearTarget = function(renderTarget, color, depth, stencil) {
|
|
console.warn("THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.");
|
|
this.setRenderTarget(renderTarget);
|
|
this.clear(color, depth, stencil);
|
|
};
|
|
WebGLRenderer.prototype.animate = function(callback) {
|
|
console.warn("THREE.WebGLRenderer: .animate() is now .setAnimationLoop().");
|
|
this.setAnimationLoop(callback);
|
|
};
|
|
WebGLRenderer.prototype.getCurrentRenderTarget = function() {
|
|
console.warn("THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().");
|
|
return this.getRenderTarget();
|
|
};
|
|
WebGLRenderer.prototype.getMaxAnisotropy = function() {
|
|
console.warn("THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().");
|
|
return this.capabilities.getMaxAnisotropy();
|
|
};
|
|
WebGLRenderer.prototype.getPrecision = function() {
|
|
console.warn("THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.");
|
|
return this.capabilities.precision;
|
|
};
|
|
WebGLRenderer.prototype.resetGLState = function() {
|
|
console.warn("THREE.WebGLRenderer: .resetGLState() is now .state.reset().");
|
|
return this.state.reset();
|
|
};
|
|
WebGLRenderer.prototype.supportsFloatTextures = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( 'OES_texture_float' ).");
|
|
return this.extensions.get("OES_texture_float");
|
|
};
|
|
WebGLRenderer.prototype.supportsHalfFloatTextures = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( 'OES_texture_half_float' ).");
|
|
return this.extensions.get("OES_texture_half_float");
|
|
};
|
|
WebGLRenderer.prototype.supportsStandardDerivatives = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( 'OES_standard_derivatives' ).");
|
|
return this.extensions.get("OES_standard_derivatives");
|
|
};
|
|
WebGLRenderer.prototype.supportsCompressedTextureS3TC = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( 'WEBGL_compressed_texture_s3tc' ).");
|
|
return this.extensions.get("WEBGL_compressed_texture_s3tc");
|
|
};
|
|
WebGLRenderer.prototype.supportsCompressedTexturePVRTC = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( 'WEBGL_compressed_texture_pvrtc' ).");
|
|
return this.extensions.get("WEBGL_compressed_texture_pvrtc");
|
|
};
|
|
WebGLRenderer.prototype.supportsBlendMinMax = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( 'EXT_blend_minmax' ).");
|
|
return this.extensions.get("EXT_blend_minmax");
|
|
};
|
|
WebGLRenderer.prototype.supportsVertexTextures = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.");
|
|
return this.capabilities.vertexTextures;
|
|
};
|
|
WebGLRenderer.prototype.supportsInstancedArrays = function() {
|
|
console.warn("THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( 'ANGLE_instanced_arrays' ).");
|
|
return this.extensions.get("ANGLE_instanced_arrays");
|
|
};
|
|
WebGLRenderer.prototype.enableScissorTest = function(boolean) {
|
|
console.warn("THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().");
|
|
this.setScissorTest(boolean);
|
|
};
|
|
WebGLRenderer.prototype.initMaterial = function() {
|
|
console.warn("THREE.WebGLRenderer: .initMaterial() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.addPrePlugin = function() {
|
|
console.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.addPostPlugin = function() {
|
|
console.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.updateShadowMap = function() {
|
|
console.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.setFaceCulling = function() {
|
|
console.warn("THREE.WebGLRenderer: .setFaceCulling() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.allocTextureUnit = function() {
|
|
console.warn("THREE.WebGLRenderer: .allocTextureUnit() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.setTexture = function() {
|
|
console.warn("THREE.WebGLRenderer: .setTexture() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.setTexture2D = function() {
|
|
console.warn("THREE.WebGLRenderer: .setTexture2D() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.setTextureCube = function() {
|
|
console.warn("THREE.WebGLRenderer: .setTextureCube() has been removed.");
|
|
};
|
|
WebGLRenderer.prototype.getActiveMipMapLevel = function() {
|
|
console.warn("THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().");
|
|
return this.getActiveMipmapLevel();
|
|
};
|
|
Object.defineProperties(WebGLRenderer.prototype, {
|
|
shadowMapEnabled: {
|
|
get: function() {
|
|
return this.shadowMap.enabled;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.");
|
|
this.shadowMap.enabled = value;
|
|
}
|
|
},
|
|
shadowMapType: {
|
|
get: function() {
|
|
return this.shadowMap.type;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.");
|
|
this.shadowMap.type = value;
|
|
}
|
|
},
|
|
shadowMapCullFace: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.");
|
|
return void 0;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.");
|
|
}
|
|
},
|
|
context: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.");
|
|
return this.getContext();
|
|
}
|
|
},
|
|
vr: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .vr has been renamed to .xr");
|
|
return this.xr;
|
|
}
|
|
},
|
|
gammaInput: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.");
|
|
return false;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.");
|
|
}
|
|
},
|
|
gammaOutput: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.");
|
|
return false;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.");
|
|
this.outputEncoding = value === true ? sRGBEncoding : LinearEncoding;
|
|
}
|
|
},
|
|
toneMappingWhitePoint: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.");
|
|
return 1;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.");
|
|
}
|
|
}
|
|
});
|
|
Object.defineProperties(WebGLShadowMap.prototype, {
|
|
cullFace: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.");
|
|
return void 0;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.");
|
|
}
|
|
},
|
|
renderReverseSided: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.");
|
|
return void 0;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.");
|
|
}
|
|
},
|
|
renderSingleSided: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.");
|
|
return void 0;
|
|
},
|
|
set: function() {
|
|
console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.");
|
|
}
|
|
}
|
|
});
|
|
Object.defineProperties(WebGLRenderTarget.prototype, {
|
|
wrapS: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.");
|
|
return this.texture.wrapS;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.");
|
|
this.texture.wrapS = value;
|
|
}
|
|
},
|
|
wrapT: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.");
|
|
return this.texture.wrapT;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.");
|
|
this.texture.wrapT = value;
|
|
}
|
|
},
|
|
magFilter: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.");
|
|
return this.texture.magFilter;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.");
|
|
this.texture.magFilter = value;
|
|
}
|
|
},
|
|
minFilter: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.");
|
|
return this.texture.minFilter;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.");
|
|
this.texture.minFilter = value;
|
|
}
|
|
},
|
|
anisotropy: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.");
|
|
return this.texture.anisotropy;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.");
|
|
this.texture.anisotropy = value;
|
|
}
|
|
},
|
|
offset: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset.");
|
|
return this.texture.offset;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset.");
|
|
this.texture.offset = value;
|
|
}
|
|
},
|
|
repeat: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat.");
|
|
return this.texture.repeat;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat.");
|
|
this.texture.repeat = value;
|
|
}
|
|
},
|
|
format: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .format is now .texture.format.");
|
|
return this.texture.format;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .format is now .texture.format.");
|
|
this.texture.format = value;
|
|
}
|
|
},
|
|
type: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .type is now .texture.type.");
|
|
return this.texture.type;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .type is now .texture.type.");
|
|
this.texture.type = value;
|
|
}
|
|
},
|
|
generateMipmaps: {
|
|
get: function() {
|
|
console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.");
|
|
return this.texture.generateMipmaps;
|
|
},
|
|
set: function(value) {
|
|
console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.");
|
|
this.texture.generateMipmaps = value;
|
|
}
|
|
}
|
|
});
|
|
Audio.prototype.load = function(file) {
|
|
console.warn("THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.");
|
|
const scope = this;
|
|
const audioLoader = new AudioLoader();
|
|
audioLoader.load(file, function(buffer) {
|
|
scope.setBuffer(buffer);
|
|
});
|
|
return this;
|
|
};
|
|
AudioAnalyser.prototype.getData = function() {
|
|
console.warn("THREE.AudioAnalyser: .getData() is now .getFrequencyData().");
|
|
return this.getFrequencyData();
|
|
};
|
|
CubeCamera.prototype.updateCubeMap = function(renderer, scene) {
|
|
console.warn("THREE.CubeCamera: .updateCubeMap() is now .update().");
|
|
return this.update(renderer, scene);
|
|
};
|
|
CubeCamera.prototype.clear = function(renderer, color, depth, stencil) {
|
|
console.warn("THREE.CubeCamera: .clear() is now .renderTarget.clear().");
|
|
return this.renderTarget.clear(renderer, color, depth, stencil);
|
|
};
|
|
ImageUtils.crossOrigin = void 0;
|
|
ImageUtils.loadTexture = function(url, mapping, onLoad, onError) {
|
|
console.warn("THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.");
|
|
const loader = new TextureLoader();
|
|
loader.setCrossOrigin(this.crossOrigin);
|
|
const texture = loader.load(url, onLoad, void 0, onError);
|
|
if (mapping)
|
|
texture.mapping = mapping;
|
|
return texture;
|
|
};
|
|
ImageUtils.loadTextureCube = function(urls, mapping, onLoad, onError) {
|
|
console.warn("THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.");
|
|
const loader = new CubeTextureLoader();
|
|
loader.setCrossOrigin(this.crossOrigin);
|
|
const texture = loader.load(urls, onLoad, void 0, onError);
|
|
if (mapping)
|
|
texture.mapping = mapping;
|
|
return texture;
|
|
};
|
|
ImageUtils.loadCompressedTexture = function() {
|
|
console.error("THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.");
|
|
};
|
|
ImageUtils.loadCompressedTextureCube = function() {
|
|
console.error("THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.");
|
|
};
|
|
if (typeof __THREE_DEVTOOLS__ !== "undefined") {
|
|
__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { detail: {
|
|
revision: REVISION
|
|
} }));
|
|
}
|
|
if (typeof window !== "undefined") {
|
|
if (window.__THREE__) {
|
|
console.warn("WARNING: Multiple instances of Three.js being imported.");
|
|
} else {
|
|
window.__THREE__ = REVISION;
|
|
}
|
|
}
|
|
|
|
// node_modules/cannon-es/dist/cannon-es.js
|
|
var Mat3 = class {
|
|
constructor(elements = [0, 0, 0, 0, 0, 0, 0, 0, 0]) {
|
|
this.elements = void 0;
|
|
this.elements = elements;
|
|
}
|
|
identity() {
|
|
const e = this.elements;
|
|
e[0] = 1;
|
|
e[1] = 0;
|
|
e[2] = 0;
|
|
e[3] = 0;
|
|
e[4] = 1;
|
|
e[5] = 0;
|
|
e[6] = 0;
|
|
e[7] = 0;
|
|
e[8] = 1;
|
|
}
|
|
setZero() {
|
|
const e = this.elements;
|
|
e[0] = 0;
|
|
e[1] = 0;
|
|
e[2] = 0;
|
|
e[3] = 0;
|
|
e[4] = 0;
|
|
e[5] = 0;
|
|
e[6] = 0;
|
|
e[7] = 0;
|
|
e[8] = 0;
|
|
}
|
|
setTrace(vector) {
|
|
const e = this.elements;
|
|
e[0] = vector.x;
|
|
e[4] = vector.y;
|
|
e[8] = vector.z;
|
|
}
|
|
getTrace(target = new Vec3()) {
|
|
const e = this.elements;
|
|
target.x = e[0];
|
|
target.y = e[4];
|
|
target.z = e[8];
|
|
return target;
|
|
}
|
|
vmult(v, target = new Vec3()) {
|
|
const e = this.elements;
|
|
const x = v.x;
|
|
const y = v.y;
|
|
const z = v.z;
|
|
target.x = e[0] * x + e[1] * y + e[2] * z;
|
|
target.y = e[3] * x + e[4] * y + e[5] * z;
|
|
target.z = e[6] * x + e[7] * y + e[8] * z;
|
|
return target;
|
|
}
|
|
smult(s) {
|
|
for (let i = 0; i < this.elements.length; i++) {
|
|
this.elements[i] *= s;
|
|
}
|
|
}
|
|
mmult(matrix, target = new Mat3()) {
|
|
const A = this.elements;
|
|
const B = matrix.elements;
|
|
const T = target.elements;
|
|
const a11 = A[0], a12 = A[1], a13 = A[2], a21 = A[3], a22 = A[4], a23 = A[5], a31 = A[6], a32 = A[7], a33 = A[8];
|
|
const b11 = B[0], b12 = B[1], b13 = B[2], b21 = B[3], b22 = B[4], b23 = B[5], b31 = B[6], b32 = B[7], b33 = B[8];
|
|
T[0] = a11 * b11 + a12 * b21 + a13 * b31;
|
|
T[1] = a11 * b12 + a12 * b22 + a13 * b32;
|
|
T[2] = a11 * b13 + a12 * b23 + a13 * b33;
|
|
T[3] = a21 * b11 + a22 * b21 + a23 * b31;
|
|
T[4] = a21 * b12 + a22 * b22 + a23 * b32;
|
|
T[5] = a21 * b13 + a22 * b23 + a23 * b33;
|
|
T[6] = a31 * b11 + a32 * b21 + a33 * b31;
|
|
T[7] = a31 * b12 + a32 * b22 + a33 * b32;
|
|
T[8] = a31 * b13 + a32 * b23 + a33 * b33;
|
|
return target;
|
|
}
|
|
scale(vector, target = new Mat3()) {
|
|
const e = this.elements;
|
|
const t = target.elements;
|
|
for (let i = 0; i !== 3; i++) {
|
|
t[3 * i + 0] = vector.x * e[3 * i + 0];
|
|
t[3 * i + 1] = vector.y * e[3 * i + 1];
|
|
t[3 * i + 2] = vector.z * e[3 * i + 2];
|
|
}
|
|
return target;
|
|
}
|
|
solve(b2, target = new Vec3()) {
|
|
const nr = 3;
|
|
const nc = 4;
|
|
const eqns = [];
|
|
let i;
|
|
let j;
|
|
for (i = 0; i < nr * nc; i++) {
|
|
eqns.push(0);
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 0; j < 3; j++) {
|
|
eqns[i + nc * j] = this.elements[i + 3 * j];
|
|
}
|
|
}
|
|
eqns[3 + 4 * 0] = b2.x;
|
|
eqns[3 + 4 * 1] = b2.y;
|
|
eqns[3 + 4 * 2] = b2.z;
|
|
let n = 3;
|
|
const k = n;
|
|
let np;
|
|
const kp = 4;
|
|
let p2;
|
|
do {
|
|
i = k - n;
|
|
if (eqns[i + nc * i] === 0) {
|
|
for (j = i + 1; j < k; j++) {
|
|
if (eqns[i + nc * j] !== 0) {
|
|
np = kp;
|
|
do {
|
|
p2 = kp - np;
|
|
eqns[p2 + nc * i] += eqns[p2 + nc * j];
|
|
} while (--np);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (eqns[i + nc * i] !== 0) {
|
|
for (j = i + 1; j < k; j++) {
|
|
const multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = kp;
|
|
do {
|
|
p2 = kp - np;
|
|
eqns[p2 + nc * j] = p2 <= i ? 0 : eqns[p2 + nc * j] - eqns[p2 + nc * i] * multiplier;
|
|
} while (--np);
|
|
}
|
|
}
|
|
} while (--n);
|
|
target.z = eqns[2 * nc + 3] / eqns[2 * nc + 2];
|
|
target.y = (eqns[1 * nc + 3] - eqns[1 * nc + 2] * target.z) / eqns[1 * nc + 1];
|
|
target.x = (eqns[0 * nc + 3] - eqns[0 * nc + 2] * target.z - eqns[0 * nc + 1] * target.y) / eqns[0 * nc + 0];
|
|
if (isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || target.x === Infinity || target.y === Infinity || target.z === Infinity) {
|
|
throw "Could not solve equation! Got x=[" + target.toString() + "], b=[" + b2.toString() + "], A=[" + this.toString() + "]";
|
|
}
|
|
return target;
|
|
}
|
|
e(row, column, value) {
|
|
if (value === void 0) {
|
|
return this.elements[column + 3 * row];
|
|
} else {
|
|
this.elements[column + 3 * row] = value;
|
|
}
|
|
}
|
|
copy(matrix) {
|
|
for (let i = 0; i < matrix.elements.length; i++) {
|
|
this.elements[i] = matrix.elements[i];
|
|
}
|
|
return this;
|
|
}
|
|
toString() {
|
|
let r = "";
|
|
const sep = ",";
|
|
for (let i = 0; i < 9; i++) {
|
|
r += this.elements[i] + sep;
|
|
}
|
|
return r;
|
|
}
|
|
reverse(target = new Mat3()) {
|
|
const nr = 3;
|
|
const nc = 6;
|
|
const eqns = reverse_eqns;
|
|
let i;
|
|
let j;
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 0; j < 3; j++) {
|
|
eqns[i + nc * j] = this.elements[i + 3 * j];
|
|
}
|
|
}
|
|
eqns[3 + 6 * 0] = 1;
|
|
eqns[3 + 6 * 1] = 0;
|
|
eqns[3 + 6 * 2] = 0;
|
|
eqns[4 + 6 * 0] = 0;
|
|
eqns[4 + 6 * 1] = 1;
|
|
eqns[4 + 6 * 2] = 0;
|
|
eqns[5 + 6 * 0] = 0;
|
|
eqns[5 + 6 * 1] = 0;
|
|
eqns[5 + 6 * 2] = 1;
|
|
let n = 3;
|
|
const k = n;
|
|
let np;
|
|
const kp = nc;
|
|
let p2;
|
|
do {
|
|
i = k - n;
|
|
if (eqns[i + nc * i] === 0) {
|
|
for (j = i + 1; j < k; j++) {
|
|
if (eqns[i + nc * j] !== 0) {
|
|
np = kp;
|
|
do {
|
|
p2 = kp - np;
|
|
eqns[p2 + nc * i] += eqns[p2 + nc * j];
|
|
} while (--np);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (eqns[i + nc * i] !== 0) {
|
|
for (j = i + 1; j < k; j++) {
|
|
const multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = kp;
|
|
do {
|
|
p2 = kp - np;
|
|
eqns[p2 + nc * j] = p2 <= i ? 0 : eqns[p2 + nc * j] - eqns[p2 + nc * i] * multiplier;
|
|
} while (--np);
|
|
}
|
|
}
|
|
} while (--n);
|
|
i = 2;
|
|
do {
|
|
j = i - 1;
|
|
do {
|
|
const multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = nc;
|
|
do {
|
|
p2 = nc - np;
|
|
eqns[p2 + nc * j] = eqns[p2 + nc * j] - eqns[p2 + nc * i] * multiplier;
|
|
} while (--np);
|
|
} while (j--);
|
|
} while (--i);
|
|
i = 2;
|
|
do {
|
|
const multiplier = 1 / eqns[i + nc * i];
|
|
np = nc;
|
|
do {
|
|
p2 = nc - np;
|
|
eqns[p2 + nc * i] = eqns[p2 + nc * i] * multiplier;
|
|
} while (--np);
|
|
} while (i--);
|
|
i = 2;
|
|
do {
|
|
j = 2;
|
|
do {
|
|
p2 = eqns[nr + j + nc * i];
|
|
if (isNaN(p2) || p2 === Infinity) {
|
|
throw "Could not reverse! A=[" + this.toString() + "]";
|
|
}
|
|
target.e(i, j, p2);
|
|
} while (j--);
|
|
} while (i--);
|
|
return target;
|
|
}
|
|
setRotationFromQuaternion(q) {
|
|
const x = q.x;
|
|
const y = q.y;
|
|
const z = q.z;
|
|
const w2 = q.w;
|
|
const x2 = x + x;
|
|
const y2 = y + y;
|
|
const z2 = z + z;
|
|
const xx = x * x2;
|
|
const xy = x * y2;
|
|
const xz = x * z2;
|
|
const yy = y * y2;
|
|
const yz = y * z2;
|
|
const zz = z * z2;
|
|
const wx = w2 * x2;
|
|
const wy = w2 * y2;
|
|
const wz = w2 * z2;
|
|
const e = this.elements;
|
|
e[3 * 0 + 0] = 1 - (yy + zz);
|
|
e[3 * 0 + 1] = xy - wz;
|
|
e[3 * 0 + 2] = xz + wy;
|
|
e[3 * 1 + 0] = xy + wz;
|
|
e[3 * 1 + 1] = 1 - (xx + zz);
|
|
e[3 * 1 + 2] = yz - wx;
|
|
e[3 * 2 + 0] = xz - wy;
|
|
e[3 * 2 + 1] = yz + wx;
|
|
e[3 * 2 + 2] = 1 - (xx + yy);
|
|
return this;
|
|
}
|
|
transpose(target = new Mat3()) {
|
|
const M = this.elements;
|
|
const T = target.elements;
|
|
let tmp3;
|
|
T[0] = M[0];
|
|
T[4] = M[4];
|
|
T[8] = M[8];
|
|
tmp3 = M[1];
|
|
T[1] = M[3];
|
|
T[3] = tmp3;
|
|
tmp3 = M[2];
|
|
T[2] = M[6];
|
|
T[6] = tmp3;
|
|
tmp3 = M[5];
|
|
T[5] = M[7];
|
|
T[7] = tmp3;
|
|
return target;
|
|
}
|
|
};
|
|
var reverse_eqns = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
var Vec3 = class {
|
|
constructor(x = 0, y = 0, z = 0) {
|
|
this.x = void 0;
|
|
this.y = void 0;
|
|
this.z = void 0;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
cross(vector, target = new Vec3()) {
|
|
const vx = vector.x;
|
|
const vy = vector.y;
|
|
const vz = vector.z;
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
target.x = y * vz - z * vy;
|
|
target.y = z * vx - x * vz;
|
|
target.z = x * vy - y * vx;
|
|
return target;
|
|
}
|
|
set(x, y, z) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
return this;
|
|
}
|
|
setZero() {
|
|
this.x = this.y = this.z = 0;
|
|
}
|
|
vadd(vector, target) {
|
|
if (target) {
|
|
target.x = vector.x + this.x;
|
|
target.y = vector.y + this.y;
|
|
target.z = vector.z + this.z;
|
|
} else {
|
|
return new Vec3(this.x + vector.x, this.y + vector.y, this.z + vector.z);
|
|
}
|
|
}
|
|
vsub(vector, target) {
|
|
if (target) {
|
|
target.x = this.x - vector.x;
|
|
target.y = this.y - vector.y;
|
|
target.z = this.z - vector.z;
|
|
} else {
|
|
return new Vec3(this.x - vector.x, this.y - vector.y, this.z - vector.z);
|
|
}
|
|
}
|
|
crossmat() {
|
|
return new Mat3([0, -this.z, this.y, this.z, 0, -this.x, -this.y, this.x, 0]);
|
|
}
|
|
normalize() {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
const n = Math.sqrt(x * x + y * y + z * z);
|
|
if (n > 0) {
|
|
const invN = 1 / n;
|
|
this.x *= invN;
|
|
this.y *= invN;
|
|
this.z *= invN;
|
|
} else {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
}
|
|
return n;
|
|
}
|
|
unit(target = new Vec3()) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
let ninv = Math.sqrt(x * x + y * y + z * z);
|
|
if (ninv > 0) {
|
|
ninv = 1 / ninv;
|
|
target.x = x * ninv;
|
|
target.y = y * ninv;
|
|
target.z = z * ninv;
|
|
} else {
|
|
target.x = 1;
|
|
target.y = 0;
|
|
target.z = 0;
|
|
}
|
|
return target;
|
|
}
|
|
length() {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
return Math.sqrt(x * x + y * y + z * z);
|
|
}
|
|
lengthSquared() {
|
|
return this.dot(this);
|
|
}
|
|
distanceTo(p2) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
const px2 = p2.x;
|
|
const py2 = p2.y;
|
|
const pz2 = p2.z;
|
|
return Math.sqrt((px2 - x) * (px2 - x) + (py2 - y) * (py2 - y) + (pz2 - z) * (pz2 - z));
|
|
}
|
|
distanceSquared(p2) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
const px2 = p2.x;
|
|
const py2 = p2.y;
|
|
const pz2 = p2.z;
|
|
return (px2 - x) * (px2 - x) + (py2 - y) * (py2 - y) + (pz2 - z) * (pz2 - z);
|
|
}
|
|
scale(scalar, target = new Vec3()) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
target.x = scalar * x;
|
|
target.y = scalar * y;
|
|
target.z = scalar * z;
|
|
return target;
|
|
}
|
|
vmul(vector, target = new Vec3()) {
|
|
target.x = vector.x * this.x;
|
|
target.y = vector.y * this.y;
|
|
target.z = vector.z * this.z;
|
|
return target;
|
|
}
|
|
addScaledVector(scalar, vector, target = new Vec3()) {
|
|
target.x = this.x + scalar * vector.x;
|
|
target.y = this.y + scalar * vector.y;
|
|
target.z = this.z + scalar * vector.z;
|
|
return target;
|
|
}
|
|
dot(vector) {
|
|
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
|
|
}
|
|
isZero() {
|
|
return this.x === 0 && this.y === 0 && this.z === 0;
|
|
}
|
|
negate(target = new Vec3()) {
|
|
target.x = -this.x;
|
|
target.y = -this.y;
|
|
target.z = -this.z;
|
|
return target;
|
|
}
|
|
tangents(t1, t2) {
|
|
const norm = this.length();
|
|
if (norm > 0) {
|
|
const n = Vec3_tangents_n;
|
|
const inorm = 1 / norm;
|
|
n.set(this.x * inorm, this.y * inorm, this.z * inorm);
|
|
const randVec = Vec3_tangents_randVec;
|
|
if (Math.abs(n.x) < 0.9) {
|
|
randVec.set(1, 0, 0);
|
|
n.cross(randVec, t1);
|
|
} else {
|
|
randVec.set(0, 1, 0);
|
|
n.cross(randVec, t1);
|
|
}
|
|
n.cross(t1, t2);
|
|
} else {
|
|
t1.set(1, 0, 0);
|
|
t2.set(0, 1, 0);
|
|
}
|
|
}
|
|
toString() {
|
|
return this.x + "," + this.y + "," + this.z;
|
|
}
|
|
toArray() {
|
|
return [this.x, this.y, this.z];
|
|
}
|
|
copy(vector) {
|
|
this.x = vector.x;
|
|
this.y = vector.y;
|
|
this.z = vector.z;
|
|
return this;
|
|
}
|
|
lerp(vector, t, target) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
target.x = x + (vector.x - x) * t;
|
|
target.y = y + (vector.y - y) * t;
|
|
target.z = z + (vector.z - z) * t;
|
|
}
|
|
almostEquals(vector, precision = 1e-6) {
|
|
if (Math.abs(this.x - vector.x) > precision || Math.abs(this.y - vector.y) > precision || Math.abs(this.z - vector.z) > precision) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
almostZero(precision = 1e-6) {
|
|
if (Math.abs(this.x) > precision || Math.abs(this.y) > precision || Math.abs(this.z) > precision) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
isAntiparallelTo(vector, precision) {
|
|
this.negate(antip_neg);
|
|
return antip_neg.almostEquals(vector, precision);
|
|
}
|
|
clone() {
|
|
return new Vec3(this.x, this.y, this.z);
|
|
}
|
|
};
|
|
Vec3.ZERO = void 0;
|
|
Vec3.UNIT_X = void 0;
|
|
Vec3.UNIT_Y = void 0;
|
|
Vec3.UNIT_Z = void 0;
|
|
Vec3.ZERO = new Vec3(0, 0, 0);
|
|
Vec3.UNIT_X = new Vec3(1, 0, 0);
|
|
Vec3.UNIT_Y = new Vec3(0, 1, 0);
|
|
Vec3.UNIT_Z = new Vec3(0, 0, 1);
|
|
var Vec3_tangents_n = new Vec3();
|
|
var Vec3_tangents_randVec = new Vec3();
|
|
var antip_neg = new Vec3();
|
|
var AABB = class {
|
|
constructor(options = {}) {
|
|
this.lowerBound = void 0;
|
|
this.upperBound = void 0;
|
|
this.lowerBound = new Vec3();
|
|
this.upperBound = new Vec3();
|
|
if (options.lowerBound) {
|
|
this.lowerBound.copy(options.lowerBound);
|
|
}
|
|
if (options.upperBound) {
|
|
this.upperBound.copy(options.upperBound);
|
|
}
|
|
}
|
|
setFromPoints(points, position, quaternion, skinSize) {
|
|
const l = this.lowerBound;
|
|
const u = this.upperBound;
|
|
const q = quaternion;
|
|
l.copy(points[0]);
|
|
if (q) {
|
|
q.vmult(l, l);
|
|
}
|
|
u.copy(l);
|
|
for (let i = 1; i < points.length; i++) {
|
|
let p2 = points[i];
|
|
if (q) {
|
|
q.vmult(p2, tmp$1);
|
|
p2 = tmp$1;
|
|
}
|
|
if (p2.x > u.x) {
|
|
u.x = p2.x;
|
|
}
|
|
if (p2.x < l.x) {
|
|
l.x = p2.x;
|
|
}
|
|
if (p2.y > u.y) {
|
|
u.y = p2.y;
|
|
}
|
|
if (p2.y < l.y) {
|
|
l.y = p2.y;
|
|
}
|
|
if (p2.z > u.z) {
|
|
u.z = p2.z;
|
|
}
|
|
if (p2.z < l.z) {
|
|
l.z = p2.z;
|
|
}
|
|
}
|
|
if (position) {
|
|
position.vadd(l, l);
|
|
position.vadd(u, u);
|
|
}
|
|
if (skinSize) {
|
|
l.x -= skinSize;
|
|
l.y -= skinSize;
|
|
l.z -= skinSize;
|
|
u.x += skinSize;
|
|
u.y += skinSize;
|
|
u.z += skinSize;
|
|
}
|
|
return this;
|
|
}
|
|
copy(aabb) {
|
|
this.lowerBound.copy(aabb.lowerBound);
|
|
this.upperBound.copy(aabb.upperBound);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new AABB().copy(this);
|
|
}
|
|
extend(aabb) {
|
|
this.lowerBound.x = Math.min(this.lowerBound.x, aabb.lowerBound.x);
|
|
this.upperBound.x = Math.max(this.upperBound.x, aabb.upperBound.x);
|
|
this.lowerBound.y = Math.min(this.lowerBound.y, aabb.lowerBound.y);
|
|
this.upperBound.y = Math.max(this.upperBound.y, aabb.upperBound.y);
|
|
this.lowerBound.z = Math.min(this.lowerBound.z, aabb.lowerBound.z);
|
|
this.upperBound.z = Math.max(this.upperBound.z, aabb.upperBound.z);
|
|
}
|
|
overlaps(aabb) {
|
|
const l1 = this.lowerBound;
|
|
const u1 = this.upperBound;
|
|
const l2 = aabb.lowerBound;
|
|
const u2 = aabb.upperBound;
|
|
const overlapsX = l2.x <= u1.x && u1.x <= u2.x || l1.x <= u2.x && u2.x <= u1.x;
|
|
const overlapsY = l2.y <= u1.y && u1.y <= u2.y || l1.y <= u2.y && u2.y <= u1.y;
|
|
const overlapsZ = l2.z <= u1.z && u1.z <= u2.z || l1.z <= u2.z && u2.z <= u1.z;
|
|
return overlapsX && overlapsY && overlapsZ;
|
|
}
|
|
volume() {
|
|
const l = this.lowerBound;
|
|
const u = this.upperBound;
|
|
return (u.x - l.x) * (u.y - l.y) * (u.z - l.z);
|
|
}
|
|
contains(aabb) {
|
|
const l1 = this.lowerBound;
|
|
const u1 = this.upperBound;
|
|
const l2 = aabb.lowerBound;
|
|
const u2 = aabb.upperBound;
|
|
return l1.x <= l2.x && u1.x >= u2.x && l1.y <= l2.y && u1.y >= u2.y && l1.z <= l2.z && u1.z >= u2.z;
|
|
}
|
|
getCorners(a2, b2, c2, d, e, f, g, h) {
|
|
const l = this.lowerBound;
|
|
const u = this.upperBound;
|
|
a2.copy(l);
|
|
b2.set(u.x, l.y, l.z);
|
|
c2.set(u.x, u.y, l.z);
|
|
d.set(l.x, u.y, u.z);
|
|
e.set(u.x, l.y, u.z);
|
|
f.set(l.x, u.y, l.z);
|
|
g.set(l.x, l.y, u.z);
|
|
h.copy(u);
|
|
}
|
|
toLocalFrame(frame, target) {
|
|
const corners = transformIntoFrame_corners;
|
|
const a2 = corners[0];
|
|
const b2 = corners[1];
|
|
const c2 = corners[2];
|
|
const d = corners[3];
|
|
const e = corners[4];
|
|
const f = corners[5];
|
|
const g = corners[6];
|
|
const h = corners[7];
|
|
this.getCorners(a2, b2, c2, d, e, f, g, h);
|
|
for (let i = 0; i !== 8; i++) {
|
|
const corner = corners[i];
|
|
frame.pointToLocal(corner, corner);
|
|
}
|
|
return target.setFromPoints(corners);
|
|
}
|
|
toWorldFrame(frame, target) {
|
|
const corners = transformIntoFrame_corners;
|
|
const a2 = corners[0];
|
|
const b2 = corners[1];
|
|
const c2 = corners[2];
|
|
const d = corners[3];
|
|
const e = corners[4];
|
|
const f = corners[5];
|
|
const g = corners[6];
|
|
const h = corners[7];
|
|
this.getCorners(a2, b2, c2, d, e, f, g, h);
|
|
for (let i = 0; i !== 8; i++) {
|
|
const corner = corners[i];
|
|
frame.pointToWorld(corner, corner);
|
|
}
|
|
return target.setFromPoints(corners);
|
|
}
|
|
overlapsRay(ray) {
|
|
const {
|
|
direction,
|
|
from
|
|
} = ray;
|
|
const dirFracX = 1 / direction.x;
|
|
const dirFracY = 1 / direction.y;
|
|
const dirFracZ = 1 / direction.z;
|
|
const t1 = (this.lowerBound.x - from.x) * dirFracX;
|
|
const t2 = (this.upperBound.x - from.x) * dirFracX;
|
|
const t3 = (this.lowerBound.y - from.y) * dirFracY;
|
|
const t4 = (this.upperBound.y - from.y) * dirFracY;
|
|
const t5 = (this.lowerBound.z - from.z) * dirFracZ;
|
|
const t6 = (this.upperBound.z - from.z) * dirFracZ;
|
|
const tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6));
|
|
const tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6));
|
|
if (tmax < 0) {
|
|
return false;
|
|
}
|
|
if (tmin > tmax) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
var tmp$1 = new Vec3();
|
|
var transformIntoFrame_corners = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
|
|
var ArrayCollisionMatrix = class {
|
|
constructor() {
|
|
this.matrix = void 0;
|
|
this.matrix = [];
|
|
}
|
|
get(bi, bj) {
|
|
let {
|
|
index: i
|
|
} = bi;
|
|
let {
|
|
index: j
|
|
} = bj;
|
|
if (j > i) {
|
|
const temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return this.matrix[(i * (i + 1) >> 1) + j - 1];
|
|
}
|
|
set(bi, bj, value) {
|
|
let {
|
|
index: i
|
|
} = bi;
|
|
let {
|
|
index: j
|
|
} = bj;
|
|
if (j > i) {
|
|
const temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
this.matrix[(i * (i + 1) >> 1) + j - 1] = value ? 1 : 0;
|
|
}
|
|
reset() {
|
|
for (let i = 0, l = this.matrix.length; i !== l; i++) {
|
|
this.matrix[i] = 0;
|
|
}
|
|
}
|
|
setNumObjects(n) {
|
|
this.matrix.length = n * (n - 1) >> 1;
|
|
}
|
|
};
|
|
var EventTarget = class {
|
|
constructor() {
|
|
this._listeners = void 0;
|
|
}
|
|
addEventListener(type, listener3) {
|
|
if (this._listeners === void 0) {
|
|
this._listeners = {};
|
|
}
|
|
const listeners = this._listeners;
|
|
if (listeners[type] === void 0) {
|
|
listeners[type] = [];
|
|
}
|
|
if (!listeners[type].includes(listener3)) {
|
|
listeners[type].push(listener3);
|
|
}
|
|
return this;
|
|
}
|
|
hasEventListener(type, listener3) {
|
|
if (this._listeners === void 0) {
|
|
return false;
|
|
}
|
|
const listeners = this._listeners;
|
|
if (listeners[type] !== void 0 && listeners[type].includes(listener3)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
hasAnyEventListener(type) {
|
|
if (this._listeners === void 0) {
|
|
return false;
|
|
}
|
|
const listeners = this._listeners;
|
|
return listeners[type] !== void 0;
|
|
}
|
|
removeEventListener(type, listener3) {
|
|
if (this._listeners === void 0) {
|
|
return this;
|
|
}
|
|
const listeners = this._listeners;
|
|
if (listeners[type] === void 0) {
|
|
return this;
|
|
}
|
|
const index = listeners[type].indexOf(listener3);
|
|
if (index !== -1) {
|
|
listeners[type].splice(index, 1);
|
|
}
|
|
return this;
|
|
}
|
|
dispatchEvent(event) {
|
|
if (this._listeners === void 0) {
|
|
return this;
|
|
}
|
|
const listeners = this._listeners;
|
|
const listenerArray = listeners[event.type];
|
|
if (listenerArray !== void 0) {
|
|
event.target = this;
|
|
for (let i = 0, l = listenerArray.length; i < l; i++) {
|
|
listenerArray[i].call(this, event);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var Quaternion2 = class {
|
|
constructor(x = 0, y = 0, z = 0, w2 = 1) {
|
|
this.x = void 0;
|
|
this.y = void 0;
|
|
this.z = void 0;
|
|
this.w = void 0;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w2;
|
|
}
|
|
set(x, y, z, w2) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w2;
|
|
return this;
|
|
}
|
|
toString() {
|
|
return this.x + "," + this.y + "," + this.z + "," + this.w;
|
|
}
|
|
toArray() {
|
|
return [this.x, this.y, this.z, this.w];
|
|
}
|
|
setFromAxisAngle(vector, angle) {
|
|
const s = Math.sin(angle * 0.5);
|
|
this.x = vector.x * s;
|
|
this.y = vector.y * s;
|
|
this.z = vector.z * s;
|
|
this.w = Math.cos(angle * 0.5);
|
|
return this;
|
|
}
|
|
toAxisAngle(targetAxis = new Vec3()) {
|
|
this.normalize();
|
|
const angle = 2 * Math.acos(this.w);
|
|
const s = Math.sqrt(1 - this.w * this.w);
|
|
if (s < 1e-3) {
|
|
targetAxis.x = this.x;
|
|
targetAxis.y = this.y;
|
|
targetAxis.z = this.z;
|
|
} else {
|
|
targetAxis.x = this.x / s;
|
|
targetAxis.y = this.y / s;
|
|
targetAxis.z = this.z / s;
|
|
}
|
|
return [targetAxis, angle];
|
|
}
|
|
setFromVectors(u, v) {
|
|
if (u.isAntiparallelTo(v)) {
|
|
const t1 = sfv_t1;
|
|
const t2 = sfv_t2;
|
|
u.tangents(t1, t2);
|
|
this.setFromAxisAngle(t1, Math.PI);
|
|
} else {
|
|
const a2 = u.cross(v);
|
|
this.x = a2.x;
|
|
this.y = a2.y;
|
|
this.z = a2.z;
|
|
this.w = Math.sqrt(u.length() ** 2 * v.length() ** 2) + u.dot(v);
|
|
this.normalize();
|
|
}
|
|
return this;
|
|
}
|
|
mult(quat, target = new Quaternion2()) {
|
|
const ax = this.x;
|
|
const ay = this.y;
|
|
const az = this.z;
|
|
const aw = this.w;
|
|
const bx = quat.x;
|
|
const by = quat.y;
|
|
const bz = quat.z;
|
|
const bw = quat.w;
|
|
target.x = ax * bw + aw * bx + ay * bz - az * by;
|
|
target.y = ay * bw + aw * by + az * bx - ax * bz;
|
|
target.z = az * bw + aw * bz + ax * by - ay * bx;
|
|
target.w = aw * bw - ax * bx - ay * by - az * bz;
|
|
return target;
|
|
}
|
|
inverse(target = new Quaternion2()) {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
const w2 = this.w;
|
|
this.conjugate(target);
|
|
const inorm2 = 1 / (x * x + y * y + z * z + w2 * w2);
|
|
target.x *= inorm2;
|
|
target.y *= inorm2;
|
|
target.z *= inorm2;
|
|
target.w *= inorm2;
|
|
return target;
|
|
}
|
|
conjugate(target = new Quaternion2()) {
|
|
target.x = -this.x;
|
|
target.y = -this.y;
|
|
target.z = -this.z;
|
|
target.w = this.w;
|
|
return target;
|
|
}
|
|
normalize() {
|
|
let l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
|
if (l === 0) {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.w = 0;
|
|
} else {
|
|
l = 1 / l;
|
|
this.x *= l;
|
|
this.y *= l;
|
|
this.z *= l;
|
|
this.w *= l;
|
|
}
|
|
return this;
|
|
}
|
|
normalizeFast() {
|
|
const f = (3 - (this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)) / 2;
|
|
if (f === 0) {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.w = 0;
|
|
} else {
|
|
this.x *= f;
|
|
this.y *= f;
|
|
this.z *= f;
|
|
this.w *= f;
|
|
}
|
|
return this;
|
|
}
|
|
vmult(v, target = new Vec3()) {
|
|
const x = v.x;
|
|
const y = v.y;
|
|
const z = v.z;
|
|
const qx = this.x;
|
|
const qy = this.y;
|
|
const qz = this.z;
|
|
const qw = this.w;
|
|
const ix = qw * x + qy * z - qz * y;
|
|
const iy = qw * y + qz * x - qx * z;
|
|
const iz = qw * z + qx * y - qy * x;
|
|
const iw = -qx * x - qy * y - qz * z;
|
|
target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
|
target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
|
target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
|
return target;
|
|
}
|
|
copy(quat) {
|
|
this.x = quat.x;
|
|
this.y = quat.y;
|
|
this.z = quat.z;
|
|
this.w = quat.w;
|
|
return this;
|
|
}
|
|
toEuler(target, order = "YZX") {
|
|
let heading;
|
|
let attitude;
|
|
let bank;
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const z = this.z;
|
|
const w2 = this.w;
|
|
switch (order) {
|
|
case "YZX":
|
|
const test = x * y + z * w2;
|
|
if (test > 0.499) {
|
|
heading = 2 * Math.atan2(x, w2);
|
|
attitude = Math.PI / 2;
|
|
bank = 0;
|
|
}
|
|
if (test < -0.499) {
|
|
heading = -2 * Math.atan2(x, w2);
|
|
attitude = -Math.PI / 2;
|
|
bank = 0;
|
|
}
|
|
if (heading === void 0) {
|
|
const sqx = x * x;
|
|
const sqy = y * y;
|
|
const sqz = z * z;
|
|
heading = Math.atan2(2 * y * w2 - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
|
|
attitude = Math.asin(2 * test);
|
|
bank = Math.atan2(2 * x * w2 - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error("Euler order " + order + " not supported yet.");
|
|
}
|
|
target.y = heading;
|
|
target.z = attitude;
|
|
target.x = bank;
|
|
}
|
|
setFromEuler(x, y, z, order = "XYZ") {
|
|
const c1 = Math.cos(x / 2);
|
|
const c2 = Math.cos(y / 2);
|
|
const c3 = Math.cos(z / 2);
|
|
const s1 = Math.sin(x / 2);
|
|
const s2 = Math.sin(y / 2);
|
|
const s3 = Math.sin(z / 2);
|
|
if (order === "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;
|
|
} else if (order === "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;
|
|
} else if (order === "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;
|
|
} else if (order === "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;
|
|
} else if (order === "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;
|
|
} else if (order === "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;
|
|
}
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new Quaternion2(this.x, this.y, this.z, this.w);
|
|
}
|
|
slerp(toQuat, t, target = new Quaternion2()) {
|
|
const ax = this.x;
|
|
const ay = this.y;
|
|
const az = this.z;
|
|
const aw = this.w;
|
|
let bx = toQuat.x;
|
|
let by = toQuat.y;
|
|
let bz = toQuat.z;
|
|
let bw = toQuat.w;
|
|
let omega;
|
|
let cosom;
|
|
let sinom;
|
|
let scale0;
|
|
let scale1;
|
|
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
|
if (cosom < 0) {
|
|
cosom = -cosom;
|
|
bx = -bx;
|
|
by = -by;
|
|
bz = -bz;
|
|
bw = -bw;
|
|
}
|
|
if (1 - cosom > 1e-6) {
|
|
omega = Math.acos(cosom);
|
|
sinom = Math.sin(omega);
|
|
scale0 = Math.sin((1 - t) * omega) / sinom;
|
|
scale1 = Math.sin(t * omega) / sinom;
|
|
} else {
|
|
scale0 = 1 - t;
|
|
scale1 = t;
|
|
}
|
|
target.x = scale0 * ax + scale1 * bx;
|
|
target.y = scale0 * ay + scale1 * by;
|
|
target.z = scale0 * az + scale1 * bz;
|
|
target.w = scale0 * aw + scale1 * bw;
|
|
return target;
|
|
}
|
|
integrate(angularVelocity, dt, angularFactor, target = new Quaternion2()) {
|
|
const ax = angularVelocity.x * angularFactor.x, ay = angularVelocity.y * angularFactor.y, az = angularVelocity.z * angularFactor.z, bx = this.x, by = this.y, bz = this.z, bw = this.w;
|
|
const half_dt = dt * 0.5;
|
|
target.x += half_dt * (ax * bw + ay * bz - az * by);
|
|
target.y += half_dt * (ay * bw + az * bx - ax * bz);
|
|
target.z += half_dt * (az * bw + ax * by - ay * bx);
|
|
target.w += half_dt * (-ax * bx - ay * by - az * bz);
|
|
return target;
|
|
}
|
|
};
|
|
var sfv_t1 = new Vec3();
|
|
var sfv_t2 = new Vec3();
|
|
var SHAPE_TYPES = {
|
|
SPHERE: 1,
|
|
PLANE: 2,
|
|
BOX: 4,
|
|
COMPOUND: 8,
|
|
CONVEXPOLYHEDRON: 16,
|
|
HEIGHTFIELD: 32,
|
|
PARTICLE: 64,
|
|
CYLINDER: 128,
|
|
TRIMESH: 256
|
|
};
|
|
var Shape2 = class {
|
|
constructor(options = {}) {
|
|
this.id = void 0;
|
|
this.type = void 0;
|
|
this.boundingSphereRadius = void 0;
|
|
this.collisionResponse = void 0;
|
|
this.collisionFilterGroup = void 0;
|
|
this.collisionFilterMask = void 0;
|
|
this.material = void 0;
|
|
this.body = void 0;
|
|
this.id = Shape2.idCounter++;
|
|
this.type = options.type || 0;
|
|
this.boundingSphereRadius = 0;
|
|
this.collisionResponse = options.collisionResponse ? options.collisionResponse : true;
|
|
this.collisionFilterGroup = options.collisionFilterGroup !== void 0 ? options.collisionFilterGroup : 1;
|
|
this.collisionFilterMask = options.collisionFilterMask !== void 0 ? options.collisionFilterMask : -1;
|
|
this.material = options.material ? options.material : null;
|
|
this.body = null;
|
|
}
|
|
updateBoundingSphereRadius() {
|
|
throw "computeBoundingSphereRadius() not implemented for shape type " + this.type;
|
|
}
|
|
volume() {
|
|
throw "volume() not implemented for shape type " + this.type;
|
|
}
|
|
calculateLocalInertia(mass, target) {
|
|
throw "calculateLocalInertia() not implemented for shape type " + this.type;
|
|
}
|
|
calculateWorldAABB(pos, quat, min, max) {
|
|
throw "calculateWorldAABB() not implemented for shape type " + this.type;
|
|
}
|
|
};
|
|
Shape2.idCounter = 0;
|
|
Shape2.types = SHAPE_TYPES;
|
|
var Transform = class {
|
|
constructor(options = {}) {
|
|
this.position = void 0;
|
|
this.quaternion = void 0;
|
|
this.position = new Vec3();
|
|
this.quaternion = new Quaternion2();
|
|
if (options.position) {
|
|
this.position.copy(options.position);
|
|
}
|
|
if (options.quaternion) {
|
|
this.quaternion.copy(options.quaternion);
|
|
}
|
|
}
|
|
pointToLocal(worldPoint, result) {
|
|
return Transform.pointToLocalFrame(this.position, this.quaternion, worldPoint, result);
|
|
}
|
|
pointToWorld(localPoint, result) {
|
|
return Transform.pointToWorldFrame(this.position, this.quaternion, localPoint, result);
|
|
}
|
|
vectorToWorldFrame(localVector, result = new Vec3()) {
|
|
this.quaternion.vmult(localVector, result);
|
|
return result;
|
|
}
|
|
static pointToLocalFrame(position, quaternion, worldPoint, result = new Vec3()) {
|
|
worldPoint.vsub(position, result);
|
|
quaternion.conjugate(tmpQuat$1);
|
|
tmpQuat$1.vmult(result, result);
|
|
return result;
|
|
}
|
|
static pointToWorldFrame(position, quaternion, localPoint, result = new Vec3()) {
|
|
quaternion.vmult(localPoint, result);
|
|
result.vadd(position, result);
|
|
return result;
|
|
}
|
|
static vectorToWorldFrame(quaternion, localVector, result = new Vec3()) {
|
|
quaternion.vmult(localVector, result);
|
|
return result;
|
|
}
|
|
static vectorToLocalFrame(position, quaternion, worldVector, result = new Vec3()) {
|
|
quaternion.w *= -1;
|
|
quaternion.vmult(worldVector, result);
|
|
quaternion.w *= -1;
|
|
return result;
|
|
}
|
|
};
|
|
var tmpQuat$1 = new Quaternion2();
|
|
var ConvexPolyhedron = class extends Shape2 {
|
|
constructor(props = {}) {
|
|
const {
|
|
vertices = [],
|
|
faces = [],
|
|
normals = [],
|
|
axes,
|
|
boundingSphereRadius
|
|
} = props;
|
|
super({
|
|
type: Shape2.types.CONVEXPOLYHEDRON
|
|
});
|
|
this.vertices = void 0;
|
|
this.faces = void 0;
|
|
this.faceNormals = void 0;
|
|
this.worldVertices = void 0;
|
|
this.worldVerticesNeedsUpdate = void 0;
|
|
this.worldFaceNormals = void 0;
|
|
this.worldFaceNormalsNeedsUpdate = void 0;
|
|
this.uniqueAxes = void 0;
|
|
this.uniqueEdges = void 0;
|
|
this.vertices = vertices;
|
|
this.faces = faces;
|
|
this.faceNormals = normals;
|
|
if (this.faceNormals.length === 0) {
|
|
this.computeNormals();
|
|
}
|
|
if (!boundingSphereRadius) {
|
|
this.updateBoundingSphereRadius();
|
|
} else {
|
|
this.boundingSphereRadius = boundingSphereRadius;
|
|
}
|
|
this.worldVertices = [];
|
|
this.worldVerticesNeedsUpdate = true;
|
|
this.worldFaceNormals = [];
|
|
this.worldFaceNormalsNeedsUpdate = true;
|
|
this.uniqueAxes = axes ? axes.slice() : null;
|
|
this.uniqueEdges = [];
|
|
this.computeEdges();
|
|
}
|
|
computeEdges() {
|
|
const faces = this.faces;
|
|
const vertices = this.vertices;
|
|
const edges = this.uniqueEdges;
|
|
edges.length = 0;
|
|
const edge = new Vec3();
|
|
for (let i = 0; i !== faces.length; i++) {
|
|
const face = faces[i];
|
|
const numVertices = face.length;
|
|
for (let j = 0; j !== numVertices; j++) {
|
|
const k = (j + 1) % numVertices;
|
|
vertices[face[j]].vsub(vertices[face[k]], edge);
|
|
edge.normalize();
|
|
let found = false;
|
|
for (let p2 = 0; p2 !== edges.length; p2++) {
|
|
if (edges[p2].almostEquals(edge) || edges[p2].almostEquals(edge)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
edges.push(edge.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
computeNormals() {
|
|
this.faceNormals.length = this.faces.length;
|
|
for (let i = 0; i < this.faces.length; i++) {
|
|
for (let j = 0; j < this.faces[i].length; j++) {
|
|
if (!this.vertices[this.faces[i][j]]) {
|
|
throw new Error("Vertex " + this.faces[i][j] + " not found!");
|
|
}
|
|
}
|
|
const n = this.faceNormals[i] || new Vec3();
|
|
this.getFaceNormal(i, n);
|
|
n.negate(n);
|
|
this.faceNormals[i] = n;
|
|
const vertex = this.vertices[this.faces[i][0]];
|
|
if (n.dot(vertex) < 0) {
|
|
console.error(".faceNormals[" + i + "] = Vec3(" + n.toString() + ") looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.");
|
|
for (let j = 0; j < this.faces[i].length; j++) {
|
|
console.warn(".vertices[" + this.faces[i][j] + "] = Vec3(" + this.vertices[this.faces[i][j]].toString() + ")");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
getFaceNormal(i, target) {
|
|
const f = this.faces[i];
|
|
const va2 = this.vertices[f[0]];
|
|
const vb2 = this.vertices[f[1]];
|
|
const vc2 = this.vertices[f[2]];
|
|
ConvexPolyhedron.computeNormal(va2, vb2, vc2, target);
|
|
}
|
|
static computeNormal(va2, vb2, vc2, target) {
|
|
const cb2 = new Vec3();
|
|
const ab2 = new Vec3();
|
|
vb2.vsub(va2, ab2);
|
|
vc2.vsub(vb2, cb2);
|
|
cb2.cross(ab2, target);
|
|
if (!target.isZero()) {
|
|
target.normalize();
|
|
}
|
|
}
|
|
clipAgainstHull(posA, quatA, hullB, posB, quatB, separatingNormal, minDist, maxDist, result) {
|
|
const WorldNormal = new Vec3();
|
|
let closestFaceB = -1;
|
|
let dmax = -Number.MAX_VALUE;
|
|
for (let face = 0; face < hullB.faces.length; face++) {
|
|
WorldNormal.copy(hullB.faceNormals[face]);
|
|
quatB.vmult(WorldNormal, WorldNormal);
|
|
const d = WorldNormal.dot(separatingNormal);
|
|
if (d > dmax) {
|
|
dmax = d;
|
|
closestFaceB = face;
|
|
}
|
|
}
|
|
const worldVertsB1 = [];
|
|
for (let i = 0; i < hullB.faces[closestFaceB].length; i++) {
|
|
const b2 = hullB.vertices[hullB.faces[closestFaceB][i]];
|
|
const worldb = new Vec3();
|
|
worldb.copy(b2);
|
|
quatB.vmult(worldb, worldb);
|
|
posB.vadd(worldb, worldb);
|
|
worldVertsB1.push(worldb);
|
|
}
|
|
if (closestFaceB >= 0) {
|
|
this.clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result);
|
|
}
|
|
}
|
|
findSeparatingAxis(hullB, posA, quatA, posB, quatB, target, faceListA, faceListB) {
|
|
const faceANormalWS3 = new Vec3();
|
|
const Worldnormal1 = new Vec3();
|
|
const deltaC = new Vec3();
|
|
const worldEdge0 = new Vec3();
|
|
const worldEdge1 = new Vec3();
|
|
const Cross = new Vec3();
|
|
let dmin = Number.MAX_VALUE;
|
|
const hullA = this;
|
|
if (!hullA.uniqueAxes) {
|
|
const numFacesA = faceListA ? faceListA.length : hullA.faces.length;
|
|
for (let i = 0; i < numFacesA; i++) {
|
|
const fi = faceListA ? faceListA[i] : i;
|
|
faceANormalWS3.copy(hullA.faceNormals[fi]);
|
|
quatA.vmult(faceANormalWS3, faceANormalWS3);
|
|
const d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
|
|
if (d === false) {
|
|
return false;
|
|
}
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(faceANormalWS3);
|
|
}
|
|
}
|
|
} else {
|
|
for (let i = 0; i !== hullA.uniqueAxes.length; i++) {
|
|
quatA.vmult(hullA.uniqueAxes[i], faceANormalWS3);
|
|
const d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
|
|
if (d === false) {
|
|
return false;
|
|
}
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(faceANormalWS3);
|
|
}
|
|
}
|
|
}
|
|
if (!hullB.uniqueAxes) {
|
|
const numFacesB = faceListB ? faceListB.length : hullB.faces.length;
|
|
for (let i = 0; i < numFacesB; i++) {
|
|
const fi = faceListB ? faceListB[i] : i;
|
|
Worldnormal1.copy(hullB.faceNormals[fi]);
|
|
quatB.vmult(Worldnormal1, Worldnormal1);
|
|
const d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
|
|
if (d === false) {
|
|
return false;
|
|
}
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(Worldnormal1);
|
|
}
|
|
}
|
|
} else {
|
|
for (let i = 0; i !== hullB.uniqueAxes.length; i++) {
|
|
quatB.vmult(hullB.uniqueAxes[i], Worldnormal1);
|
|
const d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
|
|
if (d === false) {
|
|
return false;
|
|
}
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(Worldnormal1);
|
|
}
|
|
}
|
|
}
|
|
for (let e0 = 0; e0 !== hullA.uniqueEdges.length; e0++) {
|
|
quatA.vmult(hullA.uniqueEdges[e0], worldEdge0);
|
|
for (let e1 = 0; e1 !== hullB.uniqueEdges.length; e1++) {
|
|
quatB.vmult(hullB.uniqueEdges[e1], worldEdge1);
|
|
worldEdge0.cross(worldEdge1, Cross);
|
|
if (!Cross.almostZero()) {
|
|
Cross.normalize();
|
|
const dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB);
|
|
if (dist === false) {
|
|
return false;
|
|
}
|
|
if (dist < dmin) {
|
|
dmin = dist;
|
|
target.copy(Cross);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
posB.vsub(posA, deltaC);
|
|
if (deltaC.dot(target) > 0) {
|
|
target.negate(target);
|
|
}
|
|
return true;
|
|
}
|
|
testSepAxis(axis, hullB, posA, quatA, posB, quatB) {
|
|
const hullA = this;
|
|
ConvexPolyhedron.project(hullA, axis, posA, quatA, maxminA);
|
|
ConvexPolyhedron.project(hullB, axis, posB, quatB, maxminB);
|
|
const maxA = maxminA[0];
|
|
const minA = maxminA[1];
|
|
const maxB = maxminB[0];
|
|
const minB = maxminB[1];
|
|
if (maxA < minB || maxB < minA) {
|
|
return false;
|
|
}
|
|
const d0 = maxA - minB;
|
|
const d1 = maxB - minA;
|
|
const depth = d0 < d1 ? d0 : d1;
|
|
return depth;
|
|
}
|
|
calculateLocalInertia(mass, target) {
|
|
const aabbmax = new Vec3();
|
|
const aabbmin = new Vec3();
|
|
this.computeLocalAABB(aabbmin, aabbmax);
|
|
const x = aabbmax.x - aabbmin.x;
|
|
const y = aabbmax.y - aabbmin.y;
|
|
const z = aabbmax.z - aabbmin.z;
|
|
target.x = 1 / 12 * mass * (2 * y * 2 * y + 2 * z * 2 * z);
|
|
target.y = 1 / 12 * mass * (2 * x * 2 * x + 2 * z * 2 * z);
|
|
target.z = 1 / 12 * mass * (2 * y * 2 * y + 2 * x * 2 * x);
|
|
}
|
|
getPlaneConstantOfFace(face_i) {
|
|
const f = this.faces[face_i];
|
|
const n = this.faceNormals[face_i];
|
|
const v = this.vertices[f[0]];
|
|
const c2 = -n.dot(v);
|
|
return c2;
|
|
}
|
|
clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result) {
|
|
const faceANormalWS = new Vec3();
|
|
const edge0 = new Vec3();
|
|
const WorldEdge0 = new Vec3();
|
|
const worldPlaneAnormal1 = new Vec3();
|
|
const planeNormalWS1 = new Vec3();
|
|
const worldA1 = new Vec3();
|
|
const localPlaneNormal = new Vec3();
|
|
const planeNormalWS = new Vec3();
|
|
const hullA = this;
|
|
const worldVertsB2 = [];
|
|
const pVtxIn = worldVertsB1;
|
|
const pVtxOut = worldVertsB2;
|
|
let closestFaceA = -1;
|
|
let dmin = Number.MAX_VALUE;
|
|
for (let face = 0; face < hullA.faces.length; face++) {
|
|
faceANormalWS.copy(hullA.faceNormals[face]);
|
|
quatA.vmult(faceANormalWS, faceANormalWS);
|
|
const d = faceANormalWS.dot(separatingNormal);
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
closestFaceA = face;
|
|
}
|
|
}
|
|
if (closestFaceA < 0) {
|
|
return;
|
|
}
|
|
const polyA = hullA.faces[closestFaceA];
|
|
polyA.connectedFaces = [];
|
|
for (let i = 0; i < hullA.faces.length; i++) {
|
|
for (let j = 0; j < hullA.faces[i].length; j++) {
|
|
if (polyA.indexOf(hullA.faces[i][j]) !== -1 && i !== closestFaceA && polyA.connectedFaces.indexOf(i) === -1) {
|
|
polyA.connectedFaces.push(i);
|
|
}
|
|
}
|
|
}
|
|
const numVerticesA = polyA.length;
|
|
for (let i = 0; i < numVerticesA; i++) {
|
|
const a2 = hullA.vertices[polyA[i]];
|
|
const b2 = hullA.vertices[polyA[(i + 1) % numVerticesA]];
|
|
a2.vsub(b2, edge0);
|
|
WorldEdge0.copy(edge0);
|
|
quatA.vmult(WorldEdge0, WorldEdge0);
|
|
posA.vadd(WorldEdge0, WorldEdge0);
|
|
worldPlaneAnormal1.copy(this.faceNormals[closestFaceA]);
|
|
quatA.vmult(worldPlaneAnormal1, worldPlaneAnormal1);
|
|
posA.vadd(worldPlaneAnormal1, worldPlaneAnormal1);
|
|
WorldEdge0.cross(worldPlaneAnormal1, planeNormalWS1);
|
|
planeNormalWS1.negate(planeNormalWS1);
|
|
worldA1.copy(a2);
|
|
quatA.vmult(worldA1, worldA1);
|
|
posA.vadd(worldA1, worldA1);
|
|
const otherFace = polyA.connectedFaces[i];
|
|
localPlaneNormal.copy(this.faceNormals[otherFace]);
|
|
const localPlaneEq2 = this.getPlaneConstantOfFace(otherFace);
|
|
planeNormalWS.copy(localPlaneNormal);
|
|
quatA.vmult(planeNormalWS, planeNormalWS);
|
|
const planeEqWS2 = localPlaneEq2 - planeNormalWS.dot(posA);
|
|
this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, planeEqWS2);
|
|
while (pVtxIn.length) {
|
|
pVtxIn.shift();
|
|
}
|
|
while (pVtxOut.length) {
|
|
pVtxIn.push(pVtxOut.shift());
|
|
}
|
|
}
|
|
localPlaneNormal.copy(this.faceNormals[closestFaceA]);
|
|
const localPlaneEq = this.getPlaneConstantOfFace(closestFaceA);
|
|
planeNormalWS.copy(localPlaneNormal);
|
|
quatA.vmult(planeNormalWS, planeNormalWS);
|
|
const planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
|
|
for (let i = 0; i < pVtxIn.length; i++) {
|
|
let depth = planeNormalWS.dot(pVtxIn[i]) + planeEqWS;
|
|
if (depth <= minDist) {
|
|
console.log("clamped: depth=" + depth + " to minDist=" + minDist);
|
|
depth = minDist;
|
|
}
|
|
if (depth <= maxDist) {
|
|
const point = pVtxIn[i];
|
|
if (depth <= 1e-6) {
|
|
const p2 = {
|
|
point,
|
|
normal: planeNormalWS,
|
|
depth
|
|
};
|
|
result.push(p2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
clipFaceAgainstPlane(inVertices, outVertices, planeNormal, planeConstant) {
|
|
let n_dot_first;
|
|
let n_dot_last;
|
|
const numVerts = inVertices.length;
|
|
if (numVerts < 2) {
|
|
return outVertices;
|
|
}
|
|
let firstVertex = inVertices[inVertices.length - 1];
|
|
let lastVertex = inVertices[0];
|
|
n_dot_first = planeNormal.dot(firstVertex) + planeConstant;
|
|
for (let vi = 0; vi < numVerts; vi++) {
|
|
lastVertex = inVertices[vi];
|
|
n_dot_last = planeNormal.dot(lastVertex) + planeConstant;
|
|
if (n_dot_first < 0) {
|
|
if (n_dot_last < 0) {
|
|
const newv = new Vec3();
|
|
newv.copy(lastVertex);
|
|
outVertices.push(newv);
|
|
} else {
|
|
const newv = new Vec3();
|
|
firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
|
|
outVertices.push(newv);
|
|
}
|
|
} else {
|
|
if (n_dot_last < 0) {
|
|
const newv = new Vec3();
|
|
firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
|
|
outVertices.push(newv);
|
|
outVertices.push(lastVertex);
|
|
}
|
|
}
|
|
firstVertex = lastVertex;
|
|
n_dot_first = n_dot_last;
|
|
}
|
|
return outVertices;
|
|
}
|
|
computeWorldVertices(position, quat) {
|
|
while (this.worldVertices.length < this.vertices.length) {
|
|
this.worldVertices.push(new Vec3());
|
|
}
|
|
const verts = this.vertices;
|
|
const worldVerts = this.worldVertices;
|
|
for (let i = 0; i !== this.vertices.length; i++) {
|
|
quat.vmult(verts[i], worldVerts[i]);
|
|
position.vadd(worldVerts[i], worldVerts[i]);
|
|
}
|
|
this.worldVerticesNeedsUpdate = false;
|
|
}
|
|
computeLocalAABB(aabbmin, aabbmax) {
|
|
const vertices = this.vertices;
|
|
aabbmin.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
|
aabbmax.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
|
for (let i = 0; i < this.vertices.length; i++) {
|
|
const v = vertices[i];
|
|
if (v.x < aabbmin.x) {
|
|
aabbmin.x = v.x;
|
|
} else if (v.x > aabbmax.x) {
|
|
aabbmax.x = v.x;
|
|
}
|
|
if (v.y < aabbmin.y) {
|
|
aabbmin.y = v.y;
|
|
} else if (v.y > aabbmax.y) {
|
|
aabbmax.y = v.y;
|
|
}
|
|
if (v.z < aabbmin.z) {
|
|
aabbmin.z = v.z;
|
|
} else if (v.z > aabbmax.z) {
|
|
aabbmax.z = v.z;
|
|
}
|
|
}
|
|
}
|
|
computeWorldFaceNormals(quat) {
|
|
const N = this.faceNormals.length;
|
|
while (this.worldFaceNormals.length < N) {
|
|
this.worldFaceNormals.push(new Vec3());
|
|
}
|
|
const normals = this.faceNormals;
|
|
const worldNormals = this.worldFaceNormals;
|
|
for (let i = 0; i !== N; i++) {
|
|
quat.vmult(normals[i], worldNormals[i]);
|
|
}
|
|
this.worldFaceNormalsNeedsUpdate = false;
|
|
}
|
|
updateBoundingSphereRadius() {
|
|
let max2 = 0;
|
|
const verts = this.vertices;
|
|
for (let i = 0; i !== verts.length; i++) {
|
|
const norm2 = verts[i].lengthSquared();
|
|
if (norm2 > max2) {
|
|
max2 = norm2;
|
|
}
|
|
}
|
|
this.boundingSphereRadius = Math.sqrt(max2);
|
|
}
|
|
calculateWorldAABB(pos, quat, min, max) {
|
|
const verts = this.vertices;
|
|
let minx;
|
|
let miny;
|
|
let minz;
|
|
let maxx;
|
|
let maxy;
|
|
let maxz;
|
|
let tempWorldVertex = new Vec3();
|
|
for (let i = 0; i < verts.length; i++) {
|
|
tempWorldVertex.copy(verts[i]);
|
|
quat.vmult(tempWorldVertex, tempWorldVertex);
|
|
pos.vadd(tempWorldVertex, tempWorldVertex);
|
|
const v = tempWorldVertex;
|
|
if (minx === void 0 || v.x < minx) {
|
|
minx = v.x;
|
|
}
|
|
if (maxx === void 0 || v.x > maxx) {
|
|
maxx = v.x;
|
|
}
|
|
if (miny === void 0 || v.y < miny) {
|
|
miny = v.y;
|
|
}
|
|
if (maxy === void 0 || v.y > maxy) {
|
|
maxy = v.y;
|
|
}
|
|
if (minz === void 0 || v.z < minz) {
|
|
minz = v.z;
|
|
}
|
|
if (maxz === void 0 || v.z > maxz) {
|
|
maxz = v.z;
|
|
}
|
|
}
|
|
min.set(minx, miny, minz);
|
|
max.set(maxx, maxy, maxz);
|
|
}
|
|
volume() {
|
|
return 4 * Math.PI * this.boundingSphereRadius / 3;
|
|
}
|
|
getAveragePointLocal(target = new Vec3()) {
|
|
const verts = this.vertices;
|
|
for (let i = 0; i < verts.length; i++) {
|
|
target.vadd(verts[i], target);
|
|
}
|
|
target.scale(1 / verts.length, target);
|
|
return target;
|
|
}
|
|
transformAllPoints(offset, quat) {
|
|
const n = this.vertices.length;
|
|
const verts = this.vertices;
|
|
if (quat) {
|
|
for (let i = 0; i < n; i++) {
|
|
const v = verts[i];
|
|
quat.vmult(v, v);
|
|
}
|
|
for (let i = 0; i < this.faceNormals.length; i++) {
|
|
const v = this.faceNormals[i];
|
|
quat.vmult(v, v);
|
|
}
|
|
}
|
|
if (offset) {
|
|
for (let i = 0; i < n; i++) {
|
|
const v = verts[i];
|
|
v.vadd(offset, v);
|
|
}
|
|
}
|
|
}
|
|
pointIsInside(p2) {
|
|
const verts = this.vertices;
|
|
const faces = this.faces;
|
|
const normals = this.faceNormals;
|
|
const pointInside = new Vec3();
|
|
this.getAveragePointLocal(pointInside);
|
|
for (let i = 0; i < this.faces.length; i++) {
|
|
let n = normals[i];
|
|
const v = verts[faces[i][0]];
|
|
const vToP = new Vec3();
|
|
p2.vsub(v, vToP);
|
|
const r1 = n.dot(vToP);
|
|
const vToPointInside = new Vec3();
|
|
pointInside.vsub(v, vToPointInside);
|
|
const r2 = n.dot(vToPointInside);
|
|
if (r1 < 0 && r2 > 0 || r1 > 0 && r2 < 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
static project(shape, axis, pos, quat, result) {
|
|
const n = shape.vertices.length;
|
|
const localAxis = project_localAxis;
|
|
let max = 0;
|
|
let min = 0;
|
|
const localOrigin = project_localOrigin;
|
|
const vs = shape.vertices;
|
|
localOrigin.setZero();
|
|
Transform.vectorToLocalFrame(pos, quat, axis, localAxis);
|
|
Transform.pointToLocalFrame(pos, quat, localOrigin, localOrigin);
|
|
const add = localOrigin.dot(localAxis);
|
|
min = max = vs[0].dot(localAxis);
|
|
for (let i = 1; i < n; i++) {
|
|
const val = vs[i].dot(localAxis);
|
|
if (val > max) {
|
|
max = val;
|
|
}
|
|
if (val < min) {
|
|
min = val;
|
|
}
|
|
}
|
|
min -= add;
|
|
max -= add;
|
|
if (min > max) {
|
|
const temp = min;
|
|
min = max;
|
|
max = temp;
|
|
}
|
|
result[0] = max;
|
|
result[1] = min;
|
|
}
|
|
};
|
|
var maxminA = [];
|
|
var maxminB = [];
|
|
var project_localAxis = new Vec3();
|
|
var project_localOrigin = new Vec3();
|
|
var Box = class extends Shape2 {
|
|
constructor(halfExtents) {
|
|
super({
|
|
type: Shape2.types.BOX
|
|
});
|
|
this.halfExtents = void 0;
|
|
this.convexPolyhedronRepresentation = void 0;
|
|
this.halfExtents = halfExtents;
|
|
this.convexPolyhedronRepresentation = null;
|
|
this.updateConvexPolyhedronRepresentation();
|
|
this.updateBoundingSphereRadius();
|
|
}
|
|
updateConvexPolyhedronRepresentation() {
|
|
const sx = this.halfExtents.x;
|
|
const sy = this.halfExtents.y;
|
|
const sz = this.halfExtents.z;
|
|
const V = Vec3;
|
|
const vertices = [new V(-sx, -sy, -sz), new V(sx, -sy, -sz), new V(sx, sy, -sz), new V(-sx, sy, -sz), new V(-sx, -sy, sz), new V(sx, -sy, sz), new V(sx, sy, sz), new V(-sx, sy, sz)];
|
|
const faces = [
|
|
[3, 2, 1, 0],
|
|
[4, 5, 6, 7],
|
|
[5, 4, 0, 1],
|
|
[2, 3, 7, 6],
|
|
[0, 4, 7, 3],
|
|
[1, 2, 6, 5]
|
|
];
|
|
const axes = [new V(0, 0, 1), new V(0, 1, 0), new V(1, 0, 0)];
|
|
const h = new ConvexPolyhedron({
|
|
vertices,
|
|
faces,
|
|
axes
|
|
});
|
|
this.convexPolyhedronRepresentation = h;
|
|
h.material = this.material;
|
|
}
|
|
calculateLocalInertia(mass, target = new Vec3()) {
|
|
Box.calculateInertia(this.halfExtents, mass, target);
|
|
return target;
|
|
}
|
|
static calculateInertia(halfExtents, mass, target) {
|
|
const e = halfExtents;
|
|
target.x = 1 / 12 * mass * (2 * e.y * 2 * e.y + 2 * e.z * 2 * e.z);
|
|
target.y = 1 / 12 * mass * (2 * e.x * 2 * e.x + 2 * e.z * 2 * e.z);
|
|
target.z = 1 / 12 * mass * (2 * e.y * 2 * e.y + 2 * e.x * 2 * e.x);
|
|
}
|
|
getSideNormals(sixTargetVectors, quat) {
|
|
const sides = sixTargetVectors;
|
|
const ex = this.halfExtents;
|
|
sides[0].set(ex.x, 0, 0);
|
|
sides[1].set(0, ex.y, 0);
|
|
sides[2].set(0, 0, ex.z);
|
|
sides[3].set(-ex.x, 0, 0);
|
|
sides[4].set(0, -ex.y, 0);
|
|
sides[5].set(0, 0, -ex.z);
|
|
if (quat !== void 0) {
|
|
for (let i = 0; i !== sides.length; i++) {
|
|
quat.vmult(sides[i], sides[i]);
|
|
}
|
|
}
|
|
return sides;
|
|
}
|
|
volume() {
|
|
return 8 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z;
|
|
}
|
|
updateBoundingSphereRadius() {
|
|
this.boundingSphereRadius = this.halfExtents.length();
|
|
}
|
|
forEachWorldCorner(pos, quat, callback) {
|
|
const e = this.halfExtents;
|
|
const corners = [[e.x, e.y, e.z], [-e.x, e.y, e.z], [-e.x, -e.y, e.z], [-e.x, -e.y, -e.z], [e.x, -e.y, -e.z], [e.x, e.y, -e.z], [-e.x, e.y, -e.z], [e.x, -e.y, e.z]];
|
|
for (let i = 0; i < corners.length; i++) {
|
|
worldCornerTempPos.set(corners[i][0], corners[i][1], corners[i][2]);
|
|
quat.vmult(worldCornerTempPos, worldCornerTempPos);
|
|
pos.vadd(worldCornerTempPos, worldCornerTempPos);
|
|
callback(worldCornerTempPos.x, worldCornerTempPos.y, worldCornerTempPos.z);
|
|
}
|
|
}
|
|
calculateWorldAABB(pos, quat, min, max) {
|
|
const e = this.halfExtents;
|
|
worldCornersTemp[0].set(e.x, e.y, e.z);
|
|
worldCornersTemp[1].set(-e.x, e.y, e.z);
|
|
worldCornersTemp[2].set(-e.x, -e.y, e.z);
|
|
worldCornersTemp[3].set(-e.x, -e.y, -e.z);
|
|
worldCornersTemp[4].set(e.x, -e.y, -e.z);
|
|
worldCornersTemp[5].set(e.x, e.y, -e.z);
|
|
worldCornersTemp[6].set(-e.x, e.y, -e.z);
|
|
worldCornersTemp[7].set(e.x, -e.y, e.z);
|
|
const wc = worldCornersTemp[0];
|
|
quat.vmult(wc, wc);
|
|
pos.vadd(wc, wc);
|
|
max.copy(wc);
|
|
min.copy(wc);
|
|
for (let i = 1; i < 8; i++) {
|
|
const wc2 = worldCornersTemp[i];
|
|
quat.vmult(wc2, wc2);
|
|
pos.vadd(wc2, wc2);
|
|
const x = wc2.x;
|
|
const y = wc2.y;
|
|
const z = wc2.z;
|
|
if (x > max.x) {
|
|
max.x = x;
|
|
}
|
|
if (y > max.y) {
|
|
max.y = y;
|
|
}
|
|
if (z > max.z) {
|
|
max.z = z;
|
|
}
|
|
if (x < min.x) {
|
|
min.x = x;
|
|
}
|
|
if (y < min.y) {
|
|
min.y = y;
|
|
}
|
|
if (z < min.z) {
|
|
min.z = z;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var worldCornerTempPos = new Vec3();
|
|
var worldCornersTemp = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
|
|
var BODY_TYPES = {
|
|
DYNAMIC: 1,
|
|
STATIC: 2,
|
|
KINEMATIC: 4
|
|
};
|
|
var BODY_SLEEP_STATES = {
|
|
AWAKE: 0,
|
|
SLEEPY: 1,
|
|
SLEEPING: 2
|
|
};
|
|
var Body = class extends EventTarget {
|
|
constructor(options = {}) {
|
|
super();
|
|
this.id = void 0;
|
|
this.index = void 0;
|
|
this.world = void 0;
|
|
this.preStep = void 0;
|
|
this.postStep = void 0;
|
|
this.vlambda = void 0;
|
|
this.collisionFilterGroup = void 0;
|
|
this.collisionFilterMask = void 0;
|
|
this.collisionResponse = void 0;
|
|
this.position = void 0;
|
|
this.previousPosition = void 0;
|
|
this.interpolatedPosition = void 0;
|
|
this.initPosition = void 0;
|
|
this.velocity = void 0;
|
|
this.initVelocity = void 0;
|
|
this.force = void 0;
|
|
this.mass = void 0;
|
|
this.invMass = void 0;
|
|
this.material = void 0;
|
|
this.linearDamping = void 0;
|
|
this.type = void 0;
|
|
this.allowSleep = void 0;
|
|
this.sleepState = void 0;
|
|
this.sleepSpeedLimit = void 0;
|
|
this.sleepTimeLimit = void 0;
|
|
this.timeLastSleepy = void 0;
|
|
this.wakeUpAfterNarrowphase = void 0;
|
|
this.torque = void 0;
|
|
this.quaternion = void 0;
|
|
this.initQuaternion = void 0;
|
|
this.previousQuaternion = void 0;
|
|
this.interpolatedQuaternion = void 0;
|
|
this.angularVelocity = void 0;
|
|
this.initAngularVelocity = void 0;
|
|
this.shapes = void 0;
|
|
this.shapeOffsets = void 0;
|
|
this.shapeOrientations = void 0;
|
|
this.inertia = void 0;
|
|
this.invInertia = void 0;
|
|
this.invInertiaWorld = void 0;
|
|
this.invMassSolve = void 0;
|
|
this.invInertiaSolve = void 0;
|
|
this.invInertiaWorldSolve = void 0;
|
|
this.fixedRotation = void 0;
|
|
this.angularDamping = void 0;
|
|
this.linearFactor = void 0;
|
|
this.angularFactor = void 0;
|
|
this.aabb = void 0;
|
|
this.aabbNeedsUpdate = void 0;
|
|
this.boundingRadius = void 0;
|
|
this.wlambda = void 0;
|
|
this.isTrigger = void 0;
|
|
this.id = Body.idCounter++;
|
|
this.index = -1;
|
|
this.world = null;
|
|
this.preStep = null;
|
|
this.postStep = null;
|
|
this.vlambda = new Vec3();
|
|
this.collisionFilterGroup = typeof options.collisionFilterGroup === "number" ? options.collisionFilterGroup : 1;
|
|
this.collisionFilterMask = typeof options.collisionFilterMask === "number" ? options.collisionFilterMask : -1;
|
|
this.collisionResponse = typeof options.collisionResponse === "boolean" ? options.collisionResponse : true;
|
|
this.position = new Vec3();
|
|
this.previousPosition = new Vec3();
|
|
this.interpolatedPosition = new Vec3();
|
|
this.initPosition = new Vec3();
|
|
if (options.position) {
|
|
this.position.copy(options.position);
|
|
this.previousPosition.copy(options.position);
|
|
this.interpolatedPosition.copy(options.position);
|
|
this.initPosition.copy(options.position);
|
|
}
|
|
this.velocity = new Vec3();
|
|
if (options.velocity) {
|
|
this.velocity.copy(options.velocity);
|
|
}
|
|
this.initVelocity = new Vec3();
|
|
this.force = new Vec3();
|
|
const mass = typeof options.mass === "number" ? options.mass : 0;
|
|
this.mass = mass;
|
|
this.invMass = mass > 0 ? 1 / mass : 0;
|
|
this.material = options.material || null;
|
|
this.linearDamping = typeof options.linearDamping === "number" ? options.linearDamping : 0.01;
|
|
this.type = mass <= 0 ? Body.STATIC : Body.DYNAMIC;
|
|
if (typeof options.type === typeof Body.STATIC) {
|
|
this.type = options.type;
|
|
}
|
|
this.allowSleep = typeof options.allowSleep !== "undefined" ? options.allowSleep : true;
|
|
this.sleepState = Body.AWAKE;
|
|
this.sleepSpeedLimit = typeof options.sleepSpeedLimit !== "undefined" ? options.sleepSpeedLimit : 0.1;
|
|
this.sleepTimeLimit = typeof options.sleepTimeLimit !== "undefined" ? options.sleepTimeLimit : 1;
|
|
this.timeLastSleepy = 0;
|
|
this.wakeUpAfterNarrowphase = false;
|
|
this.torque = new Vec3();
|
|
this.quaternion = new Quaternion2();
|
|
this.initQuaternion = new Quaternion2();
|
|
this.previousQuaternion = new Quaternion2();
|
|
this.interpolatedQuaternion = new Quaternion2();
|
|
if (options.quaternion) {
|
|
this.quaternion.copy(options.quaternion);
|
|
this.initQuaternion.copy(options.quaternion);
|
|
this.previousQuaternion.copy(options.quaternion);
|
|
this.interpolatedQuaternion.copy(options.quaternion);
|
|
}
|
|
this.angularVelocity = new Vec3();
|
|
if (options.angularVelocity) {
|
|
this.angularVelocity.copy(options.angularVelocity);
|
|
}
|
|
this.initAngularVelocity = new Vec3();
|
|
this.shapes = [];
|
|
this.shapeOffsets = [];
|
|
this.shapeOrientations = [];
|
|
this.inertia = new Vec3();
|
|
this.invInertia = new Vec3();
|
|
this.invInertiaWorld = new Mat3();
|
|
this.invMassSolve = 0;
|
|
this.invInertiaSolve = new Vec3();
|
|
this.invInertiaWorldSolve = new Mat3();
|
|
this.fixedRotation = typeof options.fixedRotation !== "undefined" ? options.fixedRotation : false;
|
|
this.angularDamping = typeof options.angularDamping !== "undefined" ? options.angularDamping : 0.01;
|
|
this.linearFactor = new Vec3(1, 1, 1);
|
|
if (options.linearFactor) {
|
|
this.linearFactor.copy(options.linearFactor);
|
|
}
|
|
this.angularFactor = new Vec3(1, 1, 1);
|
|
if (options.angularFactor) {
|
|
this.angularFactor.copy(options.angularFactor);
|
|
}
|
|
this.aabb = new AABB();
|
|
this.aabbNeedsUpdate = true;
|
|
this.boundingRadius = 0;
|
|
this.wlambda = new Vec3();
|
|
this.isTrigger = Boolean(options.isTrigger);
|
|
if (options.shape) {
|
|
this.addShape(options.shape);
|
|
}
|
|
this.updateMassProperties();
|
|
}
|
|
wakeUp() {
|
|
const prevState = this.sleepState;
|
|
this.sleepState = Body.AWAKE;
|
|
this.wakeUpAfterNarrowphase = false;
|
|
if (prevState === Body.SLEEPING) {
|
|
this.dispatchEvent(Body.wakeupEvent);
|
|
}
|
|
}
|
|
sleep() {
|
|
this.sleepState = Body.SLEEPING;
|
|
this.velocity.set(0, 0, 0);
|
|
this.angularVelocity.set(0, 0, 0);
|
|
this.wakeUpAfterNarrowphase = false;
|
|
}
|
|
sleepTick(time) {
|
|
if (this.allowSleep) {
|
|
const sleepState = this.sleepState;
|
|
const speedSquared = this.velocity.lengthSquared() + this.angularVelocity.lengthSquared();
|
|
const speedLimitSquared = this.sleepSpeedLimit ** 2;
|
|
if (sleepState === Body.AWAKE && speedSquared < speedLimitSquared) {
|
|
this.sleepState = Body.SLEEPY;
|
|
this.timeLastSleepy = time;
|
|
this.dispatchEvent(Body.sleepyEvent);
|
|
} else if (sleepState === Body.SLEEPY && speedSquared > speedLimitSquared) {
|
|
this.wakeUp();
|
|
} else if (sleepState === Body.SLEEPY && time - this.timeLastSleepy > this.sleepTimeLimit) {
|
|
this.sleep();
|
|
this.dispatchEvent(Body.sleepEvent);
|
|
}
|
|
}
|
|
}
|
|
updateSolveMassProperties() {
|
|
if (this.sleepState === Body.SLEEPING || this.type === Body.KINEMATIC) {
|
|
this.invMassSolve = 0;
|
|
this.invInertiaSolve.setZero();
|
|
this.invInertiaWorldSolve.setZero();
|
|
} else {
|
|
this.invMassSolve = this.invMass;
|
|
this.invInertiaSolve.copy(this.invInertia);
|
|
this.invInertiaWorldSolve.copy(this.invInertiaWorld);
|
|
}
|
|
}
|
|
pointToLocalFrame(worldPoint, result = new Vec3()) {
|
|
worldPoint.vsub(this.position, result);
|
|
this.quaternion.conjugate().vmult(result, result);
|
|
return result;
|
|
}
|
|
vectorToLocalFrame(worldVector, result = new Vec3()) {
|
|
this.quaternion.conjugate().vmult(worldVector, result);
|
|
return result;
|
|
}
|
|
pointToWorldFrame(localPoint, result = new Vec3()) {
|
|
this.quaternion.vmult(localPoint, result);
|
|
result.vadd(this.position, result);
|
|
return result;
|
|
}
|
|
vectorToWorldFrame(localVector, result = new Vec3()) {
|
|
this.quaternion.vmult(localVector, result);
|
|
return result;
|
|
}
|
|
addShape(shape, _offset2, _orientation) {
|
|
const offset = new Vec3();
|
|
const orientation = new Quaternion2();
|
|
if (_offset2) {
|
|
offset.copy(_offset2);
|
|
}
|
|
if (_orientation) {
|
|
orientation.copy(_orientation);
|
|
}
|
|
this.shapes.push(shape);
|
|
this.shapeOffsets.push(offset);
|
|
this.shapeOrientations.push(orientation);
|
|
this.updateMassProperties();
|
|
this.updateBoundingRadius();
|
|
this.aabbNeedsUpdate = true;
|
|
shape.body = this;
|
|
return this;
|
|
}
|
|
removeShape(shape) {
|
|
const index = this.shapes.indexOf(shape);
|
|
if (index === -1) {
|
|
console.warn("Shape does not belong to the body");
|
|
return this;
|
|
}
|
|
this.shapes.splice(index, 1);
|
|
this.shapeOffsets.splice(index, 1);
|
|
this.shapeOrientations.splice(index, 1);
|
|
this.updateMassProperties();
|
|
this.updateBoundingRadius();
|
|
this.aabbNeedsUpdate = true;
|
|
shape.body = null;
|
|
return this;
|
|
}
|
|
updateBoundingRadius() {
|
|
const shapes = this.shapes;
|
|
const shapeOffsets = this.shapeOffsets;
|
|
const N = shapes.length;
|
|
let radius = 0;
|
|
for (let i = 0; i !== N; i++) {
|
|
const shape = shapes[i];
|
|
shape.updateBoundingSphereRadius();
|
|
const offset = shapeOffsets[i].length();
|
|
const r = shape.boundingSphereRadius;
|
|
if (offset + r > radius) {
|
|
radius = offset + r;
|
|
}
|
|
}
|
|
this.boundingRadius = radius;
|
|
}
|
|
updateAABB() {
|
|
const shapes = this.shapes;
|
|
const shapeOffsets = this.shapeOffsets;
|
|
const shapeOrientations = this.shapeOrientations;
|
|
const N = shapes.length;
|
|
const offset = tmpVec;
|
|
const orientation = tmpQuat;
|
|
const bodyQuat = this.quaternion;
|
|
const aabb = this.aabb;
|
|
const shapeAABB = updateAABB_shapeAABB;
|
|
for (let i = 0; i !== N; i++) {
|
|
const shape = shapes[i];
|
|
bodyQuat.vmult(shapeOffsets[i], offset);
|
|
offset.vadd(this.position, offset);
|
|
bodyQuat.mult(shapeOrientations[i], orientation);
|
|
shape.calculateWorldAABB(offset, orientation, shapeAABB.lowerBound, shapeAABB.upperBound);
|
|
if (i === 0) {
|
|
aabb.copy(shapeAABB);
|
|
} else {
|
|
aabb.extend(shapeAABB);
|
|
}
|
|
}
|
|
this.aabbNeedsUpdate = false;
|
|
}
|
|
updateInertiaWorld(force) {
|
|
const I = this.invInertia;
|
|
if (I.x === I.y && I.y === I.z && !force)
|
|
;
|
|
else {
|
|
const m1 = uiw_m1;
|
|
const m2 = uiw_m2;
|
|
m1.setRotationFromQuaternion(this.quaternion);
|
|
m1.transpose(m2);
|
|
m1.scale(I, m1);
|
|
m1.mmult(m2, this.invInertiaWorld);
|
|
}
|
|
}
|
|
applyForce(force, relativePoint = new Vec3()) {
|
|
if (this.type !== Body.DYNAMIC) {
|
|
return;
|
|
}
|
|
if (this.sleepState === Body.SLEEPING) {
|
|
this.wakeUp();
|
|
}
|
|
const rotForce = Body_applyForce_rotForce;
|
|
relativePoint.cross(force, rotForce);
|
|
this.force.vadd(force, this.force);
|
|
this.torque.vadd(rotForce, this.torque);
|
|
}
|
|
applyLocalForce(localForce, localPoint = new Vec3()) {
|
|
if (this.type !== Body.DYNAMIC) {
|
|
return;
|
|
}
|
|
const worldForce = Body_applyLocalForce_worldForce;
|
|
const relativePointWorld = Body_applyLocalForce_relativePointWorld;
|
|
this.vectorToWorldFrame(localForce, worldForce);
|
|
this.vectorToWorldFrame(localPoint, relativePointWorld);
|
|
this.applyForce(worldForce, relativePointWorld);
|
|
}
|
|
applyTorque(torque2) {
|
|
if (this.type !== Body.DYNAMIC) {
|
|
return;
|
|
}
|
|
if (this.sleepState === Body.SLEEPING) {
|
|
this.wakeUp();
|
|
}
|
|
this.torque.vadd(torque2, this.torque);
|
|
}
|
|
applyImpulse(impulse, relativePoint = new Vec3()) {
|
|
if (this.type !== Body.DYNAMIC) {
|
|
return;
|
|
}
|
|
if (this.sleepState === Body.SLEEPING) {
|
|
this.wakeUp();
|
|
}
|
|
const r = relativePoint;
|
|
const velo = Body_applyImpulse_velo;
|
|
velo.copy(impulse);
|
|
velo.scale(this.invMass, velo);
|
|
this.velocity.vadd(velo, this.velocity);
|
|
const rotVelo = Body_applyImpulse_rotVelo;
|
|
r.cross(impulse, rotVelo);
|
|
this.invInertiaWorld.vmult(rotVelo, rotVelo);
|
|
this.angularVelocity.vadd(rotVelo, this.angularVelocity);
|
|
}
|
|
applyLocalImpulse(localImpulse, localPoint = new Vec3()) {
|
|
if (this.type !== Body.DYNAMIC) {
|
|
return;
|
|
}
|
|
const worldImpulse = Body_applyLocalImpulse_worldImpulse;
|
|
const relativePointWorld = Body_applyLocalImpulse_relativePoint;
|
|
this.vectorToWorldFrame(localImpulse, worldImpulse);
|
|
this.vectorToWorldFrame(localPoint, relativePointWorld);
|
|
this.applyImpulse(worldImpulse, relativePointWorld);
|
|
}
|
|
updateMassProperties() {
|
|
const halfExtents = Body_updateMassProperties_halfExtents;
|
|
this.invMass = this.mass > 0 ? 1 / this.mass : 0;
|
|
const I = this.inertia;
|
|
const fixed = this.fixedRotation;
|
|
this.updateAABB();
|
|
halfExtents.set((this.aabb.upperBound.x - this.aabb.lowerBound.x) / 2, (this.aabb.upperBound.y - this.aabb.lowerBound.y) / 2, (this.aabb.upperBound.z - this.aabb.lowerBound.z) / 2);
|
|
Box.calculateInertia(halfExtents, this.mass, I);
|
|
this.invInertia.set(I.x > 0 && !fixed ? 1 / I.x : 0, I.y > 0 && !fixed ? 1 / I.y : 0, I.z > 0 && !fixed ? 1 / I.z : 0);
|
|
this.updateInertiaWorld(true);
|
|
}
|
|
getVelocityAtWorldPoint(worldPoint, result) {
|
|
const r = new Vec3();
|
|
worldPoint.vsub(this.position, r);
|
|
this.angularVelocity.cross(r, result);
|
|
this.velocity.vadd(result, result);
|
|
return result;
|
|
}
|
|
integrate(dt, quatNormalize, quatNormalizeFast) {
|
|
this.previousPosition.copy(this.position);
|
|
this.previousQuaternion.copy(this.quaternion);
|
|
if (!(this.type === Body.DYNAMIC || this.type === Body.KINEMATIC) || this.sleepState === Body.SLEEPING) {
|
|
return;
|
|
}
|
|
const velo = this.velocity;
|
|
const angularVelo = this.angularVelocity;
|
|
const pos = this.position;
|
|
const force = this.force;
|
|
const torque2 = this.torque;
|
|
const quat = this.quaternion;
|
|
const invMass = this.invMass;
|
|
const invInertia = this.invInertiaWorld;
|
|
const linearFactor = this.linearFactor;
|
|
const iMdt = invMass * dt;
|
|
velo.x += force.x * iMdt * linearFactor.x;
|
|
velo.y += force.y * iMdt * linearFactor.y;
|
|
velo.z += force.z * iMdt * linearFactor.z;
|
|
const e = invInertia.elements;
|
|
const angularFactor = this.angularFactor;
|
|
const tx = torque2.x * angularFactor.x;
|
|
const ty = torque2.y * angularFactor.y;
|
|
const tz = torque2.z * angularFactor.z;
|
|
angularVelo.x += dt * (e[0] * tx + e[1] * ty + e[2] * tz);
|
|
angularVelo.y += dt * (e[3] * tx + e[4] * ty + e[5] * tz);
|
|
angularVelo.z += dt * (e[6] * tx + e[7] * ty + e[8] * tz);
|
|
pos.x += velo.x * dt;
|
|
pos.y += velo.y * dt;
|
|
pos.z += velo.z * dt;
|
|
quat.integrate(this.angularVelocity, dt, this.angularFactor, quat);
|
|
if (quatNormalize) {
|
|
if (quatNormalizeFast) {
|
|
quat.normalizeFast();
|
|
} else {
|
|
quat.normalize();
|
|
}
|
|
}
|
|
this.aabbNeedsUpdate = true;
|
|
this.updateInertiaWorld();
|
|
}
|
|
};
|
|
Body.idCounter = 0;
|
|
Body.COLLIDE_EVENT_NAME = "collide";
|
|
Body.DYNAMIC = BODY_TYPES.DYNAMIC;
|
|
Body.STATIC = BODY_TYPES.STATIC;
|
|
Body.KINEMATIC = BODY_TYPES.KINEMATIC;
|
|
Body.AWAKE = BODY_SLEEP_STATES.AWAKE;
|
|
Body.SLEEPY = BODY_SLEEP_STATES.SLEEPY;
|
|
Body.SLEEPING = BODY_SLEEP_STATES.SLEEPING;
|
|
Body.wakeupEvent = {
|
|
type: "wakeup"
|
|
};
|
|
Body.sleepyEvent = {
|
|
type: "sleepy"
|
|
};
|
|
Body.sleepEvent = {
|
|
type: "sleep"
|
|
};
|
|
var tmpVec = new Vec3();
|
|
var tmpQuat = new Quaternion2();
|
|
var updateAABB_shapeAABB = new AABB();
|
|
var uiw_m1 = new Mat3();
|
|
var uiw_m2 = new Mat3();
|
|
var Body_applyForce_rotForce = new Vec3();
|
|
var Body_applyLocalForce_worldForce = new Vec3();
|
|
var Body_applyLocalForce_relativePointWorld = new Vec3();
|
|
var Body_applyImpulse_velo = new Vec3();
|
|
var Body_applyImpulse_rotVelo = new Vec3();
|
|
var Body_applyLocalImpulse_worldImpulse = new Vec3();
|
|
var Body_applyLocalImpulse_relativePoint = new Vec3();
|
|
var Body_updateMassProperties_halfExtents = new Vec3();
|
|
var Broadphase = class {
|
|
constructor() {
|
|
this.world = void 0;
|
|
this.useBoundingBoxes = void 0;
|
|
this.dirty = void 0;
|
|
this.world = null;
|
|
this.useBoundingBoxes = false;
|
|
this.dirty = true;
|
|
}
|
|
collisionPairs(world, p1, p2) {
|
|
throw new Error("collisionPairs not implemented for this BroadPhase class!");
|
|
}
|
|
needBroadphaseCollision(bodyA, bodyB) {
|
|
if ((bodyA.collisionFilterGroup & bodyB.collisionFilterMask) === 0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask) === 0) {
|
|
return false;
|
|
}
|
|
if (((bodyA.type & Body.STATIC) !== 0 || bodyA.sleepState === Body.SLEEPING) && ((bodyB.type & Body.STATIC) !== 0 || bodyB.sleepState === Body.SLEEPING)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
intersectionTest(bodyA, bodyB, pairs1, pairs2) {
|
|
if (this.useBoundingBoxes) {
|
|
this.doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2);
|
|
} else {
|
|
this.doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2);
|
|
}
|
|
}
|
|
doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2) {
|
|
const r = Broadphase_collisionPairs_r;
|
|
bodyB.position.vsub(bodyA.position, r);
|
|
const boundingRadiusSum2 = (bodyA.boundingRadius + bodyB.boundingRadius) ** 2;
|
|
const norm2 = r.lengthSquared();
|
|
if (norm2 < boundingRadiusSum2) {
|
|
pairs1.push(bodyA);
|
|
pairs2.push(bodyB);
|
|
}
|
|
}
|
|
doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2) {
|
|
if (bodyA.aabbNeedsUpdate) {
|
|
bodyA.updateAABB();
|
|
}
|
|
if (bodyB.aabbNeedsUpdate) {
|
|
bodyB.updateAABB();
|
|
}
|
|
if (bodyA.aabb.overlaps(bodyB.aabb)) {
|
|
pairs1.push(bodyA);
|
|
pairs2.push(bodyB);
|
|
}
|
|
}
|
|
makePairsUnique(pairs1, pairs2) {
|
|
const t = Broadphase_makePairsUnique_temp;
|
|
const p1 = Broadphase_makePairsUnique_p1;
|
|
const p2 = Broadphase_makePairsUnique_p2;
|
|
const N = pairs1.length;
|
|
for (let i = 0; i !== N; i++) {
|
|
p1[i] = pairs1[i];
|
|
p2[i] = pairs2[i];
|
|
}
|
|
pairs1.length = 0;
|
|
pairs2.length = 0;
|
|
for (let i = 0; i !== N; i++) {
|
|
const id1 = p1[i].id;
|
|
const id2 = p2[i].id;
|
|
const key = id1 < id2 ? id1 + "," + id2 : id2 + "," + id1;
|
|
t[key] = i;
|
|
t.keys.push(key);
|
|
}
|
|
for (let i = 0; i !== t.keys.length; i++) {
|
|
const key = t.keys.pop();
|
|
const pairIndex = t[key];
|
|
pairs1.push(p1[pairIndex]);
|
|
pairs2.push(p2[pairIndex]);
|
|
delete t[key];
|
|
}
|
|
}
|
|
setWorld(world) {
|
|
}
|
|
static boundingSphereCheck(bodyA, bodyB) {
|
|
const dist = new Vec3();
|
|
bodyA.position.vsub(bodyB.position, dist);
|
|
const sa = bodyA.shapes[0];
|
|
const sb = bodyB.shapes[0];
|
|
return Math.pow(sa.boundingSphereRadius + sb.boundingSphereRadius, 2) > dist.lengthSquared();
|
|
}
|
|
aabbQuery(world, aabb, result) {
|
|
console.warn(".aabbQuery is not implemented in this Broadphase subclass.");
|
|
return [];
|
|
}
|
|
};
|
|
var Broadphase_collisionPairs_r = new Vec3();
|
|
var Broadphase_makePairsUnique_temp = {
|
|
keys: []
|
|
};
|
|
var Broadphase_makePairsUnique_p1 = [];
|
|
var Broadphase_makePairsUnique_p2 = [];
|
|
var GridBroadphase_collisionPairs_d = new Vec3();
|
|
var NaiveBroadphase = class extends Broadphase {
|
|
constructor() {
|
|
super();
|
|
}
|
|
collisionPairs(world, pairs1, pairs2) {
|
|
const bodies = world.bodies;
|
|
const n = bodies.length;
|
|
let bi;
|
|
let bj;
|
|
for (let i = 0; i !== n; i++) {
|
|
for (let j = 0; j !== i; j++) {
|
|
bi = bodies[i];
|
|
bj = bodies[j];
|
|
if (!this.needBroadphaseCollision(bi, bj)) {
|
|
continue;
|
|
}
|
|
this.intersectionTest(bi, bj, pairs1, pairs2);
|
|
}
|
|
}
|
|
}
|
|
aabbQuery(world, aabb, result = []) {
|
|
for (let i = 0; i < world.bodies.length; i++) {
|
|
const b2 = world.bodies[i];
|
|
if (b2.aabbNeedsUpdate) {
|
|
b2.updateAABB();
|
|
}
|
|
if (b2.aabb.overlaps(aabb)) {
|
|
result.push(b2);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
var RaycastResult = class {
|
|
constructor() {
|
|
this.rayFromWorld = void 0;
|
|
this.rayToWorld = void 0;
|
|
this.hitNormalWorld = void 0;
|
|
this.hitPointWorld = void 0;
|
|
this.hasHit = void 0;
|
|
this.shape = void 0;
|
|
this.body = void 0;
|
|
this.hitFaceIndex = void 0;
|
|
this.distance = void 0;
|
|
this.shouldStop = void 0;
|
|
this.rayFromWorld = new Vec3();
|
|
this.rayToWorld = new Vec3();
|
|
this.hitNormalWorld = new Vec3();
|
|
this.hitPointWorld = new Vec3();
|
|
this.hasHit = false;
|
|
this.shape = null;
|
|
this.body = null;
|
|
this.hitFaceIndex = -1;
|
|
this.distance = -1;
|
|
this.shouldStop = false;
|
|
}
|
|
reset() {
|
|
this.rayFromWorld.setZero();
|
|
this.rayToWorld.setZero();
|
|
this.hitNormalWorld.setZero();
|
|
this.hitPointWorld.setZero();
|
|
this.hasHit = false;
|
|
this.shape = null;
|
|
this.body = null;
|
|
this.hitFaceIndex = -1;
|
|
this.distance = -1;
|
|
this.shouldStop = false;
|
|
}
|
|
abort() {
|
|
this.shouldStop = true;
|
|
}
|
|
set(rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, shape, body, distance) {
|
|
this.rayFromWorld.copy(rayFromWorld);
|
|
this.rayToWorld.copy(rayToWorld);
|
|
this.hitNormalWorld.copy(hitNormalWorld);
|
|
this.hitPointWorld.copy(hitPointWorld);
|
|
this.shape = shape;
|
|
this.body = body;
|
|
this.distance = distance;
|
|
}
|
|
};
|
|
var _Shape$types$SPHERE;
|
|
var _Shape$types$PLANE;
|
|
var _Shape$types$BOX;
|
|
var _Shape$types$CYLINDER;
|
|
var _Shape$types$CONVEXPO;
|
|
var _Shape$types$HEIGHTFI;
|
|
var _Shape$types$TRIMESH;
|
|
var RAY_MODES = {
|
|
CLOSEST: 1,
|
|
ANY: 2,
|
|
ALL: 4
|
|
};
|
|
_Shape$types$SPHERE = Shape2.types.SPHERE;
|
|
_Shape$types$PLANE = Shape2.types.PLANE;
|
|
_Shape$types$BOX = Shape2.types.BOX;
|
|
_Shape$types$CYLINDER = Shape2.types.CYLINDER;
|
|
_Shape$types$CONVEXPO = Shape2.types.CONVEXPOLYHEDRON;
|
|
_Shape$types$HEIGHTFI = Shape2.types.HEIGHTFIELD;
|
|
_Shape$types$TRIMESH = Shape2.types.TRIMESH;
|
|
var Ray2 = class {
|
|
get [_Shape$types$SPHERE]() {
|
|
return this._intersectSphere;
|
|
}
|
|
get [_Shape$types$PLANE]() {
|
|
return this._intersectPlane;
|
|
}
|
|
get [_Shape$types$BOX]() {
|
|
return this._intersectBox;
|
|
}
|
|
get [_Shape$types$CYLINDER]() {
|
|
return this._intersectConvex;
|
|
}
|
|
get [_Shape$types$CONVEXPO]() {
|
|
return this._intersectConvex;
|
|
}
|
|
get [_Shape$types$HEIGHTFI]() {
|
|
return this._intersectHeightfield;
|
|
}
|
|
get [_Shape$types$TRIMESH]() {
|
|
return this._intersectTrimesh;
|
|
}
|
|
constructor(from = new Vec3(), to = new Vec3()) {
|
|
this.from = void 0;
|
|
this.to = void 0;
|
|
this.direction = void 0;
|
|
this.precision = void 0;
|
|
this.checkCollisionResponse = void 0;
|
|
this.skipBackfaces = void 0;
|
|
this.collisionFilterMask = void 0;
|
|
this.collisionFilterGroup = void 0;
|
|
this.mode = void 0;
|
|
this.result = void 0;
|
|
this.hasHit = void 0;
|
|
this.callback = void 0;
|
|
this.from = from.clone();
|
|
this.to = to.clone();
|
|
this.direction = new Vec3();
|
|
this.precision = 1e-4;
|
|
this.checkCollisionResponse = true;
|
|
this.skipBackfaces = false;
|
|
this.collisionFilterMask = -1;
|
|
this.collisionFilterGroup = -1;
|
|
this.mode = Ray2.ANY;
|
|
this.result = new RaycastResult();
|
|
this.hasHit = false;
|
|
this.callback = (result) => {
|
|
};
|
|
}
|
|
intersectWorld(world, options) {
|
|
this.mode = options.mode || Ray2.ANY;
|
|
this.result = options.result || new RaycastResult();
|
|
this.skipBackfaces = !!options.skipBackfaces;
|
|
this.collisionFilterMask = typeof options.collisionFilterMask !== "undefined" ? options.collisionFilterMask : -1;
|
|
this.collisionFilterGroup = typeof options.collisionFilterGroup !== "undefined" ? options.collisionFilterGroup : -1;
|
|
this.checkCollisionResponse = typeof options.checkCollisionResponse !== "undefined" ? options.checkCollisionResponse : true;
|
|
if (options.from) {
|
|
this.from.copy(options.from);
|
|
}
|
|
if (options.to) {
|
|
this.to.copy(options.to);
|
|
}
|
|
this.callback = options.callback || (() => {
|
|
});
|
|
this.hasHit = false;
|
|
this.result.reset();
|
|
this.updateDirection();
|
|
this.getAABB(tmpAABB$1);
|
|
tmpArray.length = 0;
|
|
world.broadphase.aabbQuery(world, tmpAABB$1, tmpArray);
|
|
this.intersectBodies(tmpArray);
|
|
return this.hasHit;
|
|
}
|
|
intersectBody(body, result) {
|
|
if (result) {
|
|
this.result = result;
|
|
this.updateDirection();
|
|
}
|
|
const checkCollisionResponse = this.checkCollisionResponse;
|
|
if (checkCollisionResponse && !body.collisionResponse) {
|
|
return;
|
|
}
|
|
if ((this.collisionFilterGroup & body.collisionFilterMask) === 0 || (body.collisionFilterGroup & this.collisionFilterMask) === 0) {
|
|
return;
|
|
}
|
|
const xi = intersectBody_xi;
|
|
const qi = intersectBody_qi;
|
|
for (let i = 0, N = body.shapes.length; i < N; i++) {
|
|
const shape = body.shapes[i];
|
|
if (checkCollisionResponse && !shape.collisionResponse) {
|
|
continue;
|
|
}
|
|
body.quaternion.mult(body.shapeOrientations[i], qi);
|
|
body.quaternion.vmult(body.shapeOffsets[i], xi);
|
|
xi.vadd(body.position, xi);
|
|
this.intersectShape(shape, qi, xi, body);
|
|
if (this.result.shouldStop) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
intersectBodies(bodies, result) {
|
|
if (result) {
|
|
this.result = result;
|
|
this.updateDirection();
|
|
}
|
|
for (let i = 0, l = bodies.length; !this.result.shouldStop && i < l; i++) {
|
|
this.intersectBody(bodies[i]);
|
|
}
|
|
}
|
|
updateDirection() {
|
|
this.to.vsub(this.from, this.direction);
|
|
this.direction.normalize();
|
|
}
|
|
intersectShape(shape, quat, position, body) {
|
|
const from = this.from;
|
|
const distance = distanceFromIntersection(from, this.direction, position);
|
|
if (distance > shape.boundingSphereRadius) {
|
|
return;
|
|
}
|
|
const intersectMethod = this[shape.type];
|
|
if (intersectMethod) {
|
|
intersectMethod.call(this, shape, quat, position, body, shape);
|
|
}
|
|
}
|
|
_intersectBox(box, quat, position, body, reportedShape) {
|
|
return this._intersectConvex(box.convexPolyhedronRepresentation, quat, position, body, reportedShape);
|
|
}
|
|
_intersectPlane(shape, quat, position, body, reportedShape) {
|
|
const from = this.from;
|
|
const to = this.to;
|
|
const direction = this.direction;
|
|
const worldNormal = new Vec3(0, 0, 1);
|
|
quat.vmult(worldNormal, worldNormal);
|
|
const len = new Vec3();
|
|
from.vsub(position, len);
|
|
const planeToFrom = len.dot(worldNormal);
|
|
to.vsub(position, len);
|
|
const planeToTo = len.dot(worldNormal);
|
|
if (planeToFrom * planeToTo > 0) {
|
|
return;
|
|
}
|
|
if (from.distanceTo(to) < planeToFrom) {
|
|
return;
|
|
}
|
|
const n_dot_dir = worldNormal.dot(direction);
|
|
if (Math.abs(n_dot_dir) < this.precision) {
|
|
return;
|
|
}
|
|
const planePointToFrom = new Vec3();
|
|
const dir_scaled_with_t = new Vec3();
|
|
const hitPointWorld = new Vec3();
|
|
from.vsub(position, planePointToFrom);
|
|
const t = -worldNormal.dot(planePointToFrom) / n_dot_dir;
|
|
direction.scale(t, dir_scaled_with_t);
|
|
from.vadd(dir_scaled_with_t, hitPointWorld);
|
|
this.reportIntersection(worldNormal, hitPointWorld, reportedShape, body, -1);
|
|
}
|
|
getAABB(aabb) {
|
|
const {
|
|
lowerBound,
|
|
upperBound
|
|
} = aabb;
|
|
const to = this.to;
|
|
const from = this.from;
|
|
lowerBound.x = Math.min(to.x, from.x);
|
|
lowerBound.y = Math.min(to.y, from.y);
|
|
lowerBound.z = Math.min(to.z, from.z);
|
|
upperBound.x = Math.max(to.x, from.x);
|
|
upperBound.y = Math.max(to.y, from.y);
|
|
upperBound.z = Math.max(to.z, from.z);
|
|
}
|
|
_intersectHeightfield(shape, quat, position, body, reportedShape) {
|
|
shape.data;
|
|
shape.elementSize;
|
|
const localRay = intersectHeightfield_localRay;
|
|
localRay.from.copy(this.from);
|
|
localRay.to.copy(this.to);
|
|
Transform.pointToLocalFrame(position, quat, localRay.from, localRay.from);
|
|
Transform.pointToLocalFrame(position, quat, localRay.to, localRay.to);
|
|
localRay.updateDirection();
|
|
const index = intersectHeightfield_index;
|
|
let iMinX;
|
|
let iMinY;
|
|
let iMaxX;
|
|
let iMaxY;
|
|
iMinX = iMinY = 0;
|
|
iMaxX = iMaxY = shape.data.length - 1;
|
|
const aabb = new AABB();
|
|
localRay.getAABB(aabb);
|
|
shape.getIndexOfPosition(aabb.lowerBound.x, aabb.lowerBound.y, index, true);
|
|
iMinX = Math.max(iMinX, index[0]);
|
|
iMinY = Math.max(iMinY, index[1]);
|
|
shape.getIndexOfPosition(aabb.upperBound.x, aabb.upperBound.y, index, true);
|
|
iMaxX = Math.min(iMaxX, index[0] + 1);
|
|
iMaxY = Math.min(iMaxY, index[1] + 1);
|
|
for (let i = iMinX; i < iMaxX; i++) {
|
|
for (let j = iMinY; j < iMaxY; j++) {
|
|
if (this.result.shouldStop) {
|
|
return;
|
|
}
|
|
shape.getAabbAtIndex(i, j, aabb);
|
|
if (!aabb.overlapsRay(localRay)) {
|
|
continue;
|
|
}
|
|
shape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
|
|
this._intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions);
|
|
if (this.result.shouldStop) {
|
|
return;
|
|
}
|
|
shape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
|
|
this._intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions);
|
|
}
|
|
}
|
|
}
|
|
_intersectSphere(sphere, quat, position, body, reportedShape) {
|
|
const from = this.from;
|
|
const to = this.to;
|
|
const r = sphere.radius;
|
|
const a2 = (to.x - from.x) ** 2 + (to.y - from.y) ** 2 + (to.z - from.z) ** 2;
|
|
const b2 = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z));
|
|
const c2 = (from.x - position.x) ** 2 + (from.y - position.y) ** 2 + (from.z - position.z) ** 2 - r ** 2;
|
|
const delta = b2 ** 2 - 4 * a2 * c2;
|
|
const intersectionPoint = Ray_intersectSphere_intersectionPoint;
|
|
const normal = Ray_intersectSphere_normal;
|
|
if (delta < 0) {
|
|
return;
|
|
} else if (delta === 0) {
|
|
from.lerp(to, delta, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
} else {
|
|
const d1 = (-b2 - Math.sqrt(delta)) / (2 * a2);
|
|
const d2 = (-b2 + Math.sqrt(delta)) / (2 * a2);
|
|
if (d1 >= 0 && d1 <= 1) {
|
|
from.lerp(to, d1, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
}
|
|
if (this.result.shouldStop) {
|
|
return;
|
|
}
|
|
if (d2 >= 0 && d2 <= 1) {
|
|
from.lerp(to, d2, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
}
|
|
}
|
|
}
|
|
_intersectConvex(shape, quat, position, body, reportedShape, options) {
|
|
const normal = intersectConvex_normal;
|
|
const vector = intersectConvex_vector;
|
|
const faceList = options && options.faceList || null;
|
|
const faces = shape.faces;
|
|
const vertices = shape.vertices;
|
|
const normals = shape.faceNormals;
|
|
const direction = this.direction;
|
|
const from = this.from;
|
|
const to = this.to;
|
|
const fromToDistance = from.distanceTo(to);
|
|
const Nfaces = faceList ? faceList.length : faces.length;
|
|
const result = this.result;
|
|
for (let j = 0; !result.shouldStop && j < Nfaces; j++) {
|
|
const fi = faceList ? faceList[j] : j;
|
|
const face = faces[fi];
|
|
const faceNormal = normals[fi];
|
|
const q = quat;
|
|
const x = position;
|
|
vector.copy(vertices[face[0]]);
|
|
q.vmult(vector, vector);
|
|
vector.vadd(x, vector);
|
|
vector.vsub(from, vector);
|
|
q.vmult(faceNormal, normal);
|
|
const dot = direction.dot(normal);
|
|
if (Math.abs(dot) < this.precision) {
|
|
continue;
|
|
}
|
|
const scalar = normal.dot(vector) / dot;
|
|
if (scalar < 0) {
|
|
continue;
|
|
}
|
|
direction.scale(scalar, intersectPoint);
|
|
intersectPoint.vadd(from, intersectPoint);
|
|
a.copy(vertices[face[0]]);
|
|
q.vmult(a, a);
|
|
x.vadd(a, a);
|
|
for (let i = 1; !result.shouldStop && i < face.length - 1; i++) {
|
|
b.copy(vertices[face[i]]);
|
|
c.copy(vertices[face[i + 1]]);
|
|
q.vmult(b, b);
|
|
q.vmult(c, c);
|
|
x.vadd(b, b);
|
|
x.vadd(c, c);
|
|
const distance = intersectPoint.distanceTo(from);
|
|
if (!(Ray2.pointInTriangle(intersectPoint, a, b, c) || Ray2.pointInTriangle(intersectPoint, b, a, c)) || distance > fromToDistance) {
|
|
continue;
|
|
}
|
|
this.reportIntersection(normal, intersectPoint, reportedShape, body, fi);
|
|
}
|
|
}
|
|
}
|
|
_intersectTrimesh(mesh, quat, position, body, reportedShape, options) {
|
|
const normal = intersectTrimesh_normal;
|
|
const triangles = intersectTrimesh_triangles;
|
|
const treeTransform = intersectTrimesh_treeTransform;
|
|
const vector = intersectConvex_vector;
|
|
const localDirection = intersectTrimesh_localDirection;
|
|
const localFrom = intersectTrimesh_localFrom;
|
|
const localTo = intersectTrimesh_localTo;
|
|
const worldIntersectPoint = intersectTrimesh_worldIntersectPoint;
|
|
const worldNormal = intersectTrimesh_worldNormal;
|
|
const indices = mesh.indices;
|
|
mesh.vertices;
|
|
const from = this.from;
|
|
const to = this.to;
|
|
const direction = this.direction;
|
|
treeTransform.position.copy(position);
|
|
treeTransform.quaternion.copy(quat);
|
|
Transform.vectorToLocalFrame(position, quat, direction, localDirection);
|
|
Transform.pointToLocalFrame(position, quat, from, localFrom);
|
|
Transform.pointToLocalFrame(position, quat, to, localTo);
|
|
localTo.x *= mesh.scale.x;
|
|
localTo.y *= mesh.scale.y;
|
|
localTo.z *= mesh.scale.z;
|
|
localFrom.x *= mesh.scale.x;
|
|
localFrom.y *= mesh.scale.y;
|
|
localFrom.z *= mesh.scale.z;
|
|
localTo.vsub(localFrom, localDirection);
|
|
localDirection.normalize();
|
|
const fromToDistanceSquared = localFrom.distanceSquared(localTo);
|
|
mesh.tree.rayQuery(this, treeTransform, triangles);
|
|
for (let i = 0, N = triangles.length; !this.result.shouldStop && i !== N; i++) {
|
|
const trianglesIndex = triangles[i];
|
|
mesh.getNormal(trianglesIndex, normal);
|
|
mesh.getVertex(indices[trianglesIndex * 3], a);
|
|
a.vsub(localFrom, vector);
|
|
const dot = localDirection.dot(normal);
|
|
const scalar = normal.dot(vector) / dot;
|
|
if (scalar < 0) {
|
|
continue;
|
|
}
|
|
localDirection.scale(scalar, intersectPoint);
|
|
intersectPoint.vadd(localFrom, intersectPoint);
|
|
mesh.getVertex(indices[trianglesIndex * 3 + 1], b);
|
|
mesh.getVertex(indices[trianglesIndex * 3 + 2], c);
|
|
const squaredDistance = intersectPoint.distanceSquared(localFrom);
|
|
if (!(Ray2.pointInTriangle(intersectPoint, b, a, c) || Ray2.pointInTriangle(intersectPoint, a, b, c)) || squaredDistance > fromToDistanceSquared) {
|
|
continue;
|
|
}
|
|
Transform.vectorToWorldFrame(quat, normal, worldNormal);
|
|
Transform.pointToWorldFrame(position, quat, intersectPoint, worldIntersectPoint);
|
|
this.reportIntersection(worldNormal, worldIntersectPoint, reportedShape, body, trianglesIndex);
|
|
}
|
|
triangles.length = 0;
|
|
}
|
|
reportIntersection(normal, hitPointWorld, shape, body, hitFaceIndex) {
|
|
const from = this.from;
|
|
const to = this.to;
|
|
const distance = from.distanceTo(hitPointWorld);
|
|
const result = this.result;
|
|
if (this.skipBackfaces && normal.dot(this.direction) > 0) {
|
|
return;
|
|
}
|
|
result.hitFaceIndex = typeof hitFaceIndex !== "undefined" ? hitFaceIndex : -1;
|
|
switch (this.mode) {
|
|
case Ray2.ALL:
|
|
this.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
result.hasHit = true;
|
|
this.callback(result);
|
|
break;
|
|
case Ray2.CLOSEST:
|
|
if (distance < result.distance || !result.hasHit) {
|
|
this.hasHit = true;
|
|
result.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
}
|
|
break;
|
|
case Ray2.ANY:
|
|
this.hasHit = true;
|
|
result.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
result.shouldStop = true;
|
|
break;
|
|
}
|
|
}
|
|
static pointInTriangle(p2, a2, b2, c2) {
|
|
c2.vsub(a2, v0);
|
|
b2.vsub(a2, v1);
|
|
p2.vsub(a2, v2);
|
|
const dot00 = v0.dot(v0);
|
|
const dot01 = v0.dot(v1);
|
|
const dot02 = v0.dot(v2);
|
|
const dot11 = v1.dot(v1);
|
|
const dot12 = v1.dot(v2);
|
|
let u;
|
|
let v;
|
|
return (u = dot11 * dot02 - dot01 * dot12) >= 0 && (v = dot00 * dot12 - dot01 * dot02) >= 0 && u + v < dot00 * dot11 - dot01 * dot01;
|
|
}
|
|
};
|
|
Ray2.CLOSEST = RAY_MODES.CLOSEST;
|
|
Ray2.ANY = RAY_MODES.ANY;
|
|
Ray2.ALL = RAY_MODES.ALL;
|
|
var tmpAABB$1 = new AABB();
|
|
var tmpArray = [];
|
|
var v1 = new Vec3();
|
|
var v2 = new Vec3();
|
|
var intersectBody_xi = new Vec3();
|
|
var intersectBody_qi = new Quaternion2();
|
|
var intersectPoint = new Vec3();
|
|
var a = new Vec3();
|
|
var b = new Vec3();
|
|
var c = new Vec3();
|
|
var intersectConvexOptions = {
|
|
faceList: [0]
|
|
};
|
|
var worldPillarOffset = new Vec3();
|
|
var intersectHeightfield_localRay = new Ray2();
|
|
var intersectHeightfield_index = [];
|
|
var Ray_intersectSphere_intersectionPoint = new Vec3();
|
|
var Ray_intersectSphere_normal = new Vec3();
|
|
var intersectConvex_normal = new Vec3();
|
|
var intersectConvex_vector = new Vec3();
|
|
var intersectTrimesh_normal = new Vec3();
|
|
var intersectTrimesh_localDirection = new Vec3();
|
|
var intersectTrimesh_localFrom = new Vec3();
|
|
var intersectTrimesh_localTo = new Vec3();
|
|
var intersectTrimesh_worldNormal = new Vec3();
|
|
var intersectTrimesh_worldIntersectPoint = new Vec3();
|
|
new AABB();
|
|
var intersectTrimesh_triangles = [];
|
|
var intersectTrimesh_treeTransform = new Transform();
|
|
var v0 = new Vec3();
|
|
var intersect = new Vec3();
|
|
function distanceFromIntersection(from, direction, position) {
|
|
position.vsub(from, v0);
|
|
const dot = v0.dot(direction);
|
|
direction.scale(dot, intersect);
|
|
intersect.vadd(from, intersect);
|
|
const distance = position.distanceTo(intersect);
|
|
return distance;
|
|
}
|
|
var Utils = class {
|
|
static defaults(options = {}, defaults) {
|
|
for (let key in defaults) {
|
|
if (!(key in options)) {
|
|
options[key] = defaults[key];
|
|
}
|
|
}
|
|
return options;
|
|
}
|
|
};
|
|
var Constraint = class {
|
|
constructor(bodyA, bodyB, options = {}) {
|
|
this.equations = void 0;
|
|
this.bodyA = void 0;
|
|
this.bodyB = void 0;
|
|
this.id = void 0;
|
|
this.collideConnected = void 0;
|
|
options = Utils.defaults(options, {
|
|
collideConnected: true,
|
|
wakeUpBodies: true
|
|
});
|
|
this.equations = [];
|
|
this.bodyA = bodyA;
|
|
this.bodyB = bodyB;
|
|
this.id = Constraint.idCounter++;
|
|
this.collideConnected = options.collideConnected;
|
|
if (options.wakeUpBodies) {
|
|
if (bodyA) {
|
|
bodyA.wakeUp();
|
|
}
|
|
if (bodyB) {
|
|
bodyB.wakeUp();
|
|
}
|
|
}
|
|
}
|
|
update() {
|
|
throw new Error("method update() not implmemented in this Constraint subclass!");
|
|
}
|
|
enable() {
|
|
const eqs = this.equations;
|
|
for (let i = 0; i < eqs.length; i++) {
|
|
eqs[i].enabled = true;
|
|
}
|
|
}
|
|
disable() {
|
|
const eqs = this.equations;
|
|
for (let i = 0; i < eqs.length; i++) {
|
|
eqs[i].enabled = false;
|
|
}
|
|
}
|
|
};
|
|
Constraint.idCounter = 0;
|
|
var JacobianElement = class {
|
|
constructor() {
|
|
this.spatial = void 0;
|
|
this.rotational = void 0;
|
|
this.spatial = new Vec3();
|
|
this.rotational = new Vec3();
|
|
}
|
|
multiplyElement(element) {
|
|
return element.spatial.dot(this.spatial) + element.rotational.dot(this.rotational);
|
|
}
|
|
multiplyVectors(spatial, rotational) {
|
|
return spatial.dot(this.spatial) + rotational.dot(this.rotational);
|
|
}
|
|
};
|
|
var Equation = class {
|
|
constructor(bi, bj, minForce = -1e6, maxForce = 1e6) {
|
|
this.id = void 0;
|
|
this.minForce = void 0;
|
|
this.maxForce = void 0;
|
|
this.bi = void 0;
|
|
this.bj = void 0;
|
|
this.si = void 0;
|
|
this.sj = void 0;
|
|
this.a = void 0;
|
|
this.b = void 0;
|
|
this.eps = void 0;
|
|
this.jacobianElementA = void 0;
|
|
this.jacobianElementB = void 0;
|
|
this.enabled = void 0;
|
|
this.multiplier = void 0;
|
|
this.id = Equation.idCounter++;
|
|
this.minForce = minForce;
|
|
this.maxForce = maxForce;
|
|
this.bi = bi;
|
|
this.bj = bj;
|
|
this.a = 0;
|
|
this.b = 0;
|
|
this.eps = 0;
|
|
this.jacobianElementA = new JacobianElement();
|
|
this.jacobianElementB = new JacobianElement();
|
|
this.enabled = true;
|
|
this.multiplier = 0;
|
|
this.setSpookParams(1e7, 4, 1 / 60);
|
|
}
|
|
setSpookParams(stiffness, relaxation, timeStep) {
|
|
const d = relaxation;
|
|
const k = stiffness;
|
|
const h = timeStep;
|
|
this.a = 4 / (h * (1 + 4 * d));
|
|
this.b = 4 * d / (1 + 4 * d);
|
|
this.eps = 4 / (h * h * k * (1 + 4 * d));
|
|
}
|
|
computeB(a2, b2, h) {
|
|
const GW = this.computeGW();
|
|
const Gq = this.computeGq();
|
|
const GiMf = this.computeGiMf();
|
|
return -Gq * a2 - GW * b2 - GiMf * h;
|
|
}
|
|
computeGq() {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const xi = bi.position;
|
|
const xj = bj.position;
|
|
return GA.spatial.dot(xi) + GB.spatial.dot(xj);
|
|
}
|
|
computeGW() {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const vi = bi.velocity;
|
|
const vj = bj.velocity;
|
|
const wi = bi.angularVelocity;
|
|
const wj = bj.angularVelocity;
|
|
return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
|
|
}
|
|
computeGWlambda() {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const vi = bi.vlambda;
|
|
const vj = bj.vlambda;
|
|
const wi = bi.wlambda;
|
|
const wj = bj.wlambda;
|
|
return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
|
|
}
|
|
computeGiMf() {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const fi = bi.force;
|
|
const ti = bi.torque;
|
|
const fj = bj.force;
|
|
const tj = bj.torque;
|
|
const invMassi = bi.invMassSolve;
|
|
const invMassj = bj.invMassSolve;
|
|
fi.scale(invMassi, iMfi);
|
|
fj.scale(invMassj, iMfj);
|
|
bi.invInertiaWorldSolve.vmult(ti, invIi_vmult_taui);
|
|
bj.invInertiaWorldSolve.vmult(tj, invIj_vmult_tauj);
|
|
return GA.multiplyVectors(iMfi, invIi_vmult_taui) + GB.multiplyVectors(iMfj, invIj_vmult_tauj);
|
|
}
|
|
computeGiMGt() {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const invMassi = bi.invMassSolve;
|
|
const invMassj = bj.invMassSolve;
|
|
const invIi = bi.invInertiaWorldSolve;
|
|
const invIj = bj.invInertiaWorldSolve;
|
|
let result = invMassi + invMassj;
|
|
invIi.vmult(GA.rotational, tmp2);
|
|
result += tmp2.dot(GA.rotational);
|
|
invIj.vmult(GB.rotational, tmp2);
|
|
result += tmp2.dot(GB.rotational);
|
|
return result;
|
|
}
|
|
addToWlambda(deltalambda) {
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const temp = addToWlambda_temp;
|
|
bi.vlambda.addScaledVector(bi.invMassSolve * deltalambda, GA.spatial, bi.vlambda);
|
|
bj.vlambda.addScaledVector(bj.invMassSolve * deltalambda, GB.spatial, bj.vlambda);
|
|
bi.invInertiaWorldSolve.vmult(GA.rotational, temp);
|
|
bi.wlambda.addScaledVector(deltalambda, temp, bi.wlambda);
|
|
bj.invInertiaWorldSolve.vmult(GB.rotational, temp);
|
|
bj.wlambda.addScaledVector(deltalambda, temp, bj.wlambda);
|
|
}
|
|
computeC() {
|
|
return this.computeGiMGt() + this.eps;
|
|
}
|
|
};
|
|
Equation.idCounter = 0;
|
|
var iMfi = new Vec3();
|
|
var iMfj = new Vec3();
|
|
var invIi_vmult_taui = new Vec3();
|
|
var invIj_vmult_tauj = new Vec3();
|
|
var tmp2 = new Vec3();
|
|
var addToWlambda_temp = new Vec3();
|
|
var ContactEquation = class extends Equation {
|
|
constructor(bodyA, bodyB, maxForce = 1e6) {
|
|
super(bodyA, bodyB, 0, maxForce);
|
|
this.restitution = void 0;
|
|
this.ri = void 0;
|
|
this.rj = void 0;
|
|
this.ni = void 0;
|
|
this.restitution = 0;
|
|
this.ri = new Vec3();
|
|
this.rj = new Vec3();
|
|
this.ni = new Vec3();
|
|
}
|
|
computeB(h) {
|
|
const a2 = this.a;
|
|
const b2 = this.b;
|
|
const bi = this.bi;
|
|
const bj = this.bj;
|
|
const ri = this.ri;
|
|
const rj = this.rj;
|
|
const rixn = ContactEquation_computeB_temp1;
|
|
const rjxn = ContactEquation_computeB_temp2;
|
|
const vi = bi.velocity;
|
|
const wi = bi.angularVelocity;
|
|
bi.force;
|
|
bi.torque;
|
|
const vj = bj.velocity;
|
|
const wj = bj.angularVelocity;
|
|
bj.force;
|
|
bj.torque;
|
|
const penetrationVec = ContactEquation_computeB_temp3;
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
const n = this.ni;
|
|
ri.cross(n, rixn);
|
|
rj.cross(n, rjxn);
|
|
n.negate(GA.spatial);
|
|
rixn.negate(GA.rotational);
|
|
GB.spatial.copy(n);
|
|
GB.rotational.copy(rjxn);
|
|
penetrationVec.copy(bj.position);
|
|
penetrationVec.vadd(rj, penetrationVec);
|
|
penetrationVec.vsub(bi.position, penetrationVec);
|
|
penetrationVec.vsub(ri, penetrationVec);
|
|
const g = n.dot(penetrationVec);
|
|
const ePlusOne = this.restitution + 1;
|
|
const GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn);
|
|
const GiMf = this.computeGiMf();
|
|
const B = -g * a2 - GW * b2 - h * GiMf;
|
|
return B;
|
|
}
|
|
getImpactVelocityAlongNormal() {
|
|
const vi = ContactEquation_getImpactVelocityAlongNormal_vi;
|
|
const vj = ContactEquation_getImpactVelocityAlongNormal_vj;
|
|
const xi = ContactEquation_getImpactVelocityAlongNormal_xi;
|
|
const xj = ContactEquation_getImpactVelocityAlongNormal_xj;
|
|
const relVel = ContactEquation_getImpactVelocityAlongNormal_relVel;
|
|
this.bi.position.vadd(this.ri, xi);
|
|
this.bj.position.vadd(this.rj, xj);
|
|
this.bi.getVelocityAtWorldPoint(xi, vi);
|
|
this.bj.getVelocityAtWorldPoint(xj, vj);
|
|
vi.vsub(vj, relVel);
|
|
return this.ni.dot(relVel);
|
|
}
|
|
};
|
|
var ContactEquation_computeB_temp1 = new Vec3();
|
|
var ContactEquation_computeB_temp2 = new Vec3();
|
|
var ContactEquation_computeB_temp3 = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3();
|
|
var tmpVec1$2 = new Vec3();
|
|
var tmpVec2$2 = new Vec3();
|
|
var tmpVec1$1 = new Vec3();
|
|
var tmpVec2$1 = new Vec3();
|
|
var HingeConstraint_update_tmpVec1 = new Vec3();
|
|
var HingeConstraint_update_tmpVec2 = new Vec3();
|
|
var FrictionEquation = class extends Equation {
|
|
constructor(bodyA, bodyB, slipForce) {
|
|
super(bodyA, bodyB, -slipForce, slipForce);
|
|
this.ri = void 0;
|
|
this.rj = void 0;
|
|
this.t = void 0;
|
|
this.ri = new Vec3();
|
|
this.rj = new Vec3();
|
|
this.t = new Vec3();
|
|
}
|
|
computeB(h) {
|
|
this.a;
|
|
const b2 = this.b;
|
|
this.bi;
|
|
this.bj;
|
|
const ri = this.ri;
|
|
const rj = this.rj;
|
|
const rixt = FrictionEquation_computeB_temp1;
|
|
const rjxt = FrictionEquation_computeB_temp2;
|
|
const t = this.t;
|
|
ri.cross(t, rixt);
|
|
rj.cross(t, rjxt);
|
|
const GA = this.jacobianElementA;
|
|
const GB = this.jacobianElementB;
|
|
t.negate(GA.spatial);
|
|
rixt.negate(GA.rotational);
|
|
GB.spatial.copy(t);
|
|
GB.rotational.copy(rjxt);
|
|
const GW = this.computeGW();
|
|
const GiMf = this.computeGiMf();
|
|
const B = -GW * b2 - h * GiMf;
|
|
return B;
|
|
}
|
|
};
|
|
var FrictionEquation_computeB_temp1 = new Vec3();
|
|
var FrictionEquation_computeB_temp2 = new Vec3();
|
|
var ContactMaterial = class {
|
|
constructor(m1, m2, options) {
|
|
this.id = void 0;
|
|
this.materials = void 0;
|
|
this.friction = void 0;
|
|
this.restitution = void 0;
|
|
this.contactEquationStiffness = void 0;
|
|
this.contactEquationRelaxation = void 0;
|
|
this.frictionEquationStiffness = void 0;
|
|
this.frictionEquationRelaxation = void 0;
|
|
options = Utils.defaults(options, {
|
|
friction: 0.3,
|
|
restitution: 0.3,
|
|
contactEquationStiffness: 1e7,
|
|
contactEquationRelaxation: 3,
|
|
frictionEquationStiffness: 1e7,
|
|
frictionEquationRelaxation: 3
|
|
});
|
|
this.id = ContactMaterial.idCounter++;
|
|
this.materials = [m1, m2];
|
|
this.friction = options.friction;
|
|
this.restitution = options.restitution;
|
|
this.contactEquationStiffness = options.contactEquationStiffness;
|
|
this.contactEquationRelaxation = options.contactEquationRelaxation;
|
|
this.frictionEquationStiffness = options.frictionEquationStiffness;
|
|
this.frictionEquationRelaxation = options.frictionEquationRelaxation;
|
|
}
|
|
};
|
|
ContactMaterial.idCounter = 0;
|
|
var Material2 = class {
|
|
constructor(options = {}) {
|
|
this.name = void 0;
|
|
this.id = void 0;
|
|
this.friction = void 0;
|
|
this.restitution = void 0;
|
|
let name = "";
|
|
if (typeof options === "string") {
|
|
name = options;
|
|
options = {};
|
|
}
|
|
this.name = name;
|
|
this.id = Material2.idCounter++;
|
|
this.friction = typeof options.friction !== "undefined" ? options.friction : -1;
|
|
this.restitution = typeof options.restitution !== "undefined" ? options.restitution : -1;
|
|
}
|
|
};
|
|
Material2.idCounter = 0;
|
|
var applyForce_r = new Vec3();
|
|
var applyForce_r_unit = new Vec3();
|
|
var applyForce_u = new Vec3();
|
|
var applyForce_f = new Vec3();
|
|
var applyForce_worldAnchorA = new Vec3();
|
|
var applyForce_worldAnchorB = new Vec3();
|
|
var applyForce_ri = new Vec3();
|
|
var applyForce_rj = new Vec3();
|
|
var applyForce_ri_x_f = new Vec3();
|
|
var applyForce_rj_x_f = new Vec3();
|
|
var applyForce_tmp = new Vec3();
|
|
var chassis_velocity_at_contactPoint = new Vec3();
|
|
var relpos = new Vec3();
|
|
var tmpVec4 = new Vec3();
|
|
var tmpVec5 = new Vec3();
|
|
var tmpVec6 = new Vec3();
|
|
new Ray2();
|
|
var castRay_rayvector = new Vec3();
|
|
var castRay_target = new Vec3();
|
|
var directions = [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)];
|
|
var updateFriction_surfNormalWS_scaled_proj = new Vec3();
|
|
var calcRollingFriction_vel1 = new Vec3();
|
|
var calcRollingFriction_vel2 = new Vec3();
|
|
var calcRollingFriction_vel = new Vec3();
|
|
var computeImpulseDenominator_r0 = new Vec3();
|
|
var computeImpulseDenominator_c0 = new Vec3();
|
|
var computeImpulseDenominator_vec = new Vec3();
|
|
var computeImpulseDenominator_m = new Vec3();
|
|
var resolveSingleBilateral_vel1 = new Vec3();
|
|
var resolveSingleBilateral_vel2 = new Vec3();
|
|
var resolveSingleBilateral_vel = new Vec3();
|
|
var torque = new Vec3();
|
|
var worldAxis = new Vec3();
|
|
var SPHSystem_getNeighbors_dist = new Vec3();
|
|
var SPHSystem_update_dist = new Vec3();
|
|
var SPHSystem_update_a_pressure = new Vec3();
|
|
var SPHSystem_update_a_visc = new Vec3();
|
|
var SPHSystem_update_gradW = new Vec3();
|
|
var SPHSystem_update_r_vec = new Vec3();
|
|
var SPHSystem_update_u = new Vec3();
|
|
var Plane2 = class extends Shape2 {
|
|
constructor() {
|
|
super({
|
|
type: Shape2.types.PLANE
|
|
});
|
|
this.worldNormal = void 0;
|
|
this.worldNormalNeedsUpdate = void 0;
|
|
this.boundingSphereRadius = void 0;
|
|
this.worldNormal = new Vec3();
|
|
this.worldNormalNeedsUpdate = true;
|
|
this.boundingSphereRadius = Number.MAX_VALUE;
|
|
}
|
|
computeWorldNormal(quat) {
|
|
const n = this.worldNormal;
|
|
n.set(0, 0, 1);
|
|
quat.vmult(n, n);
|
|
this.worldNormalNeedsUpdate = false;
|
|
}
|
|
calculateLocalInertia(mass, target = new Vec3()) {
|
|
return target;
|
|
}
|
|
volume() {
|
|
return Number.MAX_VALUE;
|
|
}
|
|
calculateWorldAABB(pos, quat, min, max) {
|
|
tempNormal.set(0, 0, 1);
|
|
quat.vmult(tempNormal, tempNormal);
|
|
const maxVal = Number.MAX_VALUE;
|
|
min.set(-maxVal, -maxVal, -maxVal);
|
|
max.set(maxVal, maxVal, maxVal);
|
|
if (tempNormal.x === 1) {
|
|
max.x = pos.x;
|
|
} else if (tempNormal.x === -1) {
|
|
min.x = pos.x;
|
|
}
|
|
if (tempNormal.y === 1) {
|
|
max.y = pos.y;
|
|
} else if (tempNormal.y === -1) {
|
|
min.y = pos.y;
|
|
}
|
|
if (tempNormal.z === 1) {
|
|
max.z = pos.z;
|
|
} else if (tempNormal.z === -1) {
|
|
min.z = pos.z;
|
|
}
|
|
}
|
|
updateBoundingSphereRadius() {
|
|
this.boundingSphereRadius = Number.MAX_VALUE;
|
|
}
|
|
};
|
|
var tempNormal = new Vec3();
|
|
var getHeightAt_weights = new Vec3();
|
|
var getHeightAt_a = new Vec3();
|
|
var getHeightAt_b = new Vec3();
|
|
var getHeightAt_c = new Vec3();
|
|
var getNormalAt_a = new Vec3();
|
|
var getNormalAt_b = new Vec3();
|
|
var getNormalAt_c = new Vec3();
|
|
var getNormalAt_e0 = new Vec3();
|
|
var getNormalAt_e1 = new Vec3();
|
|
var halfDiagonal = new Vec3();
|
|
var tmpAABB = new AABB();
|
|
var computeNormals_n = new Vec3();
|
|
var unscaledAABB = new AABB();
|
|
var getEdgeVector_va = new Vec3();
|
|
var getEdgeVector_vb = new Vec3();
|
|
var cb = new Vec3();
|
|
var ab = new Vec3();
|
|
var va = new Vec3();
|
|
var vb = new Vec3();
|
|
var vc = new Vec3();
|
|
var cli_aabb = new AABB();
|
|
var computeLocalAABB_worldVert = new Vec3();
|
|
var calculateWorldAABB_frame = new Transform();
|
|
var calculateWorldAABB_aabb = new AABB();
|
|
var Solver = class {
|
|
constructor() {
|
|
this.equations = void 0;
|
|
this.equations = [];
|
|
}
|
|
solve(dt, world) {
|
|
return 0;
|
|
}
|
|
addEquation(eq) {
|
|
if (eq.enabled && !eq.bi.isTrigger && !eq.bj.isTrigger) {
|
|
this.equations.push(eq);
|
|
}
|
|
}
|
|
removeEquation(eq) {
|
|
const eqs = this.equations;
|
|
const i = eqs.indexOf(eq);
|
|
if (i !== -1) {
|
|
eqs.splice(i, 1);
|
|
}
|
|
}
|
|
removeAllEquations() {
|
|
this.equations.length = 0;
|
|
}
|
|
};
|
|
var GSSolver = class extends Solver {
|
|
constructor() {
|
|
super();
|
|
this.iterations = void 0;
|
|
this.tolerance = void 0;
|
|
this.iterations = 10;
|
|
this.tolerance = 1e-7;
|
|
}
|
|
solve(dt, world) {
|
|
let iter = 0;
|
|
const maxIter = this.iterations;
|
|
const tolSquared = this.tolerance * this.tolerance;
|
|
const equations = this.equations;
|
|
const Neq = equations.length;
|
|
const bodies = world.bodies;
|
|
const Nbodies = bodies.length;
|
|
const h = dt;
|
|
let B;
|
|
let invC;
|
|
let deltalambda;
|
|
let deltalambdaTot;
|
|
let GWlambda;
|
|
let lambdaj;
|
|
if (Neq !== 0) {
|
|
for (let i = 0; i !== Nbodies; i++) {
|
|
bodies[i].updateSolveMassProperties();
|
|
}
|
|
}
|
|
const invCs = GSSolver_solve_invCs;
|
|
const Bs = GSSolver_solve_Bs;
|
|
const lambda = GSSolver_solve_lambda;
|
|
invCs.length = Neq;
|
|
Bs.length = Neq;
|
|
lambda.length = Neq;
|
|
for (let i = 0; i !== Neq; i++) {
|
|
const c2 = equations[i];
|
|
lambda[i] = 0;
|
|
Bs[i] = c2.computeB(h);
|
|
invCs[i] = 1 / c2.computeC();
|
|
}
|
|
if (Neq !== 0) {
|
|
for (let i = 0; i !== Nbodies; i++) {
|
|
const b2 = bodies[i];
|
|
const vlambda = b2.vlambda;
|
|
const wlambda = b2.wlambda;
|
|
vlambda.set(0, 0, 0);
|
|
wlambda.set(0, 0, 0);
|
|
}
|
|
for (iter = 0; iter !== maxIter; iter++) {
|
|
deltalambdaTot = 0;
|
|
for (let j = 0; j !== Neq; j++) {
|
|
const c2 = equations[j];
|
|
B = Bs[j];
|
|
invC = invCs[j];
|
|
lambdaj = lambda[j];
|
|
GWlambda = c2.computeGWlambda();
|
|
deltalambda = invC * (B - GWlambda - c2.eps * lambdaj);
|
|
if (lambdaj + deltalambda < c2.minForce) {
|
|
deltalambda = c2.minForce - lambdaj;
|
|
} else if (lambdaj + deltalambda > c2.maxForce) {
|
|
deltalambda = c2.maxForce - lambdaj;
|
|
}
|
|
lambda[j] += deltalambda;
|
|
deltalambdaTot += deltalambda > 0 ? deltalambda : -deltalambda;
|
|
c2.addToWlambda(deltalambda);
|
|
}
|
|
if (deltalambdaTot * deltalambdaTot < tolSquared) {
|
|
break;
|
|
}
|
|
}
|
|
for (let i = 0; i !== Nbodies; i++) {
|
|
const b2 = bodies[i];
|
|
const v = b2.velocity;
|
|
const w2 = b2.angularVelocity;
|
|
b2.vlambda.vmul(b2.linearFactor, b2.vlambda);
|
|
v.vadd(b2.vlambda, v);
|
|
b2.wlambda.vmul(b2.angularFactor, b2.wlambda);
|
|
w2.vadd(b2.wlambda, w2);
|
|
}
|
|
let l = equations.length;
|
|
const invDt = 1 / h;
|
|
while (l--) {
|
|
equations[l].multiplier = lambda[l] * invDt;
|
|
}
|
|
}
|
|
return iter;
|
|
}
|
|
};
|
|
var GSSolver_solve_lambda = [];
|
|
var GSSolver_solve_invCs = [];
|
|
var GSSolver_solve_Bs = [];
|
|
var STATIC = Body.STATIC;
|
|
var Pool = class {
|
|
constructor() {
|
|
this.objects = [];
|
|
this.type = Object;
|
|
}
|
|
release(...args) {
|
|
const Nargs = args.length;
|
|
for (let i = 0; i !== Nargs; i++) {
|
|
this.objects.push(args[i]);
|
|
}
|
|
return this;
|
|
}
|
|
get() {
|
|
if (this.objects.length === 0) {
|
|
return this.constructObject();
|
|
} else {
|
|
return this.objects.pop();
|
|
}
|
|
}
|
|
constructObject() {
|
|
throw new Error("constructObject() not implemented in this Pool subclass yet!");
|
|
}
|
|
resize(size) {
|
|
const objects = this.objects;
|
|
while (objects.length > size) {
|
|
objects.pop();
|
|
}
|
|
while (objects.length < size) {
|
|
objects.push(this.constructObject());
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var Vec3Pool = class extends Pool {
|
|
constructor(...args) {
|
|
super(...args);
|
|
this.type = Vec3;
|
|
}
|
|
constructObject() {
|
|
return new Vec3();
|
|
}
|
|
};
|
|
var _COLLISION_TYPES$sphe;
|
|
var _COLLISION_TYPES$sphe2;
|
|
var _COLLISION_TYPES$boxB;
|
|
var _COLLISION_TYPES$sphe3;
|
|
var _COLLISION_TYPES$plan;
|
|
var _COLLISION_TYPES$conv;
|
|
var _COLLISION_TYPES$sphe4;
|
|
var _COLLISION_TYPES$plan2;
|
|
var _COLLISION_TYPES$boxC;
|
|
var _COLLISION_TYPES$sphe5;
|
|
var _COLLISION_TYPES$boxH;
|
|
var _COLLISION_TYPES$conv2;
|
|
var _COLLISION_TYPES$sphe6;
|
|
var _COLLISION_TYPES$plan3;
|
|
var _COLLISION_TYPES$boxP;
|
|
var _COLLISION_TYPES$conv3;
|
|
var _COLLISION_TYPES$cyli;
|
|
var _COLLISION_TYPES$sphe7;
|
|
var _COLLISION_TYPES$plan4;
|
|
var _COLLISION_TYPES$boxC2;
|
|
var _COLLISION_TYPES$conv4;
|
|
var _COLLISION_TYPES$heig;
|
|
var _COLLISION_TYPES$part;
|
|
var _COLLISION_TYPES$sphe8;
|
|
var _COLLISION_TYPES$plan5;
|
|
var COLLISION_TYPES = {
|
|
sphereSphere: Shape2.types.SPHERE,
|
|
spherePlane: Shape2.types.SPHERE | Shape2.types.PLANE,
|
|
boxBox: Shape2.types.BOX | Shape2.types.BOX,
|
|
sphereBox: Shape2.types.SPHERE | Shape2.types.BOX,
|
|
planeBox: Shape2.types.PLANE | Shape2.types.BOX,
|
|
convexConvex: Shape2.types.CONVEXPOLYHEDRON,
|
|
sphereConvex: Shape2.types.SPHERE | Shape2.types.CONVEXPOLYHEDRON,
|
|
planeConvex: Shape2.types.PLANE | Shape2.types.CONVEXPOLYHEDRON,
|
|
boxConvex: Shape2.types.BOX | Shape2.types.CONVEXPOLYHEDRON,
|
|
sphereHeightfield: Shape2.types.SPHERE | Shape2.types.HEIGHTFIELD,
|
|
boxHeightfield: Shape2.types.BOX | Shape2.types.HEIGHTFIELD,
|
|
convexHeightfield: Shape2.types.CONVEXPOLYHEDRON | Shape2.types.HEIGHTFIELD,
|
|
sphereParticle: Shape2.types.PARTICLE | Shape2.types.SPHERE,
|
|
planeParticle: Shape2.types.PLANE | Shape2.types.PARTICLE,
|
|
boxParticle: Shape2.types.BOX | Shape2.types.PARTICLE,
|
|
convexParticle: Shape2.types.PARTICLE | Shape2.types.CONVEXPOLYHEDRON,
|
|
cylinderCylinder: Shape2.types.CYLINDER,
|
|
sphereCylinder: Shape2.types.SPHERE | Shape2.types.CYLINDER,
|
|
planeCylinder: Shape2.types.PLANE | Shape2.types.CYLINDER,
|
|
boxCylinder: Shape2.types.BOX | Shape2.types.CYLINDER,
|
|
convexCylinder: Shape2.types.CONVEXPOLYHEDRON | Shape2.types.CYLINDER,
|
|
heightfieldCylinder: Shape2.types.HEIGHTFIELD | Shape2.types.CYLINDER,
|
|
particleCylinder: Shape2.types.PARTICLE | Shape2.types.CYLINDER,
|
|
sphereTrimesh: Shape2.types.SPHERE | Shape2.types.TRIMESH,
|
|
planeTrimesh: Shape2.types.PLANE | Shape2.types.TRIMESH
|
|
};
|
|
_COLLISION_TYPES$sphe = COLLISION_TYPES.sphereSphere;
|
|
_COLLISION_TYPES$sphe2 = COLLISION_TYPES.spherePlane;
|
|
_COLLISION_TYPES$boxB = COLLISION_TYPES.boxBox;
|
|
_COLLISION_TYPES$sphe3 = COLLISION_TYPES.sphereBox;
|
|
_COLLISION_TYPES$plan = COLLISION_TYPES.planeBox;
|
|
_COLLISION_TYPES$conv = COLLISION_TYPES.convexConvex;
|
|
_COLLISION_TYPES$sphe4 = COLLISION_TYPES.sphereConvex;
|
|
_COLLISION_TYPES$plan2 = COLLISION_TYPES.planeConvex;
|
|
_COLLISION_TYPES$boxC = COLLISION_TYPES.boxConvex;
|
|
_COLLISION_TYPES$sphe5 = COLLISION_TYPES.sphereHeightfield;
|
|
_COLLISION_TYPES$boxH = COLLISION_TYPES.boxHeightfield;
|
|
_COLLISION_TYPES$conv2 = COLLISION_TYPES.convexHeightfield;
|
|
_COLLISION_TYPES$sphe6 = COLLISION_TYPES.sphereParticle;
|
|
_COLLISION_TYPES$plan3 = COLLISION_TYPES.planeParticle;
|
|
_COLLISION_TYPES$boxP = COLLISION_TYPES.boxParticle;
|
|
_COLLISION_TYPES$conv3 = COLLISION_TYPES.convexParticle;
|
|
_COLLISION_TYPES$cyli = COLLISION_TYPES.cylinderCylinder;
|
|
_COLLISION_TYPES$sphe7 = COLLISION_TYPES.sphereCylinder;
|
|
_COLLISION_TYPES$plan4 = COLLISION_TYPES.planeCylinder;
|
|
_COLLISION_TYPES$boxC2 = COLLISION_TYPES.boxCylinder;
|
|
_COLLISION_TYPES$conv4 = COLLISION_TYPES.convexCylinder;
|
|
_COLLISION_TYPES$heig = COLLISION_TYPES.heightfieldCylinder;
|
|
_COLLISION_TYPES$part = COLLISION_TYPES.particleCylinder;
|
|
_COLLISION_TYPES$sphe8 = COLLISION_TYPES.sphereTrimesh;
|
|
_COLLISION_TYPES$plan5 = COLLISION_TYPES.planeTrimesh;
|
|
var Narrowphase = class {
|
|
get [_COLLISION_TYPES$sphe]() {
|
|
return this.sphereSphere;
|
|
}
|
|
get [_COLLISION_TYPES$sphe2]() {
|
|
return this.spherePlane;
|
|
}
|
|
get [_COLLISION_TYPES$boxB]() {
|
|
return this.boxBox;
|
|
}
|
|
get [_COLLISION_TYPES$sphe3]() {
|
|
return this.sphereBox;
|
|
}
|
|
get [_COLLISION_TYPES$plan]() {
|
|
return this.planeBox;
|
|
}
|
|
get [_COLLISION_TYPES$conv]() {
|
|
return this.convexConvex;
|
|
}
|
|
get [_COLLISION_TYPES$sphe4]() {
|
|
return this.sphereConvex;
|
|
}
|
|
get [_COLLISION_TYPES$plan2]() {
|
|
return this.planeConvex;
|
|
}
|
|
get [_COLLISION_TYPES$boxC]() {
|
|
return this.boxConvex;
|
|
}
|
|
get [_COLLISION_TYPES$sphe5]() {
|
|
return this.sphereHeightfield;
|
|
}
|
|
get [_COLLISION_TYPES$boxH]() {
|
|
return this.boxHeightfield;
|
|
}
|
|
get [_COLLISION_TYPES$conv2]() {
|
|
return this.convexHeightfield;
|
|
}
|
|
get [_COLLISION_TYPES$sphe6]() {
|
|
return this.sphereParticle;
|
|
}
|
|
get [_COLLISION_TYPES$plan3]() {
|
|
return this.planeParticle;
|
|
}
|
|
get [_COLLISION_TYPES$boxP]() {
|
|
return this.boxParticle;
|
|
}
|
|
get [_COLLISION_TYPES$conv3]() {
|
|
return this.convexParticle;
|
|
}
|
|
get [_COLLISION_TYPES$cyli]() {
|
|
return this.convexConvex;
|
|
}
|
|
get [_COLLISION_TYPES$sphe7]() {
|
|
return this.sphereConvex;
|
|
}
|
|
get [_COLLISION_TYPES$plan4]() {
|
|
return this.planeConvex;
|
|
}
|
|
get [_COLLISION_TYPES$boxC2]() {
|
|
return this.boxConvex;
|
|
}
|
|
get [_COLLISION_TYPES$conv4]() {
|
|
return this.convexConvex;
|
|
}
|
|
get [_COLLISION_TYPES$heig]() {
|
|
return this.heightfieldCylinder;
|
|
}
|
|
get [_COLLISION_TYPES$part]() {
|
|
return this.particleCylinder;
|
|
}
|
|
get [_COLLISION_TYPES$sphe8]() {
|
|
return this.sphereTrimesh;
|
|
}
|
|
get [_COLLISION_TYPES$plan5]() {
|
|
return this.planeTrimesh;
|
|
}
|
|
constructor(world) {
|
|
this.contactPointPool = void 0;
|
|
this.frictionEquationPool = void 0;
|
|
this.result = void 0;
|
|
this.frictionResult = void 0;
|
|
this.v3pool = void 0;
|
|
this.world = void 0;
|
|
this.currentContactMaterial = void 0;
|
|
this.enableFrictionReduction = void 0;
|
|
this.contactPointPool = [];
|
|
this.frictionEquationPool = [];
|
|
this.result = [];
|
|
this.frictionResult = [];
|
|
this.v3pool = new Vec3Pool();
|
|
this.world = world;
|
|
this.currentContactMaterial = world.defaultContactMaterial;
|
|
this.enableFrictionReduction = false;
|
|
}
|
|
createContactEquation(bi, bj, si, sj, overrideShapeA, overrideShapeB) {
|
|
let c2;
|
|
if (this.contactPointPool.length) {
|
|
c2 = this.contactPointPool.pop();
|
|
c2.bi = bi;
|
|
c2.bj = bj;
|
|
} else {
|
|
c2 = new ContactEquation(bi, bj);
|
|
}
|
|
c2.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;
|
|
const cm = this.currentContactMaterial;
|
|
c2.restitution = cm.restitution;
|
|
c2.setSpookParams(cm.contactEquationStiffness, cm.contactEquationRelaxation, this.world.dt);
|
|
const matA = si.material || bi.material;
|
|
const matB = sj.material || bj.material;
|
|
if (matA && matB && matA.restitution >= 0 && matB.restitution >= 0) {
|
|
c2.restitution = matA.restitution * matB.restitution;
|
|
}
|
|
c2.si = overrideShapeA || si;
|
|
c2.sj = overrideShapeB || sj;
|
|
return c2;
|
|
}
|
|
createFrictionEquationsFromContact(contactEquation, outArray) {
|
|
const bodyA = contactEquation.bi;
|
|
const bodyB = contactEquation.bj;
|
|
const shapeA = contactEquation.si;
|
|
const shapeB = contactEquation.sj;
|
|
const world = this.world;
|
|
const cm = this.currentContactMaterial;
|
|
let friction = cm.friction;
|
|
const matA = shapeA.material || bodyA.material;
|
|
const matB = shapeB.material || bodyB.material;
|
|
if (matA && matB && matA.friction >= 0 && matB.friction >= 0) {
|
|
friction = matA.friction * matB.friction;
|
|
}
|
|
if (friction > 0) {
|
|
const mug = friction * world.gravity.length();
|
|
let reducedMass = bodyA.invMass + bodyB.invMass;
|
|
if (reducedMass > 0) {
|
|
reducedMass = 1 / reducedMass;
|
|
}
|
|
const pool = this.frictionEquationPool;
|
|
const c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
|
|
const c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
|
|
c1.bi = c2.bi = bodyA;
|
|
c1.bj = c2.bj = bodyB;
|
|
c1.minForce = c2.minForce = -mug * reducedMass;
|
|
c1.maxForce = c2.maxForce = mug * reducedMass;
|
|
c1.ri.copy(contactEquation.ri);
|
|
c1.rj.copy(contactEquation.rj);
|
|
c2.ri.copy(contactEquation.ri);
|
|
c2.rj.copy(contactEquation.rj);
|
|
contactEquation.ni.tangents(c1.t, c2.t);
|
|
c1.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
|
|
c2.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
|
|
c1.enabled = c2.enabled = contactEquation.enabled;
|
|
outArray.push(c1, c2);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
createFrictionFromAverage(numContacts) {
|
|
let c2 = this.result[this.result.length - 1];
|
|
if (!this.createFrictionEquationsFromContact(c2, this.frictionResult) || numContacts === 1) {
|
|
return;
|
|
}
|
|
const f1 = this.frictionResult[this.frictionResult.length - 2];
|
|
const f2 = this.frictionResult[this.frictionResult.length - 1];
|
|
averageNormal.setZero();
|
|
averageContactPointA.setZero();
|
|
averageContactPointB.setZero();
|
|
const bodyA = c2.bi;
|
|
c2.bj;
|
|
for (let i = 0; i !== numContacts; i++) {
|
|
c2 = this.result[this.result.length - 1 - i];
|
|
if (c2.bi !== bodyA) {
|
|
averageNormal.vadd(c2.ni, averageNormal);
|
|
averageContactPointA.vadd(c2.ri, averageContactPointA);
|
|
averageContactPointB.vadd(c2.rj, averageContactPointB);
|
|
} else {
|
|
averageNormal.vsub(c2.ni, averageNormal);
|
|
averageContactPointA.vadd(c2.rj, averageContactPointA);
|
|
averageContactPointB.vadd(c2.ri, averageContactPointB);
|
|
}
|
|
}
|
|
const invNumContacts = 1 / numContacts;
|
|
averageContactPointA.scale(invNumContacts, f1.ri);
|
|
averageContactPointB.scale(invNumContacts, f1.rj);
|
|
f2.ri.copy(f1.ri);
|
|
f2.rj.copy(f1.rj);
|
|
averageNormal.normalize();
|
|
averageNormal.tangents(f1.t, f2.t);
|
|
}
|
|
getContacts(p1, p2, world, result, oldcontacts, frictionResult, frictionPool) {
|
|
this.contactPointPool = oldcontacts;
|
|
this.frictionEquationPool = frictionPool;
|
|
this.result = result;
|
|
this.frictionResult = frictionResult;
|
|
const qi = tmpQuat1;
|
|
const qj = tmpQuat2;
|
|
const xi = tmpVec1;
|
|
const xj = tmpVec2;
|
|
for (let k = 0, N = p1.length; k !== N; k++) {
|
|
const bi = p1[k];
|
|
const bj = p2[k];
|
|
let bodyContactMaterial = null;
|
|
if (bi.material && bj.material) {
|
|
bodyContactMaterial = world.getContactMaterial(bi.material, bj.material) || null;
|
|
}
|
|
const justTest = bi.type & Body.KINEMATIC && bj.type & Body.STATIC || bi.type & Body.STATIC && bj.type & Body.KINEMATIC || bi.type & Body.KINEMATIC && bj.type & Body.KINEMATIC;
|
|
for (let i = 0; i < bi.shapes.length; i++) {
|
|
bi.quaternion.mult(bi.shapeOrientations[i], qi);
|
|
bi.quaternion.vmult(bi.shapeOffsets[i], xi);
|
|
xi.vadd(bi.position, xi);
|
|
const si = bi.shapes[i];
|
|
for (let j = 0; j < bj.shapes.length; j++) {
|
|
bj.quaternion.mult(bj.shapeOrientations[j], qj);
|
|
bj.quaternion.vmult(bj.shapeOffsets[j], xj);
|
|
xj.vadd(bj.position, xj);
|
|
const sj = bj.shapes[j];
|
|
if (!(si.collisionFilterMask & sj.collisionFilterGroup && sj.collisionFilterMask & si.collisionFilterGroup)) {
|
|
continue;
|
|
}
|
|
if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) {
|
|
continue;
|
|
}
|
|
let shapeContactMaterial = null;
|
|
if (si.material && sj.material) {
|
|
shapeContactMaterial = world.getContactMaterial(si.material, sj.material) || null;
|
|
}
|
|
this.currentContactMaterial = shapeContactMaterial || bodyContactMaterial || world.defaultContactMaterial;
|
|
const resolverIndex = si.type | sj.type;
|
|
const resolver = this[resolverIndex];
|
|
if (resolver) {
|
|
let retval = false;
|
|
if (si.type < sj.type) {
|
|
retval = resolver.call(this, si, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
} else {
|
|
retval = resolver.call(this, sj, si, xj, xi, qj, qi, bj, bi, si, sj, justTest);
|
|
}
|
|
if (retval && justTest) {
|
|
world.shapeOverlapKeeper.set(si.id, sj.id);
|
|
world.bodyOverlapKeeper.set(bi.id, bj.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sphereSphere(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
if (justTest) {
|
|
return xi.distanceSquared(xj) < (si.radius + sj.radius) ** 2;
|
|
}
|
|
const contactEq = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
xj.vsub(xi, contactEq.ni);
|
|
contactEq.ni.normalize();
|
|
contactEq.ri.copy(contactEq.ni);
|
|
contactEq.rj.copy(contactEq.ni);
|
|
contactEq.ri.scale(si.radius, contactEq.ri);
|
|
contactEq.rj.scale(-sj.radius, contactEq.rj);
|
|
contactEq.ri.vadd(xi, contactEq.ri);
|
|
contactEq.ri.vsub(bi.position, contactEq.ri);
|
|
contactEq.rj.vadd(xj, contactEq.rj);
|
|
contactEq.rj.vsub(bj.position, contactEq.rj);
|
|
this.result.push(contactEq);
|
|
this.createFrictionEquationsFromContact(contactEq, this.frictionResult);
|
|
}
|
|
spherePlane(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ni.set(0, 0, 1);
|
|
qj.vmult(r.ni, r.ni);
|
|
r.ni.negate(r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(si.radius, r.ri);
|
|
xi.vsub(xj, point_on_plane_to_sphere);
|
|
r.ni.scale(r.ni.dot(point_on_plane_to_sphere), plane_to_sphere_ortho);
|
|
point_on_plane_to_sphere.vsub(plane_to_sphere_ortho, r.rj);
|
|
if (-point_on_plane_to_sphere.dot(r.ni) <= si.radius) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const ri = r.ri;
|
|
const rj = r.rj;
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
boxBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
sj.convexPolyhedronRepresentation.material = sj.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
|
|
return this.convexConvex(si.convexPolyhedronRepresentation, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
}
|
|
sphereBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
const v3pool = this.v3pool;
|
|
const sides = sphereBox_sides;
|
|
xi.vsub(xj, box_to_sphere);
|
|
sj.getSideNormals(sides, qj);
|
|
const R = si.radius;
|
|
let found = false;
|
|
const side_ns = sphereBox_side_ns;
|
|
const side_ns1 = sphereBox_side_ns1;
|
|
const side_ns2 = sphereBox_side_ns2;
|
|
let side_h = null;
|
|
let side_penetrations = 0;
|
|
let side_dot1 = 0;
|
|
let side_dot2 = 0;
|
|
let side_distance = null;
|
|
for (let idx = 0, nsides = sides.length; idx !== nsides && found === false; idx++) {
|
|
const ns = sphereBox_ns;
|
|
ns.copy(sides[idx]);
|
|
const h = ns.length();
|
|
ns.normalize();
|
|
const dot = box_to_sphere.dot(ns);
|
|
if (dot < h + R && dot > 0) {
|
|
const ns1 = sphereBox_ns1;
|
|
const ns2 = sphereBox_ns2;
|
|
ns1.copy(sides[(idx + 1) % 3]);
|
|
ns2.copy(sides[(idx + 2) % 3]);
|
|
const h1 = ns1.length();
|
|
const h2 = ns2.length();
|
|
ns1.normalize();
|
|
ns2.normalize();
|
|
const dot1 = box_to_sphere.dot(ns1);
|
|
const dot2 = box_to_sphere.dot(ns2);
|
|
if (dot1 < h1 && dot1 > -h1 && dot2 < h2 && dot2 > -h2) {
|
|
const dist2 = Math.abs(dot - h - R);
|
|
if (side_distance === null || dist2 < side_distance) {
|
|
side_distance = dist2;
|
|
side_dot1 = dot1;
|
|
side_dot2 = dot2;
|
|
side_h = h;
|
|
side_ns.copy(ns);
|
|
side_ns1.copy(ns1);
|
|
side_ns2.copy(ns2);
|
|
side_penetrations++;
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (side_penetrations) {
|
|
found = true;
|
|
const r2 = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
side_ns.scale(-R, r2.ri);
|
|
r2.ni.copy(side_ns);
|
|
r2.ni.negate(r2.ni);
|
|
side_ns.scale(side_h, side_ns);
|
|
side_ns1.scale(side_dot1, side_ns1);
|
|
side_ns.vadd(side_ns1, side_ns);
|
|
side_ns2.scale(side_dot2, side_ns2);
|
|
side_ns.vadd(side_ns2, r2.rj);
|
|
r2.ri.vadd(xi, r2.ri);
|
|
r2.ri.vsub(bi.position, r2.ri);
|
|
r2.rj.vadd(xj, r2.rj);
|
|
r2.rj.vsub(bj.position, r2.rj);
|
|
this.result.push(r2);
|
|
this.createFrictionEquationsFromContact(r2, this.frictionResult);
|
|
}
|
|
let rj = v3pool.get();
|
|
const sphere_to_corner = sphereBox_sphere_to_corner;
|
|
for (let j = 0; j !== 2 && !found; j++) {
|
|
for (let k = 0; k !== 2 && !found; k++) {
|
|
for (let l = 0; l !== 2 && !found; l++) {
|
|
rj.set(0, 0, 0);
|
|
if (j) {
|
|
rj.vadd(sides[0], rj);
|
|
} else {
|
|
rj.vsub(sides[0], rj);
|
|
}
|
|
if (k) {
|
|
rj.vadd(sides[1], rj);
|
|
} else {
|
|
rj.vsub(sides[1], rj);
|
|
}
|
|
if (l) {
|
|
rj.vadd(sides[2], rj);
|
|
} else {
|
|
rj.vsub(sides[2], rj);
|
|
}
|
|
xj.vadd(rj, sphere_to_corner);
|
|
sphere_to_corner.vsub(xi, sphere_to_corner);
|
|
if (sphere_to_corner.lengthSquared() < R * R) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
const r2 = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r2.ri.copy(sphere_to_corner);
|
|
r2.ri.normalize();
|
|
r2.ni.copy(r2.ri);
|
|
r2.ri.scale(R, r2.ri);
|
|
r2.rj.copy(rj);
|
|
r2.ri.vadd(xi, r2.ri);
|
|
r2.ri.vsub(bi.position, r2.ri);
|
|
r2.rj.vadd(xj, r2.rj);
|
|
r2.rj.vsub(bj.position, r2.rj);
|
|
this.result.push(r2);
|
|
this.createFrictionEquationsFromContact(r2, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
v3pool.release(rj);
|
|
rj = null;
|
|
const edgeTangent = v3pool.get();
|
|
const edgeCenter = v3pool.get();
|
|
const r = v3pool.get();
|
|
const orthogonal = v3pool.get();
|
|
const dist = v3pool.get();
|
|
const Nsides = sides.length;
|
|
for (let j = 0; j !== Nsides && !found; j++) {
|
|
for (let k = 0; k !== Nsides && !found; k++) {
|
|
if (j % 3 !== k % 3) {
|
|
sides[k].cross(sides[j], edgeTangent);
|
|
edgeTangent.normalize();
|
|
sides[j].vadd(sides[k], edgeCenter);
|
|
r.copy(xi);
|
|
r.vsub(edgeCenter, r);
|
|
r.vsub(xj, r);
|
|
const orthonorm = r.dot(edgeTangent);
|
|
edgeTangent.scale(orthonorm, orthogonal);
|
|
let l = 0;
|
|
while (l === j % 3 || l === k % 3) {
|
|
l++;
|
|
}
|
|
dist.copy(xi);
|
|
dist.vsub(orthogonal, dist);
|
|
dist.vsub(edgeCenter, dist);
|
|
dist.vsub(xj, dist);
|
|
const tdist = Math.abs(orthonorm);
|
|
const ndist = dist.length();
|
|
if (tdist < sides[l].length() && ndist < R) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
const res = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
edgeCenter.vadd(orthogonal, res.rj);
|
|
res.rj.copy(res.rj);
|
|
dist.negate(res.ni);
|
|
res.ni.normalize();
|
|
res.ri.copy(res.rj);
|
|
res.ri.vadd(xj, res.ri);
|
|
res.ri.vsub(xi, res.ri);
|
|
res.ri.normalize();
|
|
res.ri.scale(R, res.ri);
|
|
res.ri.vadd(xi, res.ri);
|
|
res.ri.vsub(bi.position, res.ri);
|
|
res.rj.vadd(xj, res.rj);
|
|
res.rj.vsub(bj.position, res.rj);
|
|
this.result.push(res);
|
|
this.createFrictionEquationsFromContact(res, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
v3pool.release(edgeTangent, edgeCenter, r, orthogonal, dist);
|
|
}
|
|
planeBox(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
sj.convexPolyhedronRepresentation.material = sj.material;
|
|
sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
|
|
sj.convexPolyhedronRepresentation.id = sj.id;
|
|
return this.planeConvex(si, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
}
|
|
convexConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest, faceListA, faceListB) {
|
|
const sepAxis = convexConvex_sepAxis;
|
|
if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) {
|
|
return;
|
|
}
|
|
if (si.findSeparatingAxis(sj, xi, qi, xj, qj, sepAxis, faceListA, faceListB)) {
|
|
const res = [];
|
|
const q = convexConvex_q;
|
|
si.clipAgainstHull(xi, qi, sj, xj, qj, sepAxis, -100, 100, res);
|
|
let numContacts = 0;
|
|
for (let j = 0; j !== res.length; j++) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
const ri = r.ri;
|
|
const rj = r.rj;
|
|
sepAxis.negate(r.ni);
|
|
res[j].normal.negate(q);
|
|
q.scale(res[j].depth, q);
|
|
res[j].point.vadd(q, ri);
|
|
rj.copy(res[j].point);
|
|
ri.vsub(xi, ri);
|
|
rj.vsub(xj, rj);
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
numContacts++;
|
|
if (!this.enableFrictionReduction) {
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
if (this.enableFrictionReduction && numContacts) {
|
|
this.createFrictionFromAverage(numContacts);
|
|
}
|
|
}
|
|
}
|
|
sphereConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
const v3pool = this.v3pool;
|
|
xi.vsub(xj, convex_to_sphere);
|
|
const normals = sj.faceNormals;
|
|
const faces = sj.faces;
|
|
const verts = sj.vertices;
|
|
const R = si.radius;
|
|
let found = false;
|
|
for (let i = 0; i !== verts.length; i++) {
|
|
const v = verts[i];
|
|
const worldCorner = sphereConvex_worldCorner;
|
|
qj.vmult(v, worldCorner);
|
|
xj.vadd(worldCorner, worldCorner);
|
|
const sphere_to_corner = sphereConvex_sphereToCorner;
|
|
worldCorner.vsub(xi, sphere_to_corner);
|
|
if (sphere_to_corner.lengthSquared() < R * R) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ri.copy(sphere_to_corner);
|
|
r.ri.normalize();
|
|
r.ni.copy(r.ri);
|
|
r.ri.scale(R, r.ri);
|
|
worldCorner.vsub(xj, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
return;
|
|
}
|
|
}
|
|
for (let i = 0, nfaces = faces.length; i !== nfaces && found === false; i++) {
|
|
const normal = normals[i];
|
|
const face = faces[i];
|
|
const worldNormal = sphereConvex_worldNormal;
|
|
qj.vmult(normal, worldNormal);
|
|
const worldPoint = sphereConvex_worldPoint;
|
|
qj.vmult(verts[face[0]], worldPoint);
|
|
worldPoint.vadd(xj, worldPoint);
|
|
const worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane;
|
|
worldNormal.scale(-R, worldSpherePointClosestToPlane);
|
|
xi.vadd(worldSpherePointClosestToPlane, worldSpherePointClosestToPlane);
|
|
const penetrationVec = sphereConvex_penetrationVec;
|
|
worldSpherePointClosestToPlane.vsub(worldPoint, penetrationVec);
|
|
const penetration = penetrationVec.dot(worldNormal);
|
|
const worldPointToSphere = sphereConvex_sphereToWorldPoint;
|
|
xi.vsub(worldPoint, worldPointToSphere);
|
|
if (penetration < 0 && worldPointToSphere.dot(worldNormal) > 0) {
|
|
const faceVerts = [];
|
|
for (let j = 0, Nverts = face.length; j !== Nverts; j++) {
|
|
const worldVertex = v3pool.get();
|
|
qj.vmult(verts[face[j]], worldVertex);
|
|
xj.vadd(worldVertex, worldVertex);
|
|
faceVerts.push(worldVertex);
|
|
}
|
|
if (pointInPolygon(faceVerts, worldNormal, xi)) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
found = true;
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
worldNormal.scale(-R, r.ri);
|
|
worldNormal.negate(r.ni);
|
|
const penetrationVec2 = v3pool.get();
|
|
worldNormal.scale(-penetration, penetrationVec2);
|
|
const penetrationSpherePoint = v3pool.get();
|
|
worldNormal.scale(-R, penetrationSpherePoint);
|
|
xi.vsub(xj, r.rj);
|
|
r.rj.vadd(penetrationSpherePoint, r.rj);
|
|
r.rj.vadd(penetrationVec2, r.rj);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
v3pool.release(penetrationVec2);
|
|
v3pool.release(penetrationSpherePoint);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
for (let j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) {
|
|
v3pool.release(faceVerts[j]);
|
|
}
|
|
return;
|
|
} else {
|
|
for (let j = 0; j !== face.length; j++) {
|
|
const v12 = v3pool.get();
|
|
const v22 = v3pool.get();
|
|
qj.vmult(verts[face[(j + 1) % face.length]], v12);
|
|
qj.vmult(verts[face[(j + 2) % face.length]], v22);
|
|
xj.vadd(v12, v12);
|
|
xj.vadd(v22, v22);
|
|
const edge = sphereConvex_edge;
|
|
v22.vsub(v12, edge);
|
|
const edgeUnit = sphereConvex_edgeUnit;
|
|
edge.unit(edgeUnit);
|
|
const p2 = v3pool.get();
|
|
const v1_to_xi = v3pool.get();
|
|
xi.vsub(v12, v1_to_xi);
|
|
const dot = v1_to_xi.dot(edgeUnit);
|
|
edgeUnit.scale(dot, p2);
|
|
p2.vadd(v12, p2);
|
|
const xi_to_p = v3pool.get();
|
|
p2.vsub(xi, xi_to_p);
|
|
if (dot > 0 && dot * dot < edge.lengthSquared() && xi_to_p.lengthSquared() < R * R) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
p2.vsub(xj, r.rj);
|
|
p2.vsub(xi, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(R, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
for (let j2 = 0, Nfaceverts = faceVerts.length; j2 !== Nfaceverts; j2++) {
|
|
v3pool.release(faceVerts[j2]);
|
|
}
|
|
v3pool.release(v12);
|
|
v3pool.release(v22);
|
|
v3pool.release(p2);
|
|
v3pool.release(xi_to_p);
|
|
v3pool.release(v1_to_xi);
|
|
return;
|
|
}
|
|
v3pool.release(v12);
|
|
v3pool.release(v22);
|
|
v3pool.release(p2);
|
|
v3pool.release(xi_to_p);
|
|
v3pool.release(v1_to_xi);
|
|
}
|
|
}
|
|
for (let j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) {
|
|
v3pool.release(faceVerts[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
planeConvex(planeShape, convexShape, planePosition, convexPosition, planeQuat, convexQuat, planeBody, convexBody, si, sj, justTest) {
|
|
const worldVertex = planeConvex_v;
|
|
const worldNormal = planeConvex_normal;
|
|
worldNormal.set(0, 0, 1);
|
|
planeQuat.vmult(worldNormal, worldNormal);
|
|
let numContacts = 0;
|
|
const relpos2 = planeConvex_relpos;
|
|
for (let i = 0; i !== convexShape.vertices.length; i++) {
|
|
worldVertex.copy(convexShape.vertices[i]);
|
|
convexQuat.vmult(worldVertex, worldVertex);
|
|
convexPosition.vadd(worldVertex, worldVertex);
|
|
worldVertex.vsub(planePosition, relpos2);
|
|
const dot = worldNormal.dot(relpos2);
|
|
if (dot <= 0) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape, si, sj);
|
|
const projected = planeConvex_projected;
|
|
worldNormal.scale(worldNormal.dot(relpos2), projected);
|
|
worldVertex.vsub(projected, projected);
|
|
projected.vsub(planePosition, r.ri);
|
|
r.ni.copy(worldNormal);
|
|
worldVertex.vsub(convexPosition, r.rj);
|
|
r.ri.vadd(planePosition, r.ri);
|
|
r.ri.vsub(planeBody.position, r.ri);
|
|
r.rj.vadd(convexPosition, r.rj);
|
|
r.rj.vsub(convexBody.position, r.rj);
|
|
this.result.push(r);
|
|
numContacts++;
|
|
if (!this.enableFrictionReduction) {
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
if (this.enableFrictionReduction && numContacts) {
|
|
this.createFrictionFromAverage(numContacts);
|
|
}
|
|
}
|
|
boxConvex(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexConvex(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
}
|
|
sphereHeightfield(sphereShape, hfShape, spherePos, hfPos, sphereQuat, hfQuat, sphereBody, hfBody, rsi, rsj, justTest) {
|
|
const data = hfShape.data;
|
|
const radius = sphereShape.radius;
|
|
const w2 = hfShape.elementSize;
|
|
const worldPillarOffset2 = sphereHeightfield_tmp2;
|
|
const localSpherePos = sphereHeightfield_tmp1;
|
|
Transform.pointToLocalFrame(hfPos, hfQuat, spherePos, localSpherePos);
|
|
let iMinX = Math.floor((localSpherePos.x - radius) / w2) - 1;
|
|
let iMaxX = Math.ceil((localSpherePos.x + radius) / w2) + 1;
|
|
let iMinY = Math.floor((localSpherePos.y - radius) / w2) - 1;
|
|
let iMaxY = Math.ceil((localSpherePos.y + radius) / w2) + 1;
|
|
if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) {
|
|
return;
|
|
}
|
|
if (iMinX < 0) {
|
|
iMinX = 0;
|
|
}
|
|
if (iMaxX < 0) {
|
|
iMaxX = 0;
|
|
}
|
|
if (iMinY < 0) {
|
|
iMinY = 0;
|
|
}
|
|
if (iMaxY < 0) {
|
|
iMaxY = 0;
|
|
}
|
|
if (iMinX >= data.length) {
|
|
iMinX = data.length - 1;
|
|
}
|
|
if (iMaxX >= data.length) {
|
|
iMaxX = data.length - 1;
|
|
}
|
|
if (iMaxY >= data[0].length) {
|
|
iMaxY = data[0].length - 1;
|
|
}
|
|
if (iMinY >= data[0].length) {
|
|
iMinY = data[0].length - 1;
|
|
}
|
|
const minMax = [];
|
|
hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
|
|
const min = minMax[0];
|
|
const max = minMax[1];
|
|
if (localSpherePos.z - radius > max || localSpherePos.z + radius < min) {
|
|
return;
|
|
}
|
|
const result = this.result;
|
|
for (let i = iMinX; i < iMaxX; i++) {
|
|
for (let j = iMinY; j < iMaxY; j++) {
|
|
const numContactsBefore = result.length;
|
|
let intersecting = false;
|
|
hfShape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset2);
|
|
if (spherePos.distanceTo(worldPillarOffset2) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
|
|
intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset2, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest);
|
|
}
|
|
if (justTest && intersecting) {
|
|
return true;
|
|
}
|
|
hfShape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset2);
|
|
if (spherePos.distanceTo(worldPillarOffset2) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
|
|
intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset2, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest);
|
|
}
|
|
if (justTest && intersecting) {
|
|
return true;
|
|
}
|
|
const numContacts = result.length - numContactsBefore;
|
|
if (numContacts > 2) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
boxHeightfield(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexHeightfield(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
}
|
|
convexHeightfield(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest) {
|
|
const data = hfShape.data;
|
|
const w2 = hfShape.elementSize;
|
|
const radius = convexShape.boundingSphereRadius;
|
|
const worldPillarOffset2 = convexHeightfield_tmp2;
|
|
const faceList = convexHeightfield_faceList;
|
|
const localConvexPos = convexHeightfield_tmp1;
|
|
Transform.pointToLocalFrame(hfPos, hfQuat, convexPos, localConvexPos);
|
|
let iMinX = Math.floor((localConvexPos.x - radius) / w2) - 1;
|
|
let iMaxX = Math.ceil((localConvexPos.x + radius) / w2) + 1;
|
|
let iMinY = Math.floor((localConvexPos.y - radius) / w2) - 1;
|
|
let iMaxY = Math.ceil((localConvexPos.y + radius) / w2) + 1;
|
|
if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) {
|
|
return;
|
|
}
|
|
if (iMinX < 0) {
|
|
iMinX = 0;
|
|
}
|
|
if (iMaxX < 0) {
|
|
iMaxX = 0;
|
|
}
|
|
if (iMinY < 0) {
|
|
iMinY = 0;
|
|
}
|
|
if (iMaxY < 0) {
|
|
iMaxY = 0;
|
|
}
|
|
if (iMinX >= data.length) {
|
|
iMinX = data.length - 1;
|
|
}
|
|
if (iMaxX >= data.length) {
|
|
iMaxX = data.length - 1;
|
|
}
|
|
if (iMaxY >= data[0].length) {
|
|
iMaxY = data[0].length - 1;
|
|
}
|
|
if (iMinY >= data[0].length) {
|
|
iMinY = data[0].length - 1;
|
|
}
|
|
const minMax = [];
|
|
hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
|
|
const min = minMax[0];
|
|
const max = minMax[1];
|
|
if (localConvexPos.z - radius > max || localConvexPos.z + radius < min) {
|
|
return;
|
|
}
|
|
for (let i = iMinX; i < iMaxX; i++) {
|
|
for (let j = iMinY; j < iMaxY; j++) {
|
|
let intersecting = false;
|
|
hfShape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset2);
|
|
if (convexPos.distanceTo(worldPillarOffset2) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
|
|
intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset2, convexQuat, hfQuat, convexBody, hfBody, null, null, justTest, faceList, null);
|
|
}
|
|
if (justTest && intersecting) {
|
|
return true;
|
|
}
|
|
hfShape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset2);
|
|
if (convexPos.distanceTo(worldPillarOffset2) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
|
|
intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset2, convexQuat, hfQuat, convexBody, hfBody, null, null, justTest, faceList, null);
|
|
}
|
|
if (justTest && intersecting) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sphereParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
const normal = particleSphere_normal;
|
|
normal.set(0, 0, 1);
|
|
xi.vsub(xj, normal);
|
|
const lengthSquared = normal.lengthSquared();
|
|
if (lengthSquared <= sj.radius * sj.radius) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
normal.normalize();
|
|
r.rj.copy(normal);
|
|
r.rj.scale(sj.radius, r.rj);
|
|
r.ni.copy(normal);
|
|
r.ni.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
planeParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
const normal = particlePlane_normal;
|
|
normal.set(0, 0, 1);
|
|
bj.quaternion.vmult(normal, normal);
|
|
const relpos2 = particlePlane_relpos;
|
|
xi.vsub(bj.position, relpos2);
|
|
const dot = normal.dot(relpos2);
|
|
if (dot <= 0) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ni.copy(normal);
|
|
r.ni.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
const projected = particlePlane_projected;
|
|
normal.scale(normal.dot(xi), projected);
|
|
xi.vsub(projected, projected);
|
|
r.rj.copy(projected);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
boxParticle(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexParticle(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
}
|
|
convexParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
let penetratedFaceIndex = -1;
|
|
const penetratedFaceNormal = convexParticle_penetratedFaceNormal;
|
|
const worldPenetrationVec = convexParticle_worldPenetrationVec;
|
|
let minPenetration = null;
|
|
const local = convexParticle_local;
|
|
local.copy(xi);
|
|
local.vsub(xj, local);
|
|
qj.conjugate(cqj);
|
|
cqj.vmult(local, local);
|
|
if (sj.pointIsInside(local)) {
|
|
if (sj.worldVerticesNeedsUpdate) {
|
|
sj.computeWorldVertices(xj, qj);
|
|
}
|
|
if (sj.worldFaceNormalsNeedsUpdate) {
|
|
sj.computeWorldFaceNormals(qj);
|
|
}
|
|
for (let i = 0, nfaces = sj.faces.length; i !== nfaces; i++) {
|
|
const verts = [sj.worldVertices[sj.faces[i][0]]];
|
|
const normal = sj.worldFaceNormals[i];
|
|
xi.vsub(verts[0], convexParticle_vertexToParticle);
|
|
const penetration = -normal.dot(convexParticle_vertexToParticle);
|
|
if (minPenetration === null || Math.abs(penetration) < Math.abs(minPenetration)) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
minPenetration = penetration;
|
|
penetratedFaceIndex = i;
|
|
penetratedFaceNormal.copy(normal);
|
|
}
|
|
}
|
|
if (penetratedFaceIndex !== -1) {
|
|
const r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
penetratedFaceNormal.scale(minPenetration, worldPenetrationVec);
|
|
worldPenetrationVec.vadd(xi, worldPenetrationVec);
|
|
worldPenetrationVec.vsub(xj, worldPenetrationVec);
|
|
r.rj.copy(worldPenetrationVec);
|
|
penetratedFaceNormal.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
const ri = r.ri;
|
|
const rj = r.rj;
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
} else {
|
|
console.warn("Point found inside convex, but did not find penetrating face!");
|
|
}
|
|
}
|
|
}
|
|
heightfieldCylinder(hfShape, convexShape, hfPos, convexPos, hfQuat, convexQuat, hfBody, convexBody, rsi, rsj, justTest) {
|
|
return this.convexHeightfield(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest);
|
|
}
|
|
particleCylinder(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
return this.convexParticle(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest);
|
|
}
|
|
sphereTrimesh(sphereShape, trimeshShape, spherePos, trimeshPos, sphereQuat, trimeshQuat, sphereBody, trimeshBody, rsi, rsj, justTest) {
|
|
const edgeVertexA = sphereTrimesh_edgeVertexA;
|
|
const edgeVertexB = sphereTrimesh_edgeVertexB;
|
|
const edgeVector = sphereTrimesh_edgeVector;
|
|
const edgeVectorUnit = sphereTrimesh_edgeVectorUnit;
|
|
const localSpherePos = sphereTrimesh_localSpherePos;
|
|
const tmp3 = sphereTrimesh_tmp;
|
|
const localSphereAABB = sphereTrimesh_localSphereAABB;
|
|
const v22 = sphereTrimesh_v2;
|
|
const relpos2 = sphereTrimesh_relpos;
|
|
const triangles = sphereTrimesh_triangles;
|
|
Transform.pointToLocalFrame(trimeshPos, trimeshQuat, spherePos, localSpherePos);
|
|
const sphereRadius = sphereShape.radius;
|
|
localSphereAABB.lowerBound.set(localSpherePos.x - sphereRadius, localSpherePos.y - sphereRadius, localSpherePos.z - sphereRadius);
|
|
localSphereAABB.upperBound.set(localSpherePos.x + sphereRadius, localSpherePos.y + sphereRadius, localSpherePos.z + sphereRadius);
|
|
trimeshShape.getTrianglesInAABB(localSphereAABB, triangles);
|
|
const v = sphereTrimesh_v;
|
|
const radiusSquared = sphereShape.radius * sphereShape.radius;
|
|
for (let i = 0; i < triangles.length; i++) {
|
|
for (let j = 0; j < 3; j++) {
|
|
trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], v);
|
|
v.vsub(localSpherePos, relpos2);
|
|
if (relpos2.lengthSquared() <= radiusSquared) {
|
|
v22.copy(v);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v22, v);
|
|
v.vsub(spherePos, relpos2);
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
let r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
r.ni.copy(relpos2);
|
|
r.ni.normalize();
|
|
r.ri.copy(r.ni);
|
|
r.ri.scale(sphereShape.radius, r.ri);
|
|
r.ri.vadd(spherePos, r.ri);
|
|
r.ri.vsub(sphereBody.position, r.ri);
|
|
r.rj.copy(v);
|
|
r.rj.vsub(trimeshBody.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0; i < triangles.length; i++) {
|
|
for (let j = 0; j < 3; j++) {
|
|
trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], edgeVertexA);
|
|
trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + (j + 1) % 3], edgeVertexB);
|
|
edgeVertexB.vsub(edgeVertexA, edgeVector);
|
|
localSpherePos.vsub(edgeVertexB, tmp3);
|
|
const positionAlongEdgeB = tmp3.dot(edgeVector);
|
|
localSpherePos.vsub(edgeVertexA, tmp3);
|
|
let positionAlongEdgeA = tmp3.dot(edgeVector);
|
|
if (positionAlongEdgeA > 0 && positionAlongEdgeB < 0) {
|
|
localSpherePos.vsub(edgeVertexA, tmp3);
|
|
edgeVectorUnit.copy(edgeVector);
|
|
edgeVectorUnit.normalize();
|
|
positionAlongEdgeA = tmp3.dot(edgeVectorUnit);
|
|
edgeVectorUnit.scale(positionAlongEdgeA, tmp3);
|
|
tmp3.vadd(edgeVertexA, tmp3);
|
|
const dist = tmp3.distanceTo(localSpherePos);
|
|
if (dist < sphereShape.radius) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
tmp3.vsub(localSpherePos, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(sphereShape.radius, r.ri);
|
|
r.ri.vadd(spherePos, r.ri);
|
|
r.ri.vsub(sphereBody.position, r.ri);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp3, tmp3);
|
|
tmp3.vsub(trimeshBody.position, r.rj);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const va2 = sphereTrimesh_va;
|
|
const vb2 = sphereTrimesh_vb;
|
|
const vc2 = sphereTrimesh_vc;
|
|
const normal = sphereTrimesh_normal;
|
|
for (let i = 0, N = triangles.length; i !== N; i++) {
|
|
trimeshShape.getTriangleVertices(triangles[i], va2, vb2, vc2);
|
|
trimeshShape.getNormal(triangles[i], normal);
|
|
localSpherePos.vsub(va2, tmp3);
|
|
let dist = tmp3.dot(normal);
|
|
normal.scale(dist, tmp3);
|
|
localSpherePos.vsub(tmp3, tmp3);
|
|
dist = tmp3.distanceTo(localSpherePos);
|
|
if (Ray2.pointInTriangle(tmp3, va2, vb2, vc2) && dist < sphereShape.radius) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
let r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
tmp3.vsub(localSpherePos, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(sphereShape.radius, r.ri);
|
|
r.ri.vadd(spherePos, r.ri);
|
|
r.ri.vsub(sphereBody.position, r.ri);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp3, tmp3);
|
|
tmp3.vsub(trimeshBody.position, r.rj);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
triangles.length = 0;
|
|
}
|
|
planeTrimesh(planeShape, trimeshShape, planePos, trimeshPos, planeQuat, trimeshQuat, planeBody, trimeshBody, rsi, rsj, justTest) {
|
|
const v = new Vec3();
|
|
const normal = planeTrimesh_normal;
|
|
normal.set(0, 0, 1);
|
|
planeQuat.vmult(normal, normal);
|
|
for (let i = 0; i < trimeshShape.vertices.length / 3; i++) {
|
|
trimeshShape.getVertex(i, v);
|
|
const v22 = new Vec3();
|
|
v22.copy(v);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v22, v);
|
|
const relpos2 = planeTrimesh_relpos;
|
|
v.vsub(planePos, relpos2);
|
|
const dot = normal.dot(relpos2);
|
|
if (dot <= 0) {
|
|
if (justTest) {
|
|
return true;
|
|
}
|
|
const r = this.createContactEquation(planeBody, trimeshBody, planeShape, trimeshShape, rsi, rsj);
|
|
r.ni.copy(normal);
|
|
const projected = planeTrimesh_projected;
|
|
normal.scale(relpos2.dot(normal), projected);
|
|
v.vsub(projected, projected);
|
|
r.ri.copy(projected);
|
|
r.ri.vsub(planeBody.position, r.ri);
|
|
r.rj.copy(v);
|
|
r.rj.vsub(trimeshBody.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var averageNormal = new Vec3();
|
|
var averageContactPointA = new Vec3();
|
|
var averageContactPointB = new Vec3();
|
|
var tmpVec1 = new Vec3();
|
|
var tmpVec2 = new Vec3();
|
|
var tmpQuat1 = new Quaternion2();
|
|
var tmpQuat2 = new Quaternion2();
|
|
var planeTrimesh_normal = new Vec3();
|
|
var planeTrimesh_relpos = new Vec3();
|
|
var planeTrimesh_projected = new Vec3();
|
|
var sphereTrimesh_normal = new Vec3();
|
|
var sphereTrimesh_relpos = new Vec3();
|
|
var sphereTrimesh_v = new Vec3();
|
|
var sphereTrimesh_v2 = new Vec3();
|
|
var sphereTrimesh_edgeVertexA = new Vec3();
|
|
var sphereTrimesh_edgeVertexB = new Vec3();
|
|
var sphereTrimesh_edgeVector = new Vec3();
|
|
var sphereTrimesh_edgeVectorUnit = new Vec3();
|
|
var sphereTrimesh_localSpherePos = new Vec3();
|
|
var sphereTrimesh_tmp = new Vec3();
|
|
var sphereTrimesh_va = new Vec3();
|
|
var sphereTrimesh_vb = new Vec3();
|
|
var sphereTrimesh_vc = new Vec3();
|
|
var sphereTrimesh_localSphereAABB = new AABB();
|
|
var sphereTrimesh_triangles = [];
|
|
var point_on_plane_to_sphere = new Vec3();
|
|
var plane_to_sphere_ortho = new Vec3();
|
|
var pointInPolygon_edge = new Vec3();
|
|
var pointInPolygon_edge_x_normal = new Vec3();
|
|
var pointInPolygon_vtp = new Vec3();
|
|
function pointInPolygon(verts, normal, p2) {
|
|
let positiveResult = null;
|
|
const N = verts.length;
|
|
for (let i = 0; i !== N; i++) {
|
|
const v = verts[i];
|
|
const edge = pointInPolygon_edge;
|
|
verts[(i + 1) % N].vsub(v, edge);
|
|
const edge_x_normal = pointInPolygon_edge_x_normal;
|
|
edge.cross(normal, edge_x_normal);
|
|
const vertex_to_p = pointInPolygon_vtp;
|
|
p2.vsub(v, vertex_to_p);
|
|
const r = edge_x_normal.dot(vertex_to_p);
|
|
if (positiveResult === null || r > 0 && positiveResult === true || r <= 0 && positiveResult === false) {
|
|
if (positiveResult === null) {
|
|
positiveResult = r > 0;
|
|
}
|
|
continue;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
var box_to_sphere = new Vec3();
|
|
var sphereBox_ns = new Vec3();
|
|
var sphereBox_ns1 = new Vec3();
|
|
var sphereBox_ns2 = new Vec3();
|
|
var sphereBox_sides = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
|
|
var sphereBox_sphere_to_corner = new Vec3();
|
|
var sphereBox_side_ns = new Vec3();
|
|
var sphereBox_side_ns1 = new Vec3();
|
|
var sphereBox_side_ns2 = new Vec3();
|
|
var convex_to_sphere = new Vec3();
|
|
var sphereConvex_edge = new Vec3();
|
|
var sphereConvex_edgeUnit = new Vec3();
|
|
var sphereConvex_sphereToCorner = new Vec3();
|
|
var sphereConvex_worldCorner = new Vec3();
|
|
var sphereConvex_worldNormal = new Vec3();
|
|
var sphereConvex_worldPoint = new Vec3();
|
|
var sphereConvex_worldSpherePointClosestToPlane = new Vec3();
|
|
var sphereConvex_penetrationVec = new Vec3();
|
|
var sphereConvex_sphereToWorldPoint = new Vec3();
|
|
var planeConvex_v = new Vec3();
|
|
var planeConvex_normal = new Vec3();
|
|
var planeConvex_relpos = new Vec3();
|
|
var planeConvex_projected = new Vec3();
|
|
var convexConvex_sepAxis = new Vec3();
|
|
var convexConvex_q = new Vec3();
|
|
var particlePlane_normal = new Vec3();
|
|
var particlePlane_relpos = new Vec3();
|
|
var particlePlane_projected = new Vec3();
|
|
var particleSphere_normal = new Vec3();
|
|
var cqj = new Quaternion2();
|
|
var convexParticle_local = new Vec3();
|
|
var convexParticle_penetratedFaceNormal = new Vec3();
|
|
var convexParticle_vertexToParticle = new Vec3();
|
|
var convexParticle_worldPenetrationVec = new Vec3();
|
|
var convexHeightfield_tmp1 = new Vec3();
|
|
var convexHeightfield_tmp2 = new Vec3();
|
|
var convexHeightfield_faceList = [0];
|
|
var sphereHeightfield_tmp1 = new Vec3();
|
|
var sphereHeightfield_tmp2 = new Vec3();
|
|
var OverlapKeeper = class {
|
|
constructor() {
|
|
this.current = void 0;
|
|
this.previous = void 0;
|
|
this.current = [];
|
|
this.previous = [];
|
|
}
|
|
getKey(i, j) {
|
|
if (j < i) {
|
|
const temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return i << 16 | j;
|
|
}
|
|
set(i, j) {
|
|
const key = this.getKey(i, j);
|
|
const current = this.current;
|
|
let index = 0;
|
|
while (key > current[index]) {
|
|
index++;
|
|
}
|
|
if (key === current[index]) {
|
|
return;
|
|
}
|
|
for (let j2 = current.length - 1; j2 >= index; j2--) {
|
|
current[j2 + 1] = current[j2];
|
|
}
|
|
current[index] = key;
|
|
}
|
|
tick() {
|
|
const tmp3 = this.current;
|
|
this.current = this.previous;
|
|
this.previous = tmp3;
|
|
this.current.length = 0;
|
|
}
|
|
getDiff(additions2, removals2) {
|
|
const a2 = this.current;
|
|
const b2 = this.previous;
|
|
const al = a2.length;
|
|
const bl = b2.length;
|
|
let j = 0;
|
|
for (let i = 0; i < al; i++) {
|
|
let found = false;
|
|
const keyA = a2[i];
|
|
while (keyA > b2[j]) {
|
|
j++;
|
|
}
|
|
found = keyA === b2[j];
|
|
if (!found) {
|
|
unpackAndPush(additions2, keyA);
|
|
}
|
|
}
|
|
j = 0;
|
|
for (let i = 0; i < bl; i++) {
|
|
let found = false;
|
|
const keyB = b2[i];
|
|
while (keyB > a2[j]) {
|
|
j++;
|
|
}
|
|
found = a2[j] === keyB;
|
|
if (!found) {
|
|
unpackAndPush(removals2, keyB);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function unpackAndPush(array, key) {
|
|
array.push((key & 4294901760) >> 16, key & 65535);
|
|
}
|
|
var TupleDictionary = class {
|
|
constructor() {
|
|
this.data = {
|
|
keys: []
|
|
};
|
|
}
|
|
get(i, j) {
|
|
if (i > j) {
|
|
const temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return this.data[i + "-" + j];
|
|
}
|
|
set(i, j, value) {
|
|
if (i > j) {
|
|
const temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
const key = i + "-" + j;
|
|
if (!this.get(i, j)) {
|
|
this.data.keys.push(key);
|
|
}
|
|
this.data[key] = value;
|
|
}
|
|
reset() {
|
|
const data = this.data;
|
|
const keys = data.keys;
|
|
while (keys.length > 0) {
|
|
const key = keys.pop();
|
|
delete data[key];
|
|
}
|
|
}
|
|
};
|
|
var World = class extends EventTarget {
|
|
constructor(options = {}) {
|
|
super();
|
|
this.dt = void 0;
|
|
this.allowSleep = void 0;
|
|
this.contacts = void 0;
|
|
this.frictionEquations = void 0;
|
|
this.quatNormalizeSkip = void 0;
|
|
this.quatNormalizeFast = void 0;
|
|
this.time = void 0;
|
|
this.stepnumber = void 0;
|
|
this.default_dt = void 0;
|
|
this.nextId = void 0;
|
|
this.gravity = void 0;
|
|
this.broadphase = void 0;
|
|
this.bodies = void 0;
|
|
this.hasActiveBodies = void 0;
|
|
this.solver = void 0;
|
|
this.constraints = void 0;
|
|
this.narrowphase = void 0;
|
|
this.collisionMatrix = void 0;
|
|
this.collisionMatrixPrevious = void 0;
|
|
this.bodyOverlapKeeper = void 0;
|
|
this.shapeOverlapKeeper = void 0;
|
|
this.materials = void 0;
|
|
this.contactmaterials = void 0;
|
|
this.contactMaterialTable = void 0;
|
|
this.defaultMaterial = void 0;
|
|
this.defaultContactMaterial = void 0;
|
|
this.doProfiling = void 0;
|
|
this.profile = void 0;
|
|
this.accumulator = void 0;
|
|
this.subsystems = void 0;
|
|
this.addBodyEvent = void 0;
|
|
this.removeBodyEvent = void 0;
|
|
this.idToBodyMap = void 0;
|
|
this.dt = -1;
|
|
this.allowSleep = !!options.allowSleep;
|
|
this.contacts = [];
|
|
this.frictionEquations = [];
|
|
this.quatNormalizeSkip = options.quatNormalizeSkip !== void 0 ? options.quatNormalizeSkip : 0;
|
|
this.quatNormalizeFast = options.quatNormalizeFast !== void 0 ? options.quatNormalizeFast : false;
|
|
this.time = 0;
|
|
this.stepnumber = 0;
|
|
this.default_dt = 1 / 60;
|
|
this.nextId = 0;
|
|
this.gravity = new Vec3();
|
|
if (options.gravity) {
|
|
this.gravity.copy(options.gravity);
|
|
}
|
|
this.broadphase = options.broadphase !== void 0 ? options.broadphase : new NaiveBroadphase();
|
|
this.bodies = [];
|
|
this.hasActiveBodies = false;
|
|
this.solver = options.solver !== void 0 ? options.solver : new GSSolver();
|
|
this.constraints = [];
|
|
this.narrowphase = new Narrowphase(this);
|
|
this.collisionMatrix = new ArrayCollisionMatrix();
|
|
this.collisionMatrixPrevious = new ArrayCollisionMatrix();
|
|
this.bodyOverlapKeeper = new OverlapKeeper();
|
|
this.shapeOverlapKeeper = new OverlapKeeper();
|
|
this.materials = [];
|
|
this.contactmaterials = [];
|
|
this.contactMaterialTable = new TupleDictionary();
|
|
this.defaultMaterial = new Material2("default");
|
|
this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, {
|
|
friction: 0.3,
|
|
restitution: 0
|
|
});
|
|
this.doProfiling = false;
|
|
this.profile = {
|
|
solve: 0,
|
|
makeContactConstraints: 0,
|
|
broadphase: 0,
|
|
integrate: 0,
|
|
narrowphase: 0
|
|
};
|
|
this.accumulator = 0;
|
|
this.subsystems = [];
|
|
this.addBodyEvent = {
|
|
type: "addBody",
|
|
body: null
|
|
};
|
|
this.removeBodyEvent = {
|
|
type: "removeBody",
|
|
body: null
|
|
};
|
|
this.idToBodyMap = {};
|
|
this.broadphase.setWorld(this);
|
|
}
|
|
getContactMaterial(m1, m2) {
|
|
return this.contactMaterialTable.get(m1.id, m2.id);
|
|
}
|
|
numObjects() {
|
|
return this.bodies.length;
|
|
}
|
|
collisionMatrixTick() {
|
|
const temp = this.collisionMatrixPrevious;
|
|
this.collisionMatrixPrevious = this.collisionMatrix;
|
|
this.collisionMatrix = temp;
|
|
this.collisionMatrix.reset();
|
|
this.bodyOverlapKeeper.tick();
|
|
this.shapeOverlapKeeper.tick();
|
|
}
|
|
addConstraint(c2) {
|
|
this.constraints.push(c2);
|
|
}
|
|
removeConstraint(c2) {
|
|
const idx = this.constraints.indexOf(c2);
|
|
if (idx !== -1) {
|
|
this.constraints.splice(idx, 1);
|
|
}
|
|
}
|
|
rayTest(from, to, result) {
|
|
if (result instanceof RaycastResult) {
|
|
this.raycastClosest(from, to, {
|
|
skipBackfaces: true
|
|
}, result);
|
|
} else {
|
|
this.raycastAll(from, to, {
|
|
skipBackfaces: true
|
|
}, result);
|
|
}
|
|
}
|
|
raycastAll(from, to, options = {}, callback) {
|
|
options.mode = Ray2.ALL;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.callback = callback;
|
|
return tmpRay.intersectWorld(this, options);
|
|
}
|
|
raycastAny(from, to, options = {}, result) {
|
|
options.mode = Ray2.ANY;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.result = result;
|
|
return tmpRay.intersectWorld(this, options);
|
|
}
|
|
raycastClosest(from, to, options = {}, result) {
|
|
options.mode = Ray2.CLOSEST;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.result = result;
|
|
return tmpRay.intersectWorld(this, options);
|
|
}
|
|
addBody(body) {
|
|
if (this.bodies.includes(body)) {
|
|
return;
|
|
}
|
|
body.index = this.bodies.length;
|
|
this.bodies.push(body);
|
|
body.world = this;
|
|
body.initPosition.copy(body.position);
|
|
body.initVelocity.copy(body.velocity);
|
|
body.timeLastSleepy = this.time;
|
|
if (body instanceof Body) {
|
|
body.initAngularVelocity.copy(body.angularVelocity);
|
|
body.initQuaternion.copy(body.quaternion);
|
|
}
|
|
this.collisionMatrix.setNumObjects(this.bodies.length);
|
|
this.addBodyEvent.body = body;
|
|
this.idToBodyMap[body.id] = body;
|
|
this.dispatchEvent(this.addBodyEvent);
|
|
}
|
|
removeBody(body) {
|
|
body.world = null;
|
|
const n = this.bodies.length - 1;
|
|
const bodies = this.bodies;
|
|
const idx = bodies.indexOf(body);
|
|
if (idx !== -1) {
|
|
bodies.splice(idx, 1);
|
|
for (let i = 0; i !== bodies.length; i++) {
|
|
bodies[i].index = i;
|
|
}
|
|
this.collisionMatrix.setNumObjects(n);
|
|
this.removeBodyEvent.body = body;
|
|
delete this.idToBodyMap[body.id];
|
|
this.dispatchEvent(this.removeBodyEvent);
|
|
}
|
|
}
|
|
getBodyById(id) {
|
|
return this.idToBodyMap[id];
|
|
}
|
|
getShapeById(id) {
|
|
const bodies = this.bodies;
|
|
for (let i = 0; i < bodies.length; i++) {
|
|
const shapes = bodies[i].shapes;
|
|
for (let j = 0; j < shapes.length; j++) {
|
|
const shape = shapes[j];
|
|
if (shape.id === id) {
|
|
return shape;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
addMaterial(m) {
|
|
this.materials.push(m);
|
|
}
|
|
addContactMaterial(cmat) {
|
|
this.contactmaterials.push(cmat);
|
|
this.contactMaterialTable.set(cmat.materials[0].id, cmat.materials[1].id, cmat);
|
|
}
|
|
step(dt, timeSinceLastCalled, maxSubSteps = 10) {
|
|
if (timeSinceLastCalled === void 0) {
|
|
this.internalStep(dt);
|
|
this.time += dt;
|
|
} else {
|
|
this.accumulator += timeSinceLastCalled;
|
|
const t0 = performance2.now();
|
|
let substeps = 0;
|
|
while (this.accumulator >= dt && substeps < maxSubSteps) {
|
|
this.internalStep(dt);
|
|
this.accumulator -= dt;
|
|
substeps++;
|
|
if (performance2.now() - t0 > dt * 1e3) {
|
|
break;
|
|
}
|
|
}
|
|
this.accumulator = this.accumulator % dt;
|
|
const t = this.accumulator / dt;
|
|
for (let j = 0; j !== this.bodies.length; j++) {
|
|
const b2 = this.bodies[j];
|
|
b2.previousPosition.lerp(b2.position, t, b2.interpolatedPosition);
|
|
b2.previousQuaternion.slerp(b2.quaternion, t, b2.interpolatedQuaternion);
|
|
b2.previousQuaternion.normalize();
|
|
}
|
|
this.time += timeSinceLastCalled;
|
|
}
|
|
}
|
|
internalStep(dt) {
|
|
this.dt = dt;
|
|
const contacts = this.contacts;
|
|
const p1 = World_step_p1;
|
|
const p2 = World_step_p2;
|
|
const N = this.numObjects();
|
|
const bodies = this.bodies;
|
|
const solver = this.solver;
|
|
const gravity = this.gravity;
|
|
const doProfiling = this.doProfiling;
|
|
const profile = this.profile;
|
|
const DYNAMIC = Body.DYNAMIC;
|
|
let profilingStart = -Infinity;
|
|
const constraints = this.constraints;
|
|
const frictionEquationPool = World_step_frictionEquationPool;
|
|
gravity.length();
|
|
const gx = gravity.x;
|
|
const gy = gravity.y;
|
|
const gz = gravity.z;
|
|
let i = 0;
|
|
if (doProfiling) {
|
|
profilingStart = performance2.now();
|
|
}
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
if (bi.type === DYNAMIC) {
|
|
const f = bi.force;
|
|
const m = bi.mass;
|
|
f.x += m * gx;
|
|
f.y += m * gy;
|
|
f.z += m * gz;
|
|
}
|
|
}
|
|
for (let i2 = 0, Nsubsystems = this.subsystems.length; i2 !== Nsubsystems; i2++) {
|
|
this.subsystems[i2].update();
|
|
}
|
|
if (doProfiling) {
|
|
profilingStart = performance2.now();
|
|
}
|
|
p1.length = 0;
|
|
p2.length = 0;
|
|
this.broadphase.collisionPairs(this, p1, p2);
|
|
if (doProfiling) {
|
|
profile.broadphase = performance2.now() - profilingStart;
|
|
}
|
|
let Nconstraints = constraints.length;
|
|
for (i = 0; i !== Nconstraints; i++) {
|
|
const c2 = constraints[i];
|
|
if (!c2.collideConnected) {
|
|
for (let j = p1.length - 1; j >= 0; j -= 1) {
|
|
if (c2.bodyA === p1[j] && c2.bodyB === p2[j] || c2.bodyB === p1[j] && c2.bodyA === p2[j]) {
|
|
p1.splice(j, 1);
|
|
p2.splice(j, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.collisionMatrixTick();
|
|
if (doProfiling) {
|
|
profilingStart = performance2.now();
|
|
}
|
|
const oldcontacts = World_step_oldContacts;
|
|
const NoldContacts = contacts.length;
|
|
for (i = 0; i !== NoldContacts; i++) {
|
|
oldcontacts.push(contacts[i]);
|
|
}
|
|
contacts.length = 0;
|
|
const NoldFrictionEquations = this.frictionEquations.length;
|
|
for (i = 0; i !== NoldFrictionEquations; i++) {
|
|
frictionEquationPool.push(this.frictionEquations[i]);
|
|
}
|
|
this.frictionEquations.length = 0;
|
|
this.narrowphase.getContacts(p1, p2, this, contacts, oldcontacts, this.frictionEquations, frictionEquationPool);
|
|
if (doProfiling) {
|
|
profile.narrowphase = performance2.now() - profilingStart;
|
|
}
|
|
if (doProfiling) {
|
|
profilingStart = performance2.now();
|
|
}
|
|
for (i = 0; i < this.frictionEquations.length; i++) {
|
|
solver.addEquation(this.frictionEquations[i]);
|
|
}
|
|
const ncontacts = contacts.length;
|
|
for (let k = 0; k !== ncontacts; k++) {
|
|
const c2 = contacts[k];
|
|
const bi = c2.bi;
|
|
const bj = c2.bj;
|
|
const si = c2.si;
|
|
const sj = c2.sj;
|
|
let cm;
|
|
if (bi.material && bj.material) {
|
|
cm = this.getContactMaterial(bi.material, bj.material) || this.defaultContactMaterial;
|
|
} else {
|
|
cm = this.defaultContactMaterial;
|
|
}
|
|
cm.friction;
|
|
if (bi.material && bj.material) {
|
|
if (bi.material.friction >= 0 && bj.material.friction >= 0) {
|
|
bi.material.friction * bj.material.friction;
|
|
}
|
|
if (bi.material.restitution >= 0 && bj.material.restitution >= 0) {
|
|
c2.restitution = bi.material.restitution * bj.material.restitution;
|
|
}
|
|
}
|
|
solver.addEquation(c2);
|
|
if (bi.allowSleep && bi.type === Body.DYNAMIC && bi.sleepState === Body.SLEEPING && bj.sleepState === Body.AWAKE && bj.type !== Body.STATIC) {
|
|
const speedSquaredB = bj.velocity.lengthSquared() + bj.angularVelocity.lengthSquared();
|
|
const speedLimitSquaredB = bj.sleepSpeedLimit ** 2;
|
|
if (speedSquaredB >= speedLimitSquaredB * 2) {
|
|
bi.wakeUpAfterNarrowphase = true;
|
|
}
|
|
}
|
|
if (bj.allowSleep && bj.type === Body.DYNAMIC && bj.sleepState === Body.SLEEPING && bi.sleepState === Body.AWAKE && bi.type !== Body.STATIC) {
|
|
const speedSquaredA = bi.velocity.lengthSquared() + bi.angularVelocity.lengthSquared();
|
|
const speedLimitSquaredA = bi.sleepSpeedLimit ** 2;
|
|
if (speedSquaredA >= speedLimitSquaredA * 2) {
|
|
bj.wakeUpAfterNarrowphase = true;
|
|
}
|
|
}
|
|
this.collisionMatrix.set(bi, bj, true);
|
|
if (!this.collisionMatrixPrevious.get(bi, bj)) {
|
|
World_step_collideEvent.body = bj;
|
|
World_step_collideEvent.contact = c2;
|
|
bi.dispatchEvent(World_step_collideEvent);
|
|
World_step_collideEvent.body = bi;
|
|
bj.dispatchEvent(World_step_collideEvent);
|
|
}
|
|
this.bodyOverlapKeeper.set(bi.id, bj.id);
|
|
this.shapeOverlapKeeper.set(si.id, sj.id);
|
|
}
|
|
this.emitContactEvents();
|
|
if (doProfiling) {
|
|
profile.makeContactConstraints = performance2.now() - profilingStart;
|
|
profilingStart = performance2.now();
|
|
}
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
if (bi.wakeUpAfterNarrowphase) {
|
|
bi.wakeUp();
|
|
bi.wakeUpAfterNarrowphase = false;
|
|
}
|
|
}
|
|
Nconstraints = constraints.length;
|
|
for (i = 0; i !== Nconstraints; i++) {
|
|
const c2 = constraints[i];
|
|
c2.update();
|
|
for (let j = 0, Neq = c2.equations.length; j !== Neq; j++) {
|
|
const eq = c2.equations[j];
|
|
solver.addEquation(eq);
|
|
}
|
|
}
|
|
solver.solve(dt, this);
|
|
if (doProfiling) {
|
|
profile.solve = performance2.now() - profilingStart;
|
|
}
|
|
solver.removeAllEquations();
|
|
const pow = Math.pow;
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
if (bi.type & DYNAMIC) {
|
|
const ld = pow(1 - bi.linearDamping, dt);
|
|
const v = bi.velocity;
|
|
v.scale(ld, v);
|
|
const av = bi.angularVelocity;
|
|
if (av) {
|
|
const ad = pow(1 - bi.angularDamping, dt);
|
|
av.scale(ad, av);
|
|
}
|
|
}
|
|
}
|
|
this.dispatchEvent(World_step_preStepEvent);
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
if (bi.preStep) {
|
|
bi.preStep.call(bi);
|
|
}
|
|
}
|
|
if (doProfiling) {
|
|
profilingStart = performance2.now();
|
|
}
|
|
const stepnumber = this.stepnumber;
|
|
const quatNormalize = stepnumber % (this.quatNormalizeSkip + 1) === 0;
|
|
const quatNormalizeFast = this.quatNormalizeFast;
|
|
for (i = 0; i !== N; i++) {
|
|
bodies[i].integrate(dt, quatNormalize, quatNormalizeFast);
|
|
}
|
|
this.clearForces();
|
|
this.broadphase.dirty = true;
|
|
if (doProfiling) {
|
|
profile.integrate = performance2.now() - profilingStart;
|
|
}
|
|
this.stepnumber += 1;
|
|
this.dispatchEvent(World_step_postStepEvent);
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
const postStep = bi.postStep;
|
|
if (postStep) {
|
|
postStep.call(bi);
|
|
}
|
|
}
|
|
let hasActiveBodies = true;
|
|
if (this.allowSleep) {
|
|
hasActiveBodies = false;
|
|
for (i = 0; i !== N; i++) {
|
|
const bi = bodies[i];
|
|
bi.sleepTick(this.time);
|
|
if (bi.sleepState !== Body.SLEEPING) {
|
|
hasActiveBodies = true;
|
|
}
|
|
}
|
|
}
|
|
this.hasActiveBodies = hasActiveBodies;
|
|
}
|
|
emitContactEvents() {
|
|
const hasBeginContact = this.hasAnyEventListener("beginContact");
|
|
const hasEndContact = this.hasAnyEventListener("endContact");
|
|
if (hasBeginContact || hasEndContact) {
|
|
this.bodyOverlapKeeper.getDiff(additions, removals);
|
|
}
|
|
if (hasBeginContact) {
|
|
for (let i = 0, l = additions.length; i < l; i += 2) {
|
|
beginContactEvent.bodyA = this.getBodyById(additions[i]);
|
|
beginContactEvent.bodyB = this.getBodyById(additions[i + 1]);
|
|
this.dispatchEvent(beginContactEvent);
|
|
}
|
|
beginContactEvent.bodyA = beginContactEvent.bodyB = null;
|
|
}
|
|
if (hasEndContact) {
|
|
for (let i = 0, l = removals.length; i < l; i += 2) {
|
|
endContactEvent.bodyA = this.getBodyById(removals[i]);
|
|
endContactEvent.bodyB = this.getBodyById(removals[i + 1]);
|
|
this.dispatchEvent(endContactEvent);
|
|
}
|
|
endContactEvent.bodyA = endContactEvent.bodyB = null;
|
|
}
|
|
additions.length = removals.length = 0;
|
|
const hasBeginShapeContact = this.hasAnyEventListener("beginShapeContact");
|
|
const hasEndShapeContact = this.hasAnyEventListener("endShapeContact");
|
|
if (hasBeginShapeContact || hasEndShapeContact) {
|
|
this.shapeOverlapKeeper.getDiff(additions, removals);
|
|
}
|
|
if (hasBeginShapeContact) {
|
|
for (let i = 0, l = additions.length; i < l; i += 2) {
|
|
const shapeA = this.getShapeById(additions[i]);
|
|
const shapeB = this.getShapeById(additions[i + 1]);
|
|
beginShapeContactEvent.shapeA = shapeA;
|
|
beginShapeContactEvent.shapeB = shapeB;
|
|
if (shapeA)
|
|
beginShapeContactEvent.bodyA = shapeA.body;
|
|
if (shapeB)
|
|
beginShapeContactEvent.bodyB = shapeB.body;
|
|
this.dispatchEvent(beginShapeContactEvent);
|
|
}
|
|
beginShapeContactEvent.bodyA = beginShapeContactEvent.bodyB = beginShapeContactEvent.shapeA = beginShapeContactEvent.shapeB = null;
|
|
}
|
|
if (hasEndShapeContact) {
|
|
for (let i = 0, l = removals.length; i < l; i += 2) {
|
|
const shapeA = this.getShapeById(removals[i]);
|
|
const shapeB = this.getShapeById(removals[i + 1]);
|
|
endShapeContactEvent.shapeA = shapeA;
|
|
endShapeContactEvent.shapeB = shapeB;
|
|
if (shapeA)
|
|
endShapeContactEvent.bodyA = shapeA.body;
|
|
if (shapeB)
|
|
endShapeContactEvent.bodyB = shapeB.body;
|
|
this.dispatchEvent(endShapeContactEvent);
|
|
}
|
|
endShapeContactEvent.bodyA = endShapeContactEvent.bodyB = endShapeContactEvent.shapeA = endShapeContactEvent.shapeB = null;
|
|
}
|
|
}
|
|
clearForces() {
|
|
const bodies = this.bodies;
|
|
const N = bodies.length;
|
|
for (let i = 0; i !== N; i++) {
|
|
const b2 = bodies[i];
|
|
b2.force;
|
|
b2.torque;
|
|
b2.force.set(0, 0, 0);
|
|
b2.torque.set(0, 0, 0);
|
|
}
|
|
}
|
|
};
|
|
new AABB();
|
|
var tmpRay = new Ray2();
|
|
var performance2 = globalThis.performance || {};
|
|
if (!performance2.now) {
|
|
let nowOffset = Date.now();
|
|
if (performance2.timing && performance2.timing.navigationStart) {
|
|
nowOffset = performance2.timing.navigationStart;
|
|
}
|
|
performance2.now = () => Date.now() - nowOffset;
|
|
}
|
|
var World_step_postStepEvent = {
|
|
type: "postStep"
|
|
};
|
|
var World_step_preStepEvent = {
|
|
type: "preStep"
|
|
};
|
|
var World_step_collideEvent = {
|
|
type: Body.COLLIDE_EVENT_NAME,
|
|
body: null,
|
|
contact: null
|
|
};
|
|
var World_step_oldContacts = [];
|
|
var World_step_frictionEquationPool = [];
|
|
var World_step_p1 = [];
|
|
var World_step_p2 = [];
|
|
var additions = [];
|
|
var removals = [];
|
|
var beginContactEvent = {
|
|
type: "beginContact",
|
|
bodyA: null,
|
|
bodyB: null
|
|
};
|
|
var endContactEvent = {
|
|
type: "endContact",
|
|
bodyA: null,
|
|
bodyB: null
|
|
};
|
|
var beginShapeContactEvent = {
|
|
type: "beginShapeContact",
|
|
bodyA: null,
|
|
bodyB: null,
|
|
shapeA: null,
|
|
shapeB: null
|
|
};
|
|
var endShapeContactEvent = {
|
|
type: "endShapeContact",
|
|
bodyA: null,
|
|
bodyB: null,
|
|
shapeA: null,
|
|
shapeB: null
|
|
};
|
|
|
|
// src/view/renderer/geometries.ts
|
|
var MATERIAL_OPTIONS = {
|
|
specular: 1515554,
|
|
color: 15790320,
|
|
shininess: 60,
|
|
flatShading: true
|
|
};
|
|
var DEFAULT_DICE_OPTIONS = {
|
|
diceColor: "#202020",
|
|
textColor: "#ffffff"
|
|
};
|
|
var DiceShape = class {
|
|
constructor(w2, h, options = {
|
|
diceColor: "#202020",
|
|
textColor: "#aaaaaa"
|
|
}) {
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.options = options;
|
|
this.scale = 50;
|
|
this.labels = [
|
|
" ",
|
|
"0",
|
|
"1",
|
|
"2",
|
|
"3",
|
|
"4",
|
|
"5",
|
|
"6",
|
|
"7",
|
|
"8",
|
|
"9",
|
|
"10",
|
|
"11",
|
|
"12",
|
|
"13",
|
|
"14",
|
|
"15",
|
|
"16",
|
|
"17",
|
|
"18",
|
|
"19",
|
|
"20"
|
|
];
|
|
this.options = {
|
|
...DEFAULT_DICE_OPTIONS,
|
|
...options
|
|
};
|
|
}
|
|
setColor({
|
|
diceColor,
|
|
textColor
|
|
}) {
|
|
this.options.diceColor = diceColor;
|
|
this.options.textColor = textColor;
|
|
}
|
|
get radius() {
|
|
return this.scale * this.scaleFactor;
|
|
}
|
|
get diceColor() {
|
|
return this.options.diceColor;
|
|
}
|
|
get textColor() {
|
|
return this.options.textColor;
|
|
}
|
|
get buffer() {
|
|
return this.geometry.geometry;
|
|
}
|
|
create() {
|
|
const geometry = this.getGeometry();
|
|
const materials = this.getMaterials();
|
|
this.geometry = new Mesh(geometry, materials);
|
|
this.geometry.receiveShadow = true;
|
|
this.geometry.castShadow = true;
|
|
this.body.position.set(0 + this.radius * 2 * Math.random(), 0 + this.radius * 2 * Math.random(), 0 + this.radius * 4);
|
|
this.body.velocity.x = 500 * Math.random() * 2 - 1;
|
|
this.body.velocity.y = 500 * Math.random() * 2 - 1;
|
|
this.body.angularVelocity.x = 100 * Math.random();
|
|
this.body.angularVelocity.y = 100 * Math.random();
|
|
}
|
|
getGeometry() {
|
|
let vectors = new Array(this.vertices.length);
|
|
for (let i = 0; i < this.vertices.length; ++i) {
|
|
vectors[i] = new Vector3().fromArray(this.vertices[i]).normalize();
|
|
}
|
|
this.chamferGeometry = this.getChamferGeometry(vectors);
|
|
let geometry = this.makeGeometry(this.chamferGeometry.vectors, this.chamferGeometry.faces);
|
|
this.shape = this.makeShape(vectors);
|
|
this.body = new Body({
|
|
mass: this.mass,
|
|
shape: this.shape
|
|
});
|
|
return geometry;
|
|
}
|
|
makeShape(vertices) {
|
|
let cv = new Array(vertices.length), cf = new Array(this.faces.length);
|
|
for (let i = 0; i < vertices.length; ++i) {
|
|
let v = vertices[i];
|
|
cv[i] = new Vec3(v.x * this.radius, v.y * this.radius, v.z * this.radius);
|
|
}
|
|
for (let i = 0; i < this.faces.length; ++i) {
|
|
cf[i] = this.faces[i].slice(0, this.faces[i].length - 1);
|
|
}
|
|
this.shapeData = { vertices: cv, faces: cf };
|
|
return new ConvexPolyhedron({ vertices: cv, faces: cf });
|
|
}
|
|
getChamferGeometry(vectors) {
|
|
let chamfer_vectors = [], chamfer_faces = [], corner_faces = new Array(vectors.length);
|
|
for (let i = 0; i < vectors.length; ++i)
|
|
corner_faces[i] = [];
|
|
for (let i = 0; i < this.faces.length; ++i) {
|
|
let ii = this.faces[i], fl = ii.length - 1;
|
|
let center_point = new Vector3();
|
|
let face = new Array(fl);
|
|
for (let j = 0; j < fl; ++j) {
|
|
let vv = vectors[ii[j]].clone();
|
|
center_point.add(vv);
|
|
corner_faces[ii[j]].push(face[j] = chamfer_vectors.push(vv) - 1);
|
|
}
|
|
center_point.divideScalar(fl);
|
|
for (let j = 0; j < fl; ++j) {
|
|
let vv = chamfer_vectors[face[j]];
|
|
vv.subVectors(vv, center_point).multiplyScalar(this.chamfer).addVectors(vv, center_point);
|
|
}
|
|
face.push(ii[fl]);
|
|
chamfer_faces.push(face);
|
|
}
|
|
for (let i = 0; i < this.faces.length - 1; ++i) {
|
|
for (let j = i + 1; j < this.faces.length; ++j) {
|
|
let pairs = [], lastm = -1;
|
|
for (let m = 0; m < this.faces[i].length - 1; ++m) {
|
|
let n = this.faces[j].indexOf(this.faces[i][m]);
|
|
if (n >= 0 && n < this.faces[j].length - 1) {
|
|
if (lastm >= 0 && m !== lastm + 1)
|
|
pairs.unshift([i, m], [j, n]);
|
|
else
|
|
pairs.push([i, m], [j, n]);
|
|
lastm = m;
|
|
}
|
|
}
|
|
if (pairs.length !== 4)
|
|
continue;
|
|
chamfer_faces.push([
|
|
chamfer_faces[pairs[0][0]][pairs[0][1]],
|
|
chamfer_faces[pairs[1][0]][pairs[1][1]],
|
|
chamfer_faces[pairs[3][0]][pairs[3][1]],
|
|
chamfer_faces[pairs[2][0]][pairs[2][1]],
|
|
-1
|
|
]);
|
|
}
|
|
}
|
|
for (let i = 0; i < corner_faces.length; ++i) {
|
|
let cf = corner_faces[i], face = [cf[0]], count = cf.length - 1;
|
|
while (count) {
|
|
for (let m = this.faces.length; m < chamfer_faces.length; ++m) {
|
|
let index = chamfer_faces[m].indexOf(face[face.length - 1]);
|
|
if (index >= 0 && index < 4) {
|
|
if (--index === -1)
|
|
index = 3;
|
|
let next_vertex = chamfer_faces[m][index];
|
|
if (cf.indexOf(next_vertex) >= 0) {
|
|
face.push(next_vertex);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
--count;
|
|
}
|
|
face.push(-1);
|
|
chamfer_faces.push(face);
|
|
}
|
|
return { vectors: chamfer_vectors, faces: chamfer_faces };
|
|
}
|
|
makeGeometry(vertices, faces) {
|
|
let geom = new BufferGeometry();
|
|
for (let i = 0; i < vertices.length; ++i) {
|
|
vertices[i] = vertices[i].multiplyScalar(this.radius);
|
|
}
|
|
let positions = [];
|
|
const normals = [];
|
|
const uvs = [];
|
|
const cb2 = new Vector3();
|
|
const ab2 = new Vector3();
|
|
let materialIndex;
|
|
let faceFirstVertexIndex = 0;
|
|
for (let i = 0; i < faces.length; ++i) {
|
|
let ii = faces[i], fl = ii.length - 1;
|
|
let aa = Math.PI * 2 / fl;
|
|
materialIndex = ii[fl] + 1;
|
|
for (let j = 0; j < fl - 2; ++j) {
|
|
positions.push(...vertices[ii[0]].toArray());
|
|
positions.push(...vertices[ii[j + 1]].toArray());
|
|
positions.push(...vertices[ii[j + 2]].toArray());
|
|
cb2.subVectors(vertices[ii[j + 2]], vertices[ii[j + 1]]);
|
|
ab2.subVectors(vertices[ii[0]], vertices[ii[j + 1]]);
|
|
cb2.cross(ab2);
|
|
cb2.normalize();
|
|
normals.push(...cb2.toArray());
|
|
normals.push(...cb2.toArray());
|
|
normals.push(...cb2.toArray());
|
|
uvs.push((Math.cos(this.af) + 1 + this.tab) / 2 / (1 + this.tab), (Math.sin(this.af) + 1 + this.tab) / 2 / (1 + this.tab));
|
|
uvs.push((Math.cos(aa * (j + 1) + this.af) + 1 + this.tab) / 2 / (1 + this.tab), (Math.sin(aa * (j + 1) + this.af) + 1 + this.tab) / 2 / (1 + this.tab));
|
|
uvs.push((Math.cos(aa * (j + 2) + this.af) + 1 + this.tab) / 2 / (1 + this.tab), (Math.sin(aa * (j + 2) + this.af) + 1 + this.tab) / 2 / (1 + this.tab));
|
|
}
|
|
let numOfVertices = (fl - 2) * 3;
|
|
for (let i2 = 0; i2 < numOfVertices / 3; i2++) {
|
|
geom.addGroup(faceFirstVertexIndex, 3, materialIndex);
|
|
faceFirstVertexIndex += 3;
|
|
}
|
|
}
|
|
geom.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
geom.setAttribute("normal", new Float32BufferAttribute(normals, 3));
|
|
geom.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
geom.boundingSphere = new Sphere(new Vector3(), this.radius);
|
|
return geom;
|
|
}
|
|
getMaterials() {
|
|
let materials = [];
|
|
for (let i = 0; i < this.labels.length; i++) {
|
|
let texture = this.createTextTexture(i);
|
|
materials.push(new MeshPhongMaterial(Object.assign({}, MATERIAL_OPTIONS, { map: texture })));
|
|
}
|
|
return materials;
|
|
}
|
|
calculateTextureSize(approx) {
|
|
return Math.max(128, Math.pow(2, Math.floor(Math.log(approx) / Math.log(2))));
|
|
}
|
|
createTextTexture(index) {
|
|
let text = this.labels[index];
|
|
if (text == void 0)
|
|
return null;
|
|
const canvas = document.createElement("canvas");
|
|
const context = canvas.getContext("2d");
|
|
const ts = this.calculateTextureSize(this.scale / 2 + this.scale * this.margin) * 2;
|
|
canvas.width = canvas.height = ts;
|
|
let fontsize = ts / (1 + 2 * this.margin);
|
|
if (this.sides == 100) {
|
|
fontsize *= 0.75;
|
|
}
|
|
context.font = fontsize + "pt Arial";
|
|
context.fillStyle = this.diceColor;
|
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
context.textAlign = "center";
|
|
context.textBaseline = "middle";
|
|
if (this.sides == 10 || this.sides == 100) {
|
|
context.translate(canvas.width / 2, canvas.height / 2);
|
|
context.rotate(60 * Math.PI / 180);
|
|
context.translate(-canvas.width / 2, -canvas.height / 2);
|
|
}
|
|
context.fillStyle = this.textColor;
|
|
context.fillText(text, canvas.width / 2, canvas.height / 2);
|
|
if (this.sides > 6 && (text == "6" || text == "9")) {
|
|
context.fillText(" .", canvas.width / 2, canvas.height / 2);
|
|
}
|
|
var texture = new Texture(canvas);
|
|
texture.needsUpdate = true;
|
|
return texture;
|
|
}
|
|
clone() {
|
|
return {
|
|
body: new Body({
|
|
mass: this.mass,
|
|
shape: this.shape
|
|
}),
|
|
geometry: this.geometry.clone(),
|
|
values: this.values
|
|
};
|
|
}
|
|
};
|
|
var D20DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.sides = 20;
|
|
this.tab = -0.2;
|
|
this.af = -Math.PI / 4 / 2;
|
|
this.chamfer = 0.955;
|
|
this.vertices = [];
|
|
this.faces = [
|
|
[0, 11, 5, 1],
|
|
[0, 5, 1, 2],
|
|
[0, 1, 7, 3],
|
|
[0, 7, 10, 4],
|
|
[0, 10, 11, 5],
|
|
[1, 5, 9, 6],
|
|
[5, 11, 4, 7],
|
|
[11, 10, 2, 8],
|
|
[10, 7, 6, 9],
|
|
[7, 1, 8, 10],
|
|
[3, 9, 4, 11],
|
|
[3, 4, 2, 12],
|
|
[3, 2, 6, 13],
|
|
[3, 6, 8, 14],
|
|
[3, 8, 9, 15],
|
|
[4, 9, 5, 16],
|
|
[2, 4, 11, 17],
|
|
[6, 2, 10, 18],
|
|
[8, 6, 7, 19],
|
|
[9, 8, 1, 20]
|
|
];
|
|
this.scaleFactor = 1;
|
|
this.values = [...Array(20).keys()];
|
|
this.margin = 1;
|
|
this.mass = 400;
|
|
let t = (1 + Math.sqrt(5)) / 2;
|
|
this.vertices = [
|
|
[-1, t, 0],
|
|
[1, t, 0],
|
|
[-1, -t, 0],
|
|
[1, -t, 0],
|
|
[0, -1, t],
|
|
[0, 1, t],
|
|
[0, -1, -t],
|
|
[0, 1, -t],
|
|
[t, 0, -1],
|
|
[t, 0, 1],
|
|
[-t, 0, -1],
|
|
[-t, 0, 1]
|
|
];
|
|
this.create();
|
|
}
|
|
};
|
|
var D12DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 350;
|
|
this.sides = 12;
|
|
this.tab = 0.2;
|
|
this.af = -Math.PI / 4 / 2;
|
|
this.chamfer = 0.968;
|
|
this.vertices = [];
|
|
this.faces = [
|
|
[2, 14, 4, 12, 0, 1],
|
|
[15, 9, 11, 19, 3, 2],
|
|
[16, 10, 17, 7, 6, 3],
|
|
[6, 7, 19, 11, 18, 4],
|
|
[6, 18, 2, 0, 16, 5],
|
|
[18, 11, 9, 14, 2, 6],
|
|
[1, 17, 10, 8, 13, 7],
|
|
[1, 13, 5, 15, 3, 8],
|
|
[13, 8, 12, 4, 5, 9],
|
|
[5, 4, 14, 9, 15, 10],
|
|
[0, 12, 8, 10, 16, 11],
|
|
[3, 19, 7, 17, 1, 12]
|
|
];
|
|
this.scaleFactor = 0.9;
|
|
this.values = [...Array(12).keys()];
|
|
this.margin = 1;
|
|
let p2 = (1 + Math.sqrt(5)) / 2;
|
|
let q = 1 / p2;
|
|
this.vertices = [
|
|
[0, q, p2],
|
|
[0, q, -p2],
|
|
[0, -q, p2],
|
|
[0, -q, -p2],
|
|
[p2, 0, q],
|
|
[p2, 0, -q],
|
|
[-p2, 0, q],
|
|
[-p2, 0, -q],
|
|
[q, p2, 0],
|
|
[q, -p2, 0],
|
|
[-q, p2, 0],
|
|
[-q, -p2, 0],
|
|
[1, 1, 1],
|
|
[1, 1, -1],
|
|
[1, -1, 1],
|
|
[1, -1, -1],
|
|
[-1, 1, 1],
|
|
[-1, 1, -1],
|
|
[-1, -1, 1],
|
|
[-1, -1, -1]
|
|
];
|
|
this.create();
|
|
}
|
|
};
|
|
var D10DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 350;
|
|
this.sides = 10;
|
|
this.tab = 0;
|
|
this.af = -Math.PI * 6 / 5;
|
|
this.chamfer = 0.945;
|
|
this.vertices = [];
|
|
this.faces = [
|
|
[5, 7, 11, 0],
|
|
[4, 2, 10, 1],
|
|
[1, 3, 11, 2],
|
|
[0, 8, 10, 3],
|
|
[7, 9, 11, 4],
|
|
[8, 6, 10, 5],
|
|
[9, 1, 11, 6],
|
|
[2, 0, 10, 7],
|
|
[3, 5, 11, 8],
|
|
[6, 4, 10, 9],
|
|
[1, 0, 2, -1],
|
|
[1, 2, 3, -1],
|
|
[3, 2, 4, -1],
|
|
[3, 4, 5, -1],
|
|
[5, 4, 6, -1],
|
|
[5, 6, 7, -1],
|
|
[7, 6, 8, -1],
|
|
[7, 8, 9, -1],
|
|
[9, 8, 0, -1],
|
|
[9, 0, 1, -1]
|
|
];
|
|
this.scaleFactor = 0.9;
|
|
this.values = [...Array(10).keys()];
|
|
this.margin = 1;
|
|
for (let i = 0, b2 = 0; i < 10; ++i, b2 += Math.PI * 2 / 10) {
|
|
this.vertices.push([
|
|
Math.cos(b2),
|
|
Math.sin(b2),
|
|
0.105 * (i % 2 ? 1 : -1)
|
|
]);
|
|
}
|
|
this.vertices.push([0, 0, -1]);
|
|
this.vertices.push([0, 0, 1]);
|
|
this.create();
|
|
}
|
|
};
|
|
var D100DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.labels = ["", "00", "10", "20", "30", "40", "50", "60", "70", "80", "90"];
|
|
this.sides = 100;
|
|
this.mass = 350;
|
|
this.tab = 0;
|
|
this.af = -Math.PI * 6 / 5;
|
|
this.chamfer = 0.945;
|
|
this.vertices = [];
|
|
this.faces = [
|
|
[5, 7, 11, 0],
|
|
[4, 2, 10, 1],
|
|
[1, 3, 11, 2],
|
|
[0, 8, 10, 3],
|
|
[7, 9, 11, 4],
|
|
[8, 6, 10, 5],
|
|
[9, 1, 11, 6],
|
|
[2, 0, 10, 7],
|
|
[3, 5, 11, 8],
|
|
[6, 4, 10, 9],
|
|
[1, 0, 2, -1],
|
|
[1, 2, 3, -1],
|
|
[3, 2, 4, -1],
|
|
[3, 4, 5, -1],
|
|
[5, 4, 6, -1],
|
|
[5, 6, 7, -1],
|
|
[7, 6, 8, -1],
|
|
[7, 8, 9, -1],
|
|
[9, 8, 0, -1],
|
|
[9, 0, 1, -1]
|
|
];
|
|
this.scaleFactor = 0.9;
|
|
this.values = [...Array(10).keys()];
|
|
this.margin = 1;
|
|
for (let i = 0, b2 = 0; i < 10; ++i, b2 += Math.PI * 2 / 10) {
|
|
this.vertices.push([
|
|
Math.cos(b2),
|
|
Math.sin(b2),
|
|
0.105 * (i % 2 ? 1 : -1)
|
|
]);
|
|
}
|
|
this.vertices.push([0, 0, -1]);
|
|
this.vertices.push([0, 0, 1]);
|
|
this.create();
|
|
}
|
|
};
|
|
var D8DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 340;
|
|
this.sides = 8;
|
|
this.tab = 0;
|
|
this.af = -Math.PI / 4 / 2;
|
|
this.chamfer = 0.965;
|
|
this.vertices = [
|
|
[1, 0, 0],
|
|
[-1, 0, 0],
|
|
[0, 1, 0],
|
|
[0, -1, 0],
|
|
[0, 0, 1],
|
|
[0, 0, -1]
|
|
];
|
|
this.faces = [
|
|
[0, 2, 4, 1],
|
|
[0, 4, 3, 2],
|
|
[0, 3, 5, 3],
|
|
[0, 5, 2, 4],
|
|
[1, 3, 4, 5],
|
|
[1, 4, 2, 6],
|
|
[1, 2, 5, 7],
|
|
[1, 5, 3, 8]
|
|
];
|
|
this.scaleFactor = 1;
|
|
this.values = [...Array(8).keys()];
|
|
this.margin = 1.2;
|
|
this.create();
|
|
}
|
|
};
|
|
var D6DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 300;
|
|
this.tab = 0.1;
|
|
this.af = Math.PI / 4;
|
|
this.chamfer = 0.96;
|
|
this.vertices = [
|
|
[-1, -1, -1],
|
|
[1, -1, -1],
|
|
[1, 1, -1],
|
|
[-1, 1, -1],
|
|
[-1, -1, 1],
|
|
[1, -1, 1],
|
|
[1, 1, 1],
|
|
[-1, 1, 1]
|
|
];
|
|
this.faces = [
|
|
[0, 3, 2, 1, 1],
|
|
[1, 2, 6, 5, 2],
|
|
[0, 1, 5, 4, 3],
|
|
[3, 7, 6, 2, 4],
|
|
[0, 4, 7, 3, 5],
|
|
[4, 5, 6, 7, 6]
|
|
];
|
|
this.scaleFactor = 0.9;
|
|
this.sides = 6;
|
|
this.margin = 1;
|
|
this.values = [...Array(6).keys()];
|
|
this.create();
|
|
}
|
|
};
|
|
var FudgeDiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 300;
|
|
this.tab = 0.1;
|
|
this.af = Math.PI / 4;
|
|
this.chamfer = 0.96;
|
|
this.vertices = [
|
|
[-1, -1, -1],
|
|
[1, -1, -1],
|
|
[1, 1, -1],
|
|
[-1, 1, -1],
|
|
[-1, -1, 1],
|
|
[1, -1, 1],
|
|
[1, 1, 1],
|
|
[-1, 1, 1]
|
|
];
|
|
this.faces = [
|
|
[0, 3, 2, 1, 1],
|
|
[1, 2, 6, 5, 2],
|
|
[0, 1, 5, 4, 3],
|
|
[3, 7, 6, 2, 4],
|
|
[0, 4, 7, 3, 5],
|
|
[4, 5, 6, 7, 6]
|
|
];
|
|
this.scaleFactor = 0.9;
|
|
this.sides = 6;
|
|
this.margin = 1;
|
|
this.labels = ["", "", "+", "-", " ", "+", "-", " "];
|
|
this.values = [null, 1, -1, 0, 1, -1, 0];
|
|
this.create();
|
|
}
|
|
};
|
|
var D4DiceShape = class extends DiceShape {
|
|
constructor(w2, h, options = DEFAULT_DICE_OPTIONS) {
|
|
super(w2, h, options);
|
|
this.mass = 300;
|
|
this.tab = -0.1;
|
|
this.af = Math.PI * 7 / 6;
|
|
this.chamfer = 0.96;
|
|
this.vertices = [
|
|
[1, 1, 1],
|
|
[-1, -1, 1],
|
|
[-1, 1, -1],
|
|
[1, -1, -1]
|
|
];
|
|
this.faces = [
|
|
[1, 0, 2, 1],
|
|
[0, 1, 3, 2],
|
|
[0, 3, 2, 3],
|
|
[1, 2, 3, 4]
|
|
];
|
|
this.scaleFactor = 1.2;
|
|
this.sides = 4;
|
|
this.margin = 1;
|
|
this.d4FaceTexts = [
|
|
[[], [0, 0, 0], [2, 4, 3], [1, 3, 4], [2, 1, 4], [1, 2, 3]],
|
|
[[], [0, 0, 0], [2, 3, 4], [3, 1, 4], [2, 4, 1], [3, 2, 1]],
|
|
[[], [0, 0, 0], [4, 3, 2], [3, 4, 1], [4, 2, 1], [3, 1, 2]],
|
|
[[], [0, 0, 0], [4, 2, 3], [1, 4, 3], [4, 1, 2], [1, 3, 2]]
|
|
];
|
|
this.faceTexts = this.d4FaceTexts[0];
|
|
this.values = [...Array(4).keys()];
|
|
this.create();
|
|
}
|
|
getMaterials() {
|
|
let materials = [];
|
|
for (let i = 0; i < this.d4FaceTexts[0].length; ++i) {
|
|
let texture = null;
|
|
texture = this.createTextTexture(i);
|
|
materials.push(new MeshPhongMaterial(Object.assign({}, MATERIAL_OPTIONS, { map: texture })));
|
|
}
|
|
return materials;
|
|
}
|
|
createTextTexture(index) {
|
|
let canvas = document.createElement("canvas");
|
|
let ctx = canvas.getContext("2d");
|
|
let ts = this.calculateTextureSize(this.radius / 2 + this.radius * 2) * 2;
|
|
canvas.width = canvas.height = ts;
|
|
ctx.font = ts / 5 + "pt Arial";
|
|
ctx.fillStyle = this.diceColor;
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
ctx.fillStyle = this.textColor;
|
|
for (let i in this.faceTexts[index]) {
|
|
ctx.fillText(`${this.faceTexts[index][i]}`, canvas.width / 2, canvas.height / 2 - ts * 0.3);
|
|
ctx.translate(canvas.width / 2, canvas.height / 2);
|
|
ctx.rotate(Math.PI * 2 / 3);
|
|
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
|
}
|
|
let texture = new Texture(canvas);
|
|
texture.needsUpdate = true;
|
|
return texture;
|
|
}
|
|
updateMaterialsForValue(diceValue) {
|
|
if (diceValue < 0)
|
|
diceValue += 4;
|
|
this.faceTexts = this.d4FaceTexts[diceValue];
|
|
this.geometry.material = this.getMaterials();
|
|
}
|
|
};
|
|
|
|
// src/view/renderer.ts
|
|
var _DiceRenderer = class extends import_obsidian7.Component {
|
|
constructor(plugin) {
|
|
super();
|
|
this.plugin = plugin;
|
|
this.event = new import_obsidian7.Events();
|
|
this.container = createDiv("renderer-container");
|
|
this.shadows = true;
|
|
this.iterations = 0;
|
|
this.frame_rate = 1 / 60;
|
|
this.animating = false;
|
|
this.factory = new DiceFactory(this.WIDTH, this.HEIGHT, this.plugin);
|
|
this.colors = {
|
|
ambient: 16777215,
|
|
spotlight: 16777215
|
|
};
|
|
this.display = {
|
|
currentWidth: null,
|
|
currentHeight: null,
|
|
containerWidth: null,
|
|
containerHeight: null,
|
|
aspect: null,
|
|
scale: null
|
|
};
|
|
this.cameraHeight = {
|
|
max: null,
|
|
close: null,
|
|
medium: null,
|
|
far: null
|
|
};
|
|
this.extraFrames = _DiceRenderer.DEFAULT_EXTRA_FRAMES;
|
|
this.renderer = new WebGLRenderer({
|
|
alpha: true,
|
|
antialias: true
|
|
});
|
|
}
|
|
get WIDTH() {
|
|
return this.container.clientWidth / 2;
|
|
}
|
|
get HEIGHT() {
|
|
return this.container.clientHeight / 2;
|
|
}
|
|
get ASPECT() {
|
|
return this.WIDTH / this.HEIGHT;
|
|
}
|
|
get scale() {
|
|
return (this.WIDTH * this.WIDTH + this.HEIGHT * this.HEIGHT) / 13;
|
|
}
|
|
get canvasEl() {
|
|
if (!this.renderer)
|
|
return null;
|
|
return this.renderer.domElement;
|
|
}
|
|
setDice(stack) {
|
|
if (this.animating) {
|
|
this.unload();
|
|
this.load();
|
|
}
|
|
this.stack = stack;
|
|
this.current = this.factory.getDice(this.stack, {
|
|
x: (Math.random() * 2 - 1) * this.WIDTH,
|
|
y: -(Math.random() * 2 - 1) * this.HEIGHT
|
|
});
|
|
this.scene.add(...[...this.current.values()].flat().map((d) => d.geometry));
|
|
this.world.add(...[...this.current.values()].flat());
|
|
}
|
|
onload() {
|
|
this.addChild(this.factory);
|
|
this.container.empty();
|
|
this.container.style.opacity = `1`;
|
|
document.body.appendChild(this.container);
|
|
this.renderer.shadowMap.enabled = this.shadows;
|
|
this.renderer.shadowMap.type = PCFSoftShadowMap;
|
|
this.container.appendChild(this.renderer.domElement);
|
|
this.renderer.setClearColor(0, 0);
|
|
this.scene = new Scene();
|
|
this.initScene();
|
|
this.registerDomEvent(window, "resize", () => {
|
|
this.initScene();
|
|
});
|
|
this.initWorld();
|
|
}
|
|
async start() {
|
|
return new Promise(async (resolve2, reject2) => {
|
|
if (!this.current.size)
|
|
reject2();
|
|
this.event.on("throw-finished", (result) => {
|
|
resolve2(result);
|
|
});
|
|
this.event.on("error", (e) => {
|
|
reject2(e);
|
|
});
|
|
this.animating = true;
|
|
this.extraFrames = _DiceRenderer.DEFAULT_EXTRA_FRAMES;
|
|
this.render();
|
|
});
|
|
}
|
|
enableShadows() {
|
|
this.shadows = true;
|
|
if (this.renderer)
|
|
this.renderer.shadowMap.enabled = this.shadows;
|
|
if (this.light)
|
|
this.light.castShadow = this.shadows;
|
|
if (this.desk)
|
|
this.desk.receiveShadow = this.shadows;
|
|
}
|
|
disableShadows() {
|
|
this.shadows = false;
|
|
if (this.renderer)
|
|
this.renderer.shadowMap.enabled = this.shadows;
|
|
if (this.light)
|
|
this.light.castShadow = this.shadows;
|
|
if (this.desk)
|
|
this.desk.receiveShadow = this.shadows;
|
|
}
|
|
get mw() {
|
|
return Math.max(this.WIDTH, this.HEIGHT);
|
|
}
|
|
setDimensions(dimensions) {
|
|
this.display.currentWidth = this.container.clientWidth / 2;
|
|
this.display.currentHeight = this.container.clientHeight / 2;
|
|
if (dimensions) {
|
|
this.display.containerWidth = dimensions.w;
|
|
this.display.containerHeight = dimensions.h;
|
|
} else {
|
|
this.display.containerWidth = this.display.currentWidth;
|
|
this.display.containerHeight = this.display.currentHeight;
|
|
}
|
|
this.display.aspect = Math.min(this.display.currentWidth / this.display.containerWidth, this.display.currentHeight / this.display.containerHeight);
|
|
this.display.scale = Math.sqrt(this.display.containerWidth * this.display.containerWidth + this.display.containerHeight * this.display.containerHeight) / 13;
|
|
this.renderer.setSize(this.display.currentWidth * 2, this.display.currentHeight * 2);
|
|
this.cameraHeight.max = this.display.currentHeight / this.display.aspect / Math.tan(10 * Math.PI / 180);
|
|
this.factory.width = this.display.currentWidth;
|
|
this.factory.height = this.display.currentHeight;
|
|
this.cameraHeight.medium = this.cameraHeight.max / 1.5;
|
|
this.cameraHeight.far = this.cameraHeight.max;
|
|
this.cameraHeight.close = this.cameraHeight.max / 2;
|
|
}
|
|
initCamera() {
|
|
if (this.camera)
|
|
this.scene.remove(this.camera);
|
|
this.camera = new PerspectiveCamera(20, this.display.currentWidth / this.display.currentHeight, 1, this.cameraHeight.max * 1.3);
|
|
this.camera.position.z = this.cameraHeight.far;
|
|
this.camera.lookAt(new Vector3(0, 0, 0));
|
|
}
|
|
initLighting() {
|
|
const maxwidth = Math.max(this.display.containerWidth, this.display.containerHeight);
|
|
if (this.light)
|
|
this.scene.remove(this.light);
|
|
if (this.ambientLight)
|
|
this.scene.remove(this.ambientLight);
|
|
this.light = new SpotLight(this.colors.spotlight, 0.25);
|
|
this.light.position.set(-maxwidth / 2, maxwidth / 2, maxwidth * 3);
|
|
this.light.target.position.set(0, 0, 0);
|
|
this.light.distance = maxwidth * 5;
|
|
this.light.angle = Math.PI / 4;
|
|
this.light.castShadow = this.shadows;
|
|
this.light.shadow.camera.near = maxwidth / 10;
|
|
this.light.shadow.camera.far = maxwidth * 5;
|
|
this.light.shadow.camera.fov = 50;
|
|
this.light.shadow.bias = 1e-3;
|
|
this.light.shadow.mapSize.width = 1024;
|
|
this.light.shadow.mapSize.height = 1024;
|
|
this.scene.add(this.light);
|
|
this.ambientLight = new AmbientLight(16777215, 0.9);
|
|
this.scene.add(this.ambientLight);
|
|
}
|
|
initDesk() {
|
|
if (this.desk)
|
|
this.scene.remove(this.desk);
|
|
let shadowplane = new ShadowMaterial();
|
|
shadowplane.opacity = 0.5;
|
|
this.desk = new Mesh(new PlaneGeometry(this.display.containerWidth * 6, this.display.containerHeight * 6, 1, 1), shadowplane);
|
|
this.desk.receiveShadow = this.shadows;
|
|
this.scene.add(this.desk);
|
|
}
|
|
initScene() {
|
|
this.setDimensions();
|
|
this.initCamera();
|
|
this.initLighting();
|
|
this.initDesk();
|
|
this.camera.updateProjectionMatrix();
|
|
this.renderer.render(this.scene, this.camera);
|
|
}
|
|
initWorld() {
|
|
this.world = new World2(this.WIDTH, this.HEIGHT);
|
|
this.iterations = 0;
|
|
}
|
|
returnResult() {
|
|
for (const roller of this.stack.dynamic) {
|
|
if (!this.current.has(roller)) {
|
|
continue;
|
|
}
|
|
const diceArray = this.current.get(roller);
|
|
const percentile = diceArray.filter((d) => d instanceof D10Dice && d.isPercentile);
|
|
const chunked = [];
|
|
for (let i = 0; i < percentile.length; i += 2) {
|
|
chunked.push(percentile.slice(i, i + 2));
|
|
}
|
|
let results = [
|
|
...diceArray.filter((d) => !(d instanceof D10Dice && d.isPercentile)).map((dice) => {
|
|
return dice.getUpsideValue();
|
|
}).filter((r) => r),
|
|
...chunked.map(([tensDice, onesDice]) => {
|
|
let tens = tensDice.getUpsideValue();
|
|
if (!onesDice)
|
|
return tens;
|
|
let ones = onesDice.getUpsideValue();
|
|
if (tens === 10 && ones == 10) {
|
|
return 100;
|
|
} else {
|
|
if (ones == 10)
|
|
ones = 0;
|
|
if (tens == 10)
|
|
tens = 0;
|
|
return tens * 10 + ones;
|
|
}
|
|
}).filter((r) => r)
|
|
];
|
|
roller.setResults(results);
|
|
}
|
|
this.event.trigger("throw-finished", this.stack);
|
|
}
|
|
render() {
|
|
if (this.throwFinished()) {
|
|
if (this.extraFrames > 10) {
|
|
this.extraFrames--;
|
|
} else {
|
|
try {
|
|
this.returnResult();
|
|
this.registerInterval(window.setTimeout(() => {
|
|
this.container.style.opacity = `0`;
|
|
this.registerInterval(window.setTimeout(() => {
|
|
this.animating = false;
|
|
this.unload();
|
|
}, 1e3));
|
|
}, 2e3));
|
|
} catch (e) {
|
|
this.event.trigger("error", e);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
this.animation = requestAnimationFrame(() => this.render());
|
|
this.world.step(this.frame_rate);
|
|
this.iterations++;
|
|
this.current.forEach((dice) => {
|
|
dice.map((d) => d.set());
|
|
});
|
|
this.renderer.render(this.scene, this.camera);
|
|
}
|
|
dispose(...children) {
|
|
children.forEach((child) => {
|
|
if ("dispose" in child)
|
|
child.dispose();
|
|
if (child.children)
|
|
this.dispose(...child.children);
|
|
});
|
|
}
|
|
detach() {
|
|
}
|
|
onunload() {
|
|
cancelAnimationFrame(this.animation);
|
|
this.container.detach();
|
|
this.container.empty();
|
|
this.renderer.domElement.detach();
|
|
this.renderer.dispose();
|
|
this.factory.dispose();
|
|
this.ambientLight.dispose();
|
|
this.light.dispose();
|
|
this.scene.children.forEach((child) => this.dispose(child));
|
|
this.scene.remove(this.scene, ...this.scene.children, ...[...this.current.values()].flat().map((d) => d.geometry));
|
|
this.current.forEach((arr) => {
|
|
arr.forEach((dice) => {
|
|
let materials = [
|
|
...Array.isArray(dice.geometry.material) ? dice.geometry.material : [dice.geometry.material]
|
|
];
|
|
materials.forEach((material) => material && material.dispose());
|
|
this.world.world.removeBody(dice.body);
|
|
});
|
|
});
|
|
this.current = /* @__PURE__ */ new Map();
|
|
}
|
|
onThrowFinished() {
|
|
}
|
|
throwFinished() {
|
|
let res = true;
|
|
const threshold = 4;
|
|
if (this.iterations < 10 / this.frame_rate) {
|
|
for (const diceArray of this.current.values()) {
|
|
for (const dice of diceArray) {
|
|
if (dice.stopped === true)
|
|
continue;
|
|
const a2 = dice.body.angularVelocity, v = dice.body.velocity;
|
|
if (Math.abs(a2.x) < threshold && Math.abs(a2.y) < threshold && Math.abs(a2.z) < threshold && Math.abs(v.x) < threshold && Math.abs(v.y) < threshold && Math.abs(v.z) < threshold) {
|
|
if (dice.stopped) {
|
|
if (this.iterations - dice.stopped > 3) {
|
|
dice.stopped = true;
|
|
continue;
|
|
}
|
|
} else {
|
|
dice.stopped = this.iterations;
|
|
}
|
|
res = false;
|
|
} else {
|
|
dice.stopped = void 0;
|
|
res = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
var DiceRenderer = _DiceRenderer;
|
|
DiceRenderer.DEFAULT_EXTRA_FRAMES = 30;
|
|
var World2 = class {
|
|
constructor(WIDTH, HEIGHT) {
|
|
this.WIDTH = WIDTH;
|
|
this.HEIGHT = HEIGHT;
|
|
this.world = new World({ gravity: new Vec3(0, 0, -9.82 * 400) });
|
|
this.ground = this.getPlane();
|
|
this.diceMaterial = new Material2();
|
|
this.deskMaterial = new Material2();
|
|
this.barrierMaterial = new Material2();
|
|
this.world.broadphase = new NaiveBroadphase();
|
|
this.world.allowSleep = true;
|
|
this.ground.position.set(0, 0, 0);
|
|
this.world.addBody(this.ground);
|
|
this.buildWalls();
|
|
}
|
|
add(...dice) {
|
|
dice.forEach((die) => {
|
|
this.world.addBody(die.body);
|
|
});
|
|
}
|
|
step(step = 1 / 60) {
|
|
const time = performance.now() / 1e3;
|
|
if (!this.lastCallTime) {
|
|
this.world.step(step);
|
|
} else {
|
|
const dt = time - this.lastCallTime;
|
|
this.world.step(step, dt);
|
|
}
|
|
this.lastCallTime = time;
|
|
}
|
|
buildWalls() {
|
|
this.world.addContactMaterial(new ContactMaterial(this.deskMaterial, this.diceMaterial, {
|
|
friction: 0.01,
|
|
restitution: 0.5,
|
|
contactEquationRelaxation: 3,
|
|
contactEquationStiffness: 1e8
|
|
}));
|
|
this.world.addContactMaterial(new ContactMaterial(this.barrierMaterial, this.diceMaterial, {
|
|
friction: 0.01,
|
|
restitution: 1,
|
|
contactEquationRelaxation: 3,
|
|
contactEquationStiffness: 1e8
|
|
}));
|
|
this.world.addContactMaterial(new ContactMaterial(this.diceMaterial, this.diceMaterial, {
|
|
friction: 0.1,
|
|
restitution: 0.5,
|
|
contactEquationRelaxation: 3,
|
|
contactEquationStiffness: 1e8
|
|
}));
|
|
this.world.addBody(new Body({
|
|
allowSleep: false,
|
|
mass: 0,
|
|
shape: new Plane2(),
|
|
material: this.deskMaterial
|
|
}));
|
|
let barrier = new Body({
|
|
allowSleep: false,
|
|
mass: 0,
|
|
shape: new Plane2(),
|
|
material: this.barrierMaterial
|
|
});
|
|
barrier.quaternion.setFromAxisAngle(new Vec3(1, 0, 0), Math.PI / 2);
|
|
barrier.position.set(0, this.HEIGHT * 0.93, 0);
|
|
this.world.addBody(barrier);
|
|
barrier = new Body({
|
|
allowSleep: false,
|
|
mass: 0,
|
|
shape: new Plane2(),
|
|
material: this.barrierMaterial
|
|
});
|
|
barrier.quaternion.setFromAxisAngle(new Vec3(1, 0, 0), -Math.PI / 2);
|
|
barrier.position.set(0, -this.HEIGHT * 0.93, 0);
|
|
this.world.addBody(barrier);
|
|
barrier = new Body({
|
|
allowSleep: false,
|
|
mass: 0,
|
|
shape: new Plane2(),
|
|
material: this.barrierMaterial
|
|
});
|
|
barrier.quaternion.setFromAxisAngle(new Vec3(0, 1, 0), -Math.PI / 2);
|
|
barrier.position.set(this.WIDTH * 0.93, 0, 0);
|
|
this.world.addBody(barrier);
|
|
barrier = new Body({
|
|
allowSleep: false,
|
|
mass: 0,
|
|
shape: new Plane2(),
|
|
material: this.barrierMaterial
|
|
});
|
|
barrier.quaternion.setFromAxisAngle(new Vec3(0, 1, 0), Math.PI / 2);
|
|
barrier.position.set(-this.WIDTH * 0.93, 0, 0);
|
|
this.world.addBody(barrier);
|
|
}
|
|
getPlane() {
|
|
return new Body({
|
|
type: Body.STATIC,
|
|
shape: new Plane2()
|
|
});
|
|
}
|
|
};
|
|
var DEFAULT_VECTOR = {
|
|
pos: {
|
|
x: 0 + 100 * Math.random(),
|
|
y: 0 + 100 * Math.random(),
|
|
z: 0 + 250
|
|
},
|
|
velocity: {
|
|
x: 600 * (Math.random() * 2 + 1),
|
|
y: 750 * (Math.random() * 2 + 1),
|
|
z: 0
|
|
},
|
|
angular: {
|
|
x: 200 * Math.random(),
|
|
y: 200 * Math.random(),
|
|
z: 100 * Math.random()
|
|
},
|
|
axis: {
|
|
x: Math.random(),
|
|
y: Math.random(),
|
|
z: Math.random(),
|
|
w: Math.random()
|
|
}
|
|
};
|
|
var Dice = class {
|
|
constructor(w2, h, data) {
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.scale = 50;
|
|
this.stopped = false;
|
|
this.iteration = 0;
|
|
this.vector = { ...DEFAULT_VECTOR };
|
|
this.geometry = data.geometry;
|
|
this.body = data.body;
|
|
}
|
|
generateVector(v) {
|
|
const dist = Math.sqrt(v.x * v.x + v.y * v.y);
|
|
const boost = (Math.random() + 3) * dist;
|
|
const vector = { x: v.x / dist, y: v.y / dist };
|
|
const vec = this.makeRandomVector(vector);
|
|
const pos = {
|
|
x: this.w * (vec.x > 0 ? -1 : 1) * 0.9,
|
|
y: this.h * (vec.y > 0 ? -1 : 1) * 0.9,
|
|
z: Math.random() * 200 + 200
|
|
};
|
|
const projector = Math.abs(vec.x / vec.y);
|
|
if (projector > 1)
|
|
pos.y /= projector;
|
|
else
|
|
pos.x *= projector;
|
|
const velvec = this.makeRandomVector(vector);
|
|
const velocity = {
|
|
x: velvec.x * boost,
|
|
y: velvec.y * boost,
|
|
z: -10
|
|
};
|
|
const angular = {
|
|
x: -(Math.random() * vec.y * 5 + this.inertia * vec.y),
|
|
y: Math.random() * vec.x * 5 + this.inertia * vec.x,
|
|
z: 0
|
|
};
|
|
const axis = {
|
|
x: Math.random(),
|
|
y: Math.random(),
|
|
z: Math.random(),
|
|
w: Math.random()
|
|
};
|
|
return {
|
|
pos,
|
|
velocity,
|
|
angular,
|
|
axis
|
|
};
|
|
}
|
|
makeRandomVector(vector) {
|
|
const random_angle = Math.random() * Math.PI / 5 - Math.PI / 5 / 2;
|
|
const vec = {
|
|
x: vector.x * Math.cos(random_angle) - vector.y * Math.sin(random_angle),
|
|
y: vector.x * Math.sin(random_angle) + vector.y * Math.cos(random_angle)
|
|
};
|
|
if (vec.x == 0)
|
|
vec.x = 0.01;
|
|
if (vec.y == 0)
|
|
vec.y = 0.01;
|
|
return vec;
|
|
}
|
|
get buffer() {
|
|
return this.geometry.geometry;
|
|
}
|
|
getUpsideValue() {
|
|
let vector = new Vector3(0, 0, this.sides == 4 ? -1 : 1);
|
|
let closest_face, closest_angle = Math.PI * 2;
|
|
const normals = this.buffer.getAttribute("normal").array;
|
|
for (let i = 0, l = this.buffer.groups.length; i < l; ++i) {
|
|
const face = this.buffer.groups[i];
|
|
if (face.materialIndex == 0)
|
|
continue;
|
|
let startVertex = i * 9;
|
|
const normal = new Vector3(normals[startVertex], normals[startVertex + 1], normals[startVertex + 2]);
|
|
const angle = normal.clone().applyQuaternion(new Quaternion(this.body.quaternion.x, this.body.quaternion.y, this.body.quaternion.z, this.body.quaternion.w)).angleTo(vector);
|
|
if (angle < closest_angle) {
|
|
closest_angle = angle;
|
|
closest_face = face;
|
|
}
|
|
}
|
|
let matindex = closest_face.materialIndex - 1;
|
|
if (this.sides == 10 && matindex == 0)
|
|
matindex = 10;
|
|
return this.data.values?.[matindex] ?? matindex;
|
|
}
|
|
shiftUpperValue(to) {
|
|
let geometry = this.geometry.geometry.clone();
|
|
let from = this.getUpsideValue();
|
|
for (let i = 0, l = geometry.groups.length; i < l; ++i) {
|
|
let materialIndex = geometry.groups[i].materialIndex;
|
|
if (materialIndex === 0)
|
|
continue;
|
|
materialIndex += to - from - 1;
|
|
while (materialIndex > this.sides)
|
|
materialIndex -= this.sides;
|
|
while (materialIndex < 1)
|
|
materialIndex += this.sides;
|
|
geometry.groups[i].materialIndex = materialIndex + 1;
|
|
}
|
|
this.updateMaterialsForValue(to - from);
|
|
this.geometry.geometry = geometry;
|
|
}
|
|
resetBody() {
|
|
this.body.vlambda = new Vec3();
|
|
this.body.position = new Vec3();
|
|
this.body.previousPosition = new Vec3();
|
|
this.body.initPosition = new Vec3();
|
|
this.body.velocity = new Vec3();
|
|
this.body.initVelocity = new Vec3();
|
|
this.body.force = new Vec3();
|
|
this.body.torque = new Vec3();
|
|
this.body.quaternion = new Quaternion2();
|
|
this.body.initQuaternion = new Quaternion2();
|
|
this.body.angularVelocity = new Vec3();
|
|
this.body.initAngularVelocity = new Vec3();
|
|
this.body.interpolatedPosition = new Vec3();
|
|
this.body.interpolatedQuaternion = new Quaternion2();
|
|
this.body.inertia = new Vec3();
|
|
this.body.invInertia = new Vec3();
|
|
this.body.invInertiaWorld = new Mat3();
|
|
this.body.invInertiaSolve = new Vec3();
|
|
this.body.invInertiaWorldSolve = new Mat3();
|
|
this.body.wlambda = new Vec3();
|
|
this.body.updateMassProperties();
|
|
}
|
|
updateMaterialsForValue(value) {
|
|
}
|
|
set() {
|
|
this.geometry.position.set(this.body.position.x, this.body.position.y, this.body.position.z);
|
|
this.geometry.quaternion.set(this.body.quaternion.x, this.body.quaternion.y, this.body.quaternion.z, this.body.quaternion.w);
|
|
}
|
|
create() {
|
|
this.body.position.set(this.vector.pos.x, this.vector.pos.y, this.vector.pos.z);
|
|
this.body.quaternion.setFromAxisAngle(new Vec3(this.vector.axis.x, this.vector.axis.y, this.vector.axis.z), this.vector.axis.w * Math.PI * 2);
|
|
this.body.angularVelocity.set(this.vector.angular.x, this.vector.angular.y, this.vector.angular.z);
|
|
this.body.velocity.set(this.vector.velocity.x, this.vector.velocity.y, this.vector.velocity.z);
|
|
this.body.linearDamping = 0.1;
|
|
this.body.angularDamping = 0.1;
|
|
}
|
|
};
|
|
var DiceFactory = class extends import_obsidian7.Component {
|
|
constructor(width, height, plugin) {
|
|
super();
|
|
this.width = width;
|
|
this.height = height;
|
|
this.plugin = plugin;
|
|
this.d100 = new D100DiceShape(this.width, this.height, this.colors);
|
|
this.d20 = new D20DiceShape(this.width, this.height, this.colors);
|
|
this.d12 = new D12DiceShape(this.width, this.height, this.colors);
|
|
this.d10 = new D10DiceShape(this.width, this.height, this.colors);
|
|
this.d8 = new D8DiceShape(this.width, this.height, this.colors);
|
|
this.d6 = new D6DiceShape(this.width, this.height, this.colors);
|
|
this.d4 = new D4DiceShape(this.width, this.height, this.colors);
|
|
this.fudge = new FudgeDiceShape(this.width, this.height, this.colors);
|
|
}
|
|
get colors() {
|
|
return {
|
|
diceColor: this.plugin.data.diceColor,
|
|
textColor: this.plugin.data.textColor
|
|
};
|
|
}
|
|
updateColors() {
|
|
this.dispose();
|
|
this.d100 = new D100DiceShape(this.width, this.height, this.colors);
|
|
this.d20 = new D20DiceShape(this.width, this.height, this.colors);
|
|
this.d12 = new D12DiceShape(this.width, this.height, this.colors);
|
|
this.d10 = new D10DiceShape(this.width, this.height, this.colors);
|
|
this.d8 = new D8DiceShape(this.width, this.height, this.colors);
|
|
this.d6 = new D6DiceShape(this.width, this.height, this.colors);
|
|
this.d4 = new D4DiceShape(this.width, this.height, this.colors);
|
|
this.fudge = new FudgeDiceShape(this.width, this.height, this.colors);
|
|
}
|
|
onunload() {
|
|
this.dispose();
|
|
}
|
|
disposeChildren(...children) {
|
|
children.forEach((child) => {
|
|
if ("dispose" in child)
|
|
child.dispose();
|
|
if (child.children)
|
|
this.disposeChildren(...child.children);
|
|
});
|
|
}
|
|
dispose() {
|
|
this.disposeChildren(this.d100.geometry.children);
|
|
this.disposeChildren(this.d20.geometry.children);
|
|
this.disposeChildren(this.d12.geometry.children);
|
|
this.disposeChildren(this.d10.geometry.children);
|
|
this.disposeChildren(this.d8.geometry.children);
|
|
this.disposeChildren(this.d6.geometry.children);
|
|
this.disposeChildren(this.d4.geometry.children);
|
|
}
|
|
getDice(stack, vector) {
|
|
const map = /* @__PURE__ */ new Map();
|
|
for (const roller of stack.dynamic) {
|
|
const dice = [];
|
|
switch (roller.faces.max) {
|
|
case 4: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D4Dice(this.width, this.height, this.d4.clone(), vector)));
|
|
break;
|
|
}
|
|
case 1:
|
|
case 6: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D6Dice(this.width, this.height, roller.fudge ? this.fudge.clone() : this.d6.clone(), vector)));
|
|
break;
|
|
}
|
|
case 8: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D8Dice(this.width, this.height, this.d8.clone(), vector)));
|
|
break;
|
|
}
|
|
case 10: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D10Dice(this.width, this.height, this.d10.clone(), vector)));
|
|
break;
|
|
}
|
|
case 12: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D12Dice(this.width, this.height, this.d12.clone(), vector)));
|
|
break;
|
|
}
|
|
case 20: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => new D20Dice(this.width, this.height, this.d20.clone(), vector)));
|
|
break;
|
|
}
|
|
case 100: {
|
|
dice.push(...new Array(roller.rolls).fill(0).map((r) => [
|
|
new D10Dice(this.width, this.height, this.d100.clone(), vector, true),
|
|
new D10Dice(this.width, this.height, this.d10.clone(), vector, true)
|
|
]).flat());
|
|
break;
|
|
}
|
|
}
|
|
if (dice.length)
|
|
map.set(roller, dice);
|
|
}
|
|
return map;
|
|
}
|
|
};
|
|
var D20Dice = class extends Dice {
|
|
constructor(w2, h, data, vector) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.sides = 20;
|
|
this.inertia = 6;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
var D12Dice = class extends Dice {
|
|
constructor(w2, h, data, vector) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.sides = 12;
|
|
this.inertia = 8;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
var D10Dice = class extends Dice {
|
|
constructor(w2, h, data, vector, isPercentile = false) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.isPercentile = isPercentile;
|
|
this.sides = 10;
|
|
this.inertia = 9;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
var D8Dice = class extends Dice {
|
|
constructor(w2, h, data, vector) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.sides = 8;
|
|
this.inertia = 10;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
var D6Dice = class extends Dice {
|
|
constructor(w2, h, data, vector) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.sides = 6;
|
|
this.inertia = 13;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
var D4Dice = class extends Dice {
|
|
constructor(w2, h, data, vector) {
|
|
super(w2, h, data);
|
|
this.w = w2;
|
|
this.h = h;
|
|
this.data = data;
|
|
this.sides = 4;
|
|
this.inertia = 5;
|
|
if (vector) {
|
|
this.vector = this.generateVector(vector);
|
|
}
|
|
this.create();
|
|
}
|
|
};
|
|
|
|
// src/main.ts
|
|
String.prototype.matchAll = String.prototype.matchAll || function* matchAll(regexp) {
|
|
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
|
|
const re = new RegExp(regexp, flags);
|
|
let match;
|
|
while (match = re.exec(this)) {
|
|
yield match;
|
|
}
|
|
};
|
|
var DEFAULT_SETTINGS = {
|
|
returnAllTags: true,
|
|
rollLinksForTags: false,
|
|
copyContentButton: true,
|
|
customFormulas: [],
|
|
displayFormulaForMod: true,
|
|
displayResultsInline: false,
|
|
displayLookupRoll: true,
|
|
formulas: {},
|
|
persistResults: false,
|
|
results: {},
|
|
defaultRoll: 1,
|
|
defaultFace: 100,
|
|
renderer: false,
|
|
diceColor: "#202020",
|
|
textColor: "#ffffff",
|
|
showLeafOnStartup: true,
|
|
showDice: true
|
|
};
|
|
var DiceRollerPlugin = class extends import_obsidian8.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.persistingFiles = /* @__PURE__ */ new Set();
|
|
this.fileMap = /* @__PURE__ */ new Map();
|
|
this.inline = /* @__PURE__ */ new Map();
|
|
this.operators = {
|
|
"+": (a2, b2) => a2 + b2,
|
|
"-": (a2, b2) => a2 - b2,
|
|
"*": (a2, b2) => a2 * b2,
|
|
"/": (a2, b2) => a2 / b2,
|
|
"^": (a2, b2) => {
|
|
return Math.pow(a2, b2);
|
|
}
|
|
};
|
|
}
|
|
get canUseDataview() {
|
|
return this.app.plugins.getPlugin("dataview") != null;
|
|
}
|
|
get dataview() {
|
|
return this.app.plugins.getPlugin("dataview");
|
|
}
|
|
async dataviewReady() {
|
|
return new Promise((resolve2) => {
|
|
if (!this.canUseDataview)
|
|
resolve2(false);
|
|
if (this.dataview.api) {
|
|
resolve2(true);
|
|
}
|
|
this.registerEvent(this.app.metadataCache.on("dataview:api-ready", () => {
|
|
resolve2(true);
|
|
}));
|
|
});
|
|
}
|
|
get view() {
|
|
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE);
|
|
const leaf = leaves.length ? leaves[0] : null;
|
|
if (leaf && leaf.view && leaf.view instanceof DiceView)
|
|
return leaf.view;
|
|
}
|
|
async addDiceView(startup = false) {
|
|
if (startup && !this.data.showLeafOnStartup)
|
|
return;
|
|
if (this.app.workspace.getLeavesOfType(VIEW_TYPE).length) {
|
|
return;
|
|
}
|
|
await this.app.workspace.getRightLeaf(false).setViewState({
|
|
type: VIEW_TYPE
|
|
});
|
|
}
|
|
async registerDataviewInlineFields() {
|
|
if (!this.canUseDataview)
|
|
return;
|
|
await this.dataviewReady();
|
|
const pages = this.dataview.index.pages;
|
|
pages.forEach(({ fields }) => {
|
|
for (const [key, value] of fields) {
|
|
if (typeof value !== "number" || Number.isNaN(value) || value == void 0)
|
|
continue;
|
|
this.inline.set(key, value);
|
|
}
|
|
});
|
|
this.registerEvent(this.app.metadataCache.on("dataview:metadata-change", (type, file) => {
|
|
if (type === "update") {
|
|
const page = this.dataview.api.page(file.path);
|
|
if (!page)
|
|
return;
|
|
for (let key in page) {
|
|
let value = page[key];
|
|
if (typeof value !== "number" || Number.isNaN(value) || value == void 0)
|
|
continue;
|
|
this.inline.set(key, value);
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
async renderRoll(roller) {
|
|
this.addChild(this.renderer);
|
|
this.renderer.setDice(roller);
|
|
await this.renderer.start();
|
|
roller.recalculate();
|
|
}
|
|
async onload() {
|
|
console.log("DiceRoller plugin loaded");
|
|
this.data = Object.assign(DEFAULT_SETTINGS, await this.loadData());
|
|
this.renderer = new DiceRenderer(this);
|
|
this.addSettingTab(new SettingTab(this.app, this));
|
|
this.registerView(VIEW_TYPE, (leaf) => new DiceView(this, leaf));
|
|
this.app.workspace.onLayoutReady(() => this.addDiceView(true));
|
|
this.registerEvent(this.app.workspace.on("dice-roller:update-colors", () => {
|
|
this.renderer.factory.updateColors();
|
|
}));
|
|
this.registerEvent(this.app.workspace.on("dice-roller:render-dice", async (roll) => {
|
|
const roller = await this.getRoller(roll, "external");
|
|
if (!(roller instanceof StackRoller)) {
|
|
new import_obsidian8.Notice("The Dice View only supports dice rolls.");
|
|
return;
|
|
}
|
|
await roller.roll();
|
|
if (!roller.dice.length) {
|
|
new import_obsidian8.Notice("Invalid formula.");
|
|
return;
|
|
}
|
|
try {
|
|
this.renderRoll(roller);
|
|
} catch (e) {
|
|
new import_obsidian8.Notice("There was an error rendering the roll.");
|
|
console.error(e);
|
|
}
|
|
this.app.workspace.trigger("dice-roller:rendered-result", roller.result);
|
|
}));
|
|
this.addCommand({
|
|
id: "open-view",
|
|
name: "Open Dice View",
|
|
checkCallback: (checking) => {
|
|
if (!this.view) {
|
|
if (!checking) {
|
|
this.addDiceView();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: "reroll",
|
|
name: "Re-roll Dice",
|
|
checkCallback: (checking) => {
|
|
const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView);
|
|
if (view && view.getMode() === "preview" && this.fileMap.has(view.file)) {
|
|
if (!checking) {
|
|
const dice = this.fileMap.get(view.file);
|
|
dice.forEach((roller) => {
|
|
roller.roll();
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
const ICON_SVG = icon(faDice).html[0];
|
|
(0, import_obsidian8.addIcon)(ICON_DEFINITION, ICON_SVG);
|
|
const COPY_SVG = icon(faCopy).html[0];
|
|
(0, import_obsidian8.addIcon)(COPY_DEFINITION, COPY_SVG);
|
|
this.registerMarkdownPostProcessor(async (el, ctx) => {
|
|
let nodeList = el.querySelectorAll("code");
|
|
if (!nodeList.length)
|
|
return;
|
|
const path = ctx.sourcePath;
|
|
const info = ctx.getSectionInfo(el);
|
|
const lineStart = ctx.getSectionInfo(el)?.lineStart;
|
|
const file = this.app.vault.getAbstractFileByPath(ctx.sourcePath);
|
|
if (!file || !(file instanceof import_obsidian8.TFile))
|
|
return;
|
|
const toPersist = {};
|
|
for (let index = 0; index < nodeList.length; index++) {
|
|
const node = nodeList.item(index);
|
|
if (/^dice\-mod:\s*([\s\S]+)\s*?/.test(node.innerText) && info) {
|
|
try {
|
|
let [full, content] = node.innerText.match(/^dice\-mod:\s*([\s\S]+)\s*?/);
|
|
let showFormula = this.data.displayFormulaForMod;
|
|
if (content.includes("|noform")) {
|
|
showFormula = false;
|
|
}
|
|
content = content.replace("|noform", "");
|
|
const roller = this.getRoller(content, ctx.sourcePath);
|
|
roller.on("new-result", async () => {
|
|
const fileContent = (await this.app.vault.cachedRead(file)).split("\n");
|
|
let splitContent = fileContent.slice(info.lineStart, info.lineEnd + 1);
|
|
const replacer = roller.replacer;
|
|
if (!replacer) {
|
|
new import_obsidian8.Notice("Dice Roller: There was an issue modifying the file.");
|
|
return;
|
|
}
|
|
const rep = showFormula ? `${roller.inlineText} **${replacer}**` : `${replacer}`;
|
|
splitContent = splitContent.join("\n").replace(`\`${full}\``, rep).split("\n");
|
|
fileContent.splice(info.lineStart, info.lineEnd - info.lineStart + 1, ...splitContent);
|
|
await this.app.vault.modify(file, fileContent.join("\n"));
|
|
});
|
|
await roller.roll();
|
|
continue;
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
if (!/^dice(?:\+|\-|\-mod)?:\s*([\s\S]+)\s*?/.test(node.innerText))
|
|
continue;
|
|
try {
|
|
let [, content] = node.innerText.match(/^dice(?:\+|\-|\-mod)?:\s*([\s\S]+)\s*?/);
|
|
const roller = this.getRoller(content, ctx.sourcePath);
|
|
const load = async () => {
|
|
await roller.roll();
|
|
if (this.data.persistResults && !/dice\-/.test(node.innerText) || /dice\+/.test(node.innerText)) {
|
|
this.persistingFiles.add(ctx.sourcePath);
|
|
toPersist[index] = roller;
|
|
roller.save = true;
|
|
const result = this.data.results?.[path]?.[lineStart]?.[index] ?? null;
|
|
if (result) {
|
|
await roller.applyResult(result);
|
|
}
|
|
}
|
|
node.replaceWith(roller.containerEl);
|
|
};
|
|
if (roller.loaded) {
|
|
await load();
|
|
} else {
|
|
roller.on("loaded", async () => {
|
|
await load();
|
|
});
|
|
}
|
|
if (!this.fileMap.has(file)) {
|
|
this.fileMap.set(file, []);
|
|
}
|
|
this.fileMap.set(file, [
|
|
...this.fileMap.get(file),
|
|
roller
|
|
]);
|
|
const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView);
|
|
if (view && this.fileMap.has(file) && this.fileMap.get(file).length === 1) {
|
|
const self = this;
|
|
let unregisterOnUnloadFile = around(view, {
|
|
onUnloadFile: function(next) {
|
|
return async function(unloaded) {
|
|
if (unloaded == file) {
|
|
self.fileMap.delete(file);
|
|
unregisterOnUnloadFile();
|
|
}
|
|
return await next.call(this, unloaded);
|
|
};
|
|
}
|
|
});
|
|
view.register(unregisterOnUnloadFile);
|
|
view.register(() => this.fileMap.delete(file));
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
new import_obsidian8.Notice(`There was an error parsing the dice string: ${node.innerText}.
|
|
|
|
${e}`, 5e3);
|
|
continue;
|
|
}
|
|
}
|
|
if (path in this.data.results) {
|
|
this.data.results[path][lineStart] = {};
|
|
}
|
|
if (Object.entries(toPersist).length) {
|
|
const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView);
|
|
if (view) {
|
|
const self = this;
|
|
let unregisterOnUnloadFile = around(view, {
|
|
onUnloadFile: function(next) {
|
|
return async function(unloaded) {
|
|
if (unloaded = file) {
|
|
if (self.persistingFiles.has(path)) {
|
|
self.persistingFiles.delete(path);
|
|
self.data.results[path] = {};
|
|
}
|
|
for (let index in toPersist) {
|
|
const roller = toPersist[index];
|
|
const newLineStart = ctx.getSectionInfo(el)?.lineStart;
|
|
if (newLineStart == null)
|
|
continue;
|
|
const result = {
|
|
[newLineStart]: {
|
|
...self.data.results[path]?.[newLineStart] ?? {},
|
|
[index]: roller.toResult()
|
|
}
|
|
};
|
|
self.data.results[path] = {
|
|
...self.data.results[path] ?? {},
|
|
...result
|
|
};
|
|
await self.saveSettings();
|
|
}
|
|
}
|
|
unregisterOnUnloadFile();
|
|
return await next.call(this, unloaded);
|
|
};
|
|
}
|
|
});
|
|
view.register(unregisterOnUnloadFile);
|
|
view.register(async () => {
|
|
if (this.persistingFiles.has(path)) {
|
|
this.persistingFiles.delete(path);
|
|
this.data.results[path] = {};
|
|
}
|
|
for (let index in toPersist) {
|
|
const roller = toPersist[index];
|
|
const newLineStart = ctx.getSectionInfo(el)?.lineStart;
|
|
if (newLineStart == null)
|
|
continue;
|
|
const result = {
|
|
[newLineStart]: {
|
|
...this.data.results[path]?.[newLineStart] ?? {},
|
|
[index]: roller.toResult()
|
|
}
|
|
};
|
|
this.data.results[path] = {
|
|
...this.data.results[path] ?? {},
|
|
...result
|
|
};
|
|
await this.saveSettings();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
this.lexer = new import_lex.default();
|
|
this.addLexerRules();
|
|
var exponent = {
|
|
precedence: 3,
|
|
associativity: "right"
|
|
};
|
|
var factor = {
|
|
precedence: 2,
|
|
associativity: "left"
|
|
};
|
|
var term = {
|
|
precedence: 1,
|
|
associativity: "left"
|
|
};
|
|
this.parser = new Parser({
|
|
"+": term,
|
|
"-": term,
|
|
"*": factor,
|
|
"/": factor,
|
|
"^": exponent
|
|
});
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
await this.registerDataviewInlineFields();
|
|
});
|
|
}
|
|
async parseDice(content, source) {
|
|
const roller = this.getRoller(content, source);
|
|
return { result: await roller.roll(), roller };
|
|
}
|
|
clearEmpties(o) {
|
|
for (var k in o) {
|
|
if (!o[k] || typeof o[k] !== "object") {
|
|
continue;
|
|
}
|
|
this.clearEmpties(o[k]);
|
|
if (Object.keys(o[k]).length === 0) {
|
|
delete o[k];
|
|
}
|
|
}
|
|
}
|
|
async saveSettings() {
|
|
this.clearEmpties(this.data.results);
|
|
await this.saveData(this.data);
|
|
}
|
|
get dataview_regex() {
|
|
const fields = Array.from(this.inline.keys());
|
|
if (!fields.length)
|
|
return null;
|
|
return new RegExp(`(${fields.join("|")})`, "g");
|
|
}
|
|
getRoller(content, source, icon2 = this.data.showDice) {
|
|
let showDice = content.includes("|nodice") ? false : icon2;
|
|
content = (0, import_he.decode)(content.replace("|nodice", "").replace("\\|", "|"));
|
|
if (content in this.data.formulas) {
|
|
content = this.data.formulas[content];
|
|
}
|
|
const lexemes = this.parse(content);
|
|
const type = this.getTypeFromLexemes(lexemes);
|
|
switch (type) {
|
|
case "dice": {
|
|
return new StackRoller(this, content, lexemes, showDice);
|
|
}
|
|
case "table": {
|
|
return new TableRoller(this, content, lexemes[0], source, showDice);
|
|
}
|
|
case "section": {
|
|
return new SectionRoller(this, content, lexemes[0], source, showDice);
|
|
}
|
|
case "tag": {
|
|
if (!this.canUseDataview) {
|
|
throw new Error("Tags are only supported with the Dataview plugin installed.");
|
|
}
|
|
return new TagRoller(this, content, lexemes[0], source, showDice);
|
|
}
|
|
case "link": {
|
|
return new LinkRoller(this, content, lexemes[0], source, showDice);
|
|
}
|
|
case "line": {
|
|
return new LineRoller(this, content, lexemes[0], source, showDice);
|
|
}
|
|
}
|
|
}
|
|
getTypeFromLexemes(lexemes) {
|
|
if (lexemes.some(({ type }) => type === "table")) {
|
|
return "table";
|
|
}
|
|
if (lexemes.some(({ type }) => type === "section")) {
|
|
return "section";
|
|
}
|
|
if (lexemes.some(({ type }) => type === "tag")) {
|
|
return "tag";
|
|
}
|
|
if (lexemes.some(({ type }) => type === "link")) {
|
|
return "link";
|
|
}
|
|
if (lexemes.some(({ type }) => type === "line")) {
|
|
return "line";
|
|
}
|
|
return "dice";
|
|
}
|
|
addLexerRules() {
|
|
this.lexer.addRule(/\s+/, function() {
|
|
});
|
|
this.lexer.addRule(/[{}]+/, function() {
|
|
});
|
|
this.lexer.addRule(TABLE_REGEX, function(lexeme) {
|
|
return {
|
|
type: "table",
|
|
data: lexeme,
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(SECTION_REGEX, function(lexeme) {
|
|
const { groups } = lexeme.match(SECTION_REGEX);
|
|
let type = "section";
|
|
if (groups.types === "line") {
|
|
type = "line";
|
|
}
|
|
return {
|
|
type,
|
|
data: lexeme,
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(TAG_REGEX, (lexeme) => {
|
|
const { groups } = lexeme.match(TAG_REGEX);
|
|
let type = "tag";
|
|
if (groups.types === "link" || this.data.rollLinksForTags && !groups.types?.length) {
|
|
type = "link";
|
|
}
|
|
return {
|
|
type,
|
|
data: lexeme,
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(OMITTED_REGEX, (lexeme) => {
|
|
const {
|
|
roll = this.data.defaultRoll,
|
|
faces = this.data.defaultFace,
|
|
conditional
|
|
} = lexeme.match(OMITTED_REGEX).groups;
|
|
let conditionals = [];
|
|
if (conditional) {
|
|
let matches = conditional.matchAll(CONDITIONAL_REGEX);
|
|
if (matches) {
|
|
for (let match of matches) {
|
|
if (!match)
|
|
continue;
|
|
const { comparer, operator } = match.groups;
|
|
conditionals.push({
|
|
comparer: Number(comparer),
|
|
operator
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
type: "dice",
|
|
data: `${roll}d${faces}`,
|
|
original: lexeme,
|
|
conditionals
|
|
};
|
|
});
|
|
this.lexer.addRule(/\d+/, function(lexeme) {
|
|
return {
|
|
type: "dice",
|
|
data: lexeme,
|
|
original: lexeme,
|
|
conditionals: []
|
|
};
|
|
});
|
|
this.lexer.addRule(MATH_REGEX, function(lexeme) {
|
|
return {
|
|
type: "math",
|
|
data: lexeme,
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/1[Dd]S/, function(lexeme) {
|
|
const [, dice] = lexeme.match(/1[Dd]S/) ?? [, "1"];
|
|
return {
|
|
type: "stunt",
|
|
data: dice,
|
|
original: lexeme,
|
|
conditionals: []
|
|
};
|
|
});
|
|
this.lexer.addRule(/\d+[Dd]\d+%/, function(lexeme) {
|
|
return {
|
|
type: "%",
|
|
data: lexeme.replace(/^\D+/g, ""),
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/kh?(?!:l)(\d*)/, function(lexeme) {
|
|
return {
|
|
type: "kh",
|
|
data: lexeme.replace(/^\D+/g, ""),
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/dl?(?!:h)\d*/, function(lexeme) {
|
|
return {
|
|
type: "dl",
|
|
data: lexeme.replace(/^\D+/g, ""),
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/kl\d*/, function(lexeme) {
|
|
return {
|
|
type: "kl",
|
|
data: lexeme.replace(/^\D+/g, ""),
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/dh\d*/, function(lexeme) {
|
|
return {
|
|
type: "dh",
|
|
data: lexeme.replace(/^\D+/g, ""),
|
|
original: lexeme,
|
|
conditionals: null
|
|
};
|
|
});
|
|
this.lexer.addRule(/!!(i|\d+)?(?:(!?=|=!|>=?|<=?)(-?\d+))*/, function(lexeme) {
|
|
let [, data = `1`] = lexeme.match(/!!(i|\d+)?(?:(!?=|=!|>=?|<=?)(-?\d+))*/), conditionals = [];
|
|
if (/(?:(!?=|=!|>=?|<=?)(-?\d+))+/.test(lexeme)) {
|
|
for (const [, operator, comparer] of lexeme.matchAll(/(?:(!?=|=!|>=?|<=?)(-?\d+))/g)) {
|
|
conditionals.push({
|
|
operator,
|
|
comparer: Number(comparer)
|
|
});
|
|
}
|
|
}
|
|
if (/!!i/.test(lexeme)) {
|
|
data = `100`;
|
|
}
|
|
return {
|
|
type: "!!",
|
|
data,
|
|
original: lexeme,
|
|
conditionals
|
|
};
|
|
});
|
|
this.lexer.addRule(/!(i|\d+)?(?:(!?=|=!?|>=?|<=?)(-?\d+))*/, function(lexeme) {
|
|
let [, data = `1`] = lexeme.match(/!(i|\d+)?(?:(!?=|=!?|>=?|<=?)(-?\d+))*/), conditionals = [];
|
|
if (/(?:(!?=|=!|>=?|<=?)(\d+))+/.test(lexeme)) {
|
|
for (const [, operator, comparer] of lexeme.matchAll(/(?:(!?=|=!?|>=?|<=?)(-?\d+))/g)) {
|
|
conditionals.push({
|
|
operator,
|
|
comparer: Number(comparer)
|
|
});
|
|
}
|
|
}
|
|
if (/!i/.test(lexeme)) {
|
|
data = `100`;
|
|
}
|
|
return {
|
|
type: "!",
|
|
data,
|
|
original: lexeme,
|
|
conditionals
|
|
};
|
|
});
|
|
this.lexer.addRule(/r(i|\d+)?(?:(!?=|=!|>=?|<=?)(-?\d+))*/, function(lexeme) {
|
|
let [, data = `1`] = lexeme.match(/r(i|\d+)?(?:(!?=|=!|>=?|<=?)(-?\d+))*/), conditionals = [];
|
|
if (/(?:(!?={1,2}|>=?|<=?)(-?\d+))+/.test(lexeme)) {
|
|
for (const [, operator, comparer] of lexeme.matchAll(/(?:(!?=|=!|>=?|<=?)(-?\d+))/g)) {
|
|
conditionals.push({
|
|
operator,
|
|
comparer: Number(comparer)
|
|
});
|
|
}
|
|
}
|
|
if (/ri/.test(lexeme)) {
|
|
data = `100`;
|
|
}
|
|
return {
|
|
type: "r",
|
|
data,
|
|
original: lexeme,
|
|
conditionals
|
|
};
|
|
});
|
|
const self = this;
|
|
this.lexer.addRule(/[A-Za-z][A-Za-z0-9_]+/, function(lexeme) {
|
|
if (self.inline.has(lexeme.trim())) {
|
|
return {
|
|
type: "dice",
|
|
data: `${self.inline.get(lexeme.trim())}`,
|
|
original: lexeme,
|
|
conditionals: []
|
|
};
|
|
}
|
|
});
|
|
}
|
|
onunload() {
|
|
console.log("DiceRoller unloaded");
|
|
this.app.workspace.getLeavesOfType(VIEW_TYPE).forEach((leaf) => leaf.detach());
|
|
if ("__THREE__" in window) {
|
|
delete window.__THREE__;
|
|
}
|
|
this.renderer.unload();
|
|
this.app.workspace.trigger("dice-roller:unload");
|
|
}
|
|
parse(input) {
|
|
this.lexer.setInput(input);
|
|
var tokens = [], token;
|
|
while (token = this.tryLex()) {
|
|
tokens.push(token);
|
|
}
|
|
return this.parser.parse(tokens);
|
|
}
|
|
tryLex() {
|
|
try {
|
|
return this.lexer.lex();
|
|
} catch (e) {
|
|
}
|
|
}
|
|
};
|
|
/*!
|
|
* Font Awesome Free 5.15.3 by @fontawesome - https://fontawesome.com
|
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
*/
|
|
/*!
|
|
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
|
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
*/
|
|
/*! https://mths.be/he v1.2.0 by @mathias | MIT license */
|
|
/**
|
|
* @license
|
|
* Copyright 2010-2021 Three.js Authors
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|